Clp-1.15.10/0000755000076600007660000000000012377556130011064 5ustar coincoinClp-1.15.10/config.sub0000755000076600007660000007772611405215425013060 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: Clp-1.15.10/AUTHORS0000644000076600007660000000002010430454205012110 0ustar coincoinForrest, John J.Clp-1.15.10/doxydoc/0000755000076600007660000000000012377556130012535 5ustar coincoinClp-1.15.10/doxydoc/doxygen.conf.in0000644000076600007660000017377512244006740015500 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 Clp-1.15.10/doc/0000755000076600007660000000000012377556130011631 5ustar coincoinClp-1.15.10/doc/basicmodelclasses.xml0000644000076600007660000006330610430454205016027 0ustar coincoin Basic Model Classes
Hierarchy The basic CLP model class hierarchy is simple. The top three levels of the hierarchy are depicted in the figure below. The first two levels (i.e. ClpModel, ClpSimplex, ClpInterior) contain all the problem data which define a model (that is, a problem instance). The third level contains most of the algorithmic aspects of CLP. There is a fourth level (for models with more general objectives than linear ones), but a description of it is beyond the current scope of this document. Most Simplex users need only concern themselves with the classes ClpModel and ClpSimplex. There are algorithm-specific classes which inherit from ClpSimplex (e.g. ClpSimplexDual and ClpSimplexPrimal), but they have no member data and rarely need be visible to the user. These classes are cast at algorithm time. So, for example, after instantiating an object model of type ClpSimplex, a user only need call model.dual() to invoke the dual simplex method.
First Example Below is our first CLP sample program. It is short enough to present in full (this code can be found in the CLP Samples directory, see ). Most of the remaining examples in this Guide will take the form of small code fragments. minimum.cpp This sample program creates a ClpSimplex model, reads an MPS file, and if there are no errors, solves it using the primal algorithm. The program is easy to follow, but it is not terribly useful: it does not attempt to inspect the results of the solve. There are two main kinds of results: a "status" describing what happened to the model during the solve, and arrays filled with solution values. Both will be addressed in this chapter.
Getting at the Solution It is often the case with CLP that there is more than one way to do something. This is a consequence of CLP's mixed heritage as a child of OSL and a cousin of OSI. Finding the status of a model exemplifies this situation. The OSI way to check for optimality is to call model.isProvenOptimal(). Also available are isProvenPrimalInfeasible(), isProvenDualInfeasible(), isPrimalObjectiveLimitReached(), isDualObjectiveLimitReached(), isIterationLimitReached() or the feared isAbandoned(). Should one prefer the OSL way of doing things, model.status() returns as it would in OSL, so 0 means optimal, 1 means primal infeasible etc. Similarly, to pick up the solution values, one could inhabit the virtuous world of OSI, or the not-quite-so-virtuous world of OSL and "pure" CLP. By this it is meant that const and non-const forms of arrays are used, respectively. It is easier to deal with the non-const versions, so most of the elaborate algorithms in CLP and its Samples use them. Methods for getting solution information Purpose OSI-style (virtuous) CLP-style (less virtuous) Primal column solution const double * getColSolution() double * primalColumnSolution() Dual row solution const double * getRowPrice() double * dualColumnSolution() Primal row solution const double * getRowActivity() double * primalRowSolution() Dual row solution const double * getReducedCost() double * dualColumnSolution() Number of rows in model int getNumRows() int numberRows() Number of columns in model int getNumCols() int numberColumns()
The reader may have noted a preference for "number" over "num" and "column" over "col". This may be a reaction to when one of the authors was young and 5 or 6 letters was the maximum in FORTRAN for any name or to early days with OSL when seven characters were allowed but the first three had to be "ekk"! Using the above-listed functions, our initial example might be continued as follows: Possible extension of minimum.cpp This code sample would pretty-print information about the model's primal and dual solutions. How to additionally print row and column names is illustrated in the defaults.cpp file in the "Samples" directory (the Samples are properly addressed in ). This sample is also useful as it explicitly performs default actions (e.g. it sets the primal feasiblility tolerance value to the default value). The remainder of this chapter will show more of the basic CLP tasks a user might wish to perform. Apart from presolve we will only be looking at actions which can be performed when including the single header file COIN/Clp/include/ClpSimplex.hpp.
Building and Modifying a Model Rather than reading a model from an MPS file we can load a model from arrays in memory. There are various loadProblem methods which are similar to those in OSI. It is easy to add more such methods to CLP if the need arises. We can copy in integer information by copyInIntegerInformation(const char * array) where array is 0 or 1 to say integer and we can drop existing information by deleteIntegerInformation(). There are various ways of changing the size of a model. The simplest is by the use of the method resize(newNumberRows,newNumberColumns) - this will either truncate the model or add "default" rows or columns - a default row has lower bound of -infinity and upper bound of +infinity, while a default column has zero cost, zero lower bound and an upper bound of +infinity. Normally we would use deleteRows, addRows, deleteColumns and addColumns, where the add methods will also add in the elements. A potentially very useful way of modifying a model is strictly a constructor. Given a large model and a list of rows and a list of columns it constructs the model as a subset of the large model. It is possible to change the order of the columns/rows and to duplicate columns/rows. So a list of columns 4,4,1,0 will create a new model where the first two columns are copies of column 4 in original model and the next two are the first two of original model in reverse order. This can be useful to form a model with piecewise linear costs by duplicating columns and then modifying bounds and costs.
Tolerances There are set and get methods for tolerances, for example, double primalTolerance() and setPrimalTolerance(double). Assuming that one has a minimization problem, an individual variable is deemed primal feasible if it is less than the tolerance referred to by these methods below its lower bound and less than it above its upper bound. Similarly for dual tolerances, a variable is deemed to be dual feasible if its reduced cost is greater than minus the tolerance or its distance to the upper bound is less than primal tolerance and the reduced cost is less than plus the tolerance or the distance to lower bound is less than primal tolerance. In short, this is complementarity conditions adadpted for tolerances and simple lower and upper bounds.(Note that the above was stated as for minimization; signs are reversed for maximization.)
Some Useful Set and Get Methods Some Useful Set and Get Methods Method(s) Description setMaximumIterations(int value) int maximumIterations() setMaximumSeconds(double value) double maximumIterations() These methods tell CLP to stop after a given number of iterations or seconds (and returns these values). double objectiveValue() This method returns the objective value. const double * getObjCoefficients() double * objective() These methods return the objective coefficients. const double * getRowLower() double * rowLower() const double * getRowUpper() double * rowUpper() const double * getColLower() double * columnLower() const double * getColUpper() double * columnUpper() These methods give lower and upper bounds on row and column activities. double * infeasibilityRay() double * unboundedRay() If the problem was primal or dual infeasible, these methods will give a pointer to a ray proving infeasibility. CoinPackMatrix * matrix() There are more options as the user has great flexibility in how the problem matrix is stored, but the default matrix class is CoinPackedMatrix (see ). So we have that this method returns a pointer to a CoinPackedMatrix which can be further manipulated. CoinBigIndex getNumElements() CoinBigIndex is a typedef which in most cases is the same as int. Returns the number of elements in the problem matrix. void setOptimizationDirection(double value) double optimizationDirection() These methods set and get the objective sense. The parameter value should be +1 to minimize, -1 to maximize, and 0 to ignore.
Simplex-specific Methods Some of the most commonly-used methods when working with Simplex are listed in the table below. Common Simplex-specific methods Method(s) Description primal(int mode=0) This applies the primal algorithm. If mode is set to the default of 0, then the method uses the status variables to determine basis and solution. If mode is 1 then the method does a values pass so variables not in basis are given their current values and one pass of variables is done to clean up the basis with an equal or better objective value. dual(int mode=0) This applies the dual algorithm. if mode is set to the default of 0, then the method uses the status variables to determine basis and solution. If mode is 1 then the method uses input duals and does a values pass so one pass of basic variables is done to clean up the duals with an equal or better objective value. scaling(int mode=1) This method toggles scaling on (mode set to 1) and off (mode set to 0). int crash(double gap,int mode) This method attemps to improve on an all slack basis. For dual this will move variables to the dual feasible bound if the gap between bounds is less than gap. Setting mode to 0 guesses which algorithm is better, while a value of 1 or 2 will result in more work being done. The return code is 0 if the basis was not slacks in first case, it is negative if dual is preferred or positive if primal. ±1 means an all slack basis seemed best, while ±2 means some work was done. perturb(int mode) This method toggles perturbation on (mode set to 1) and off (mode set to 0). It should be considered a work in progress, although on some problems it gives very good results. factorizationFrequency() setFactorizationFrequency(int value) These are "get" and "set" methods for the basis matrix factorization frequency. The default is to refactor every 200 iterations, but it may make more sense to use something such as 100 + the number of rows divided by 50. dualBound() setDualBound(double value) These are "get" and "set" methods for the "dual bound". The CLP dual algorithm declares all problems to be dual feasible by putting non-basic variables to correct bounds for the reduced cost. If the gap between the bounds is too big then it pretends the gap is only the value specified by this set method. In essence, this gives a composite dual rather than a pure Phase I- Phase II method. infeasibilityCost() setInfeasibilityCost(double value) These are the primal analogs to the "dual bound" methods. numberPrimalInfeasibilities() sumPrimalInfeasibilities() After a solve, there may be infeasibilities. These methods serve to check for said infeasibilities. One could check the solution explicitly as well. For a code fragement illustrating this, see .
Presolve The header file for the use of CLP's presolve functionality is COIN/Clp/include/Presolve.hpp. The sample program below illustrates some of the possibilities offered by CLP's presolve: Presolve code fragment #include "ClpSimplex.hpp" #include "ClpPresolve.hpp" int main (int argc, const char *argv[]) { ClpSimplex model; model.readMps("../../Mps/Sample/p0033.mps"); // initialized by readMps or whatever ClpPresolve presolveInfo; ClpSimplex * presolvedModel = presolveInfo.presolvedModel(model); // at this point we have original model and a new model. The information // on the operations done is in presolveInfo if (presolvedModel) { // was not found to be infeasible - so lets solve // if presolvedModel was NULL then it was primal infeasible and ... presolvedModel->dual(); // or whatever else we wish to do presolveInfo.postsolve(true); // the true updates status arrays in original /* If the presolved model was optimal then so should the original be. We can use checkSolution and test feasibility */ model.checkSolution(); if (model.numberDualInfeasibilities()|| model.numberPrimalInfeasibilities()) printf("%g dual %g(%d) Primal %g(%d)\n", model.objectiveValue(), model.sumDualInfeasibilities(), model.numberDualInfeasibilities(), model.sumPrimalInfeasibilities(), model.numberPrimalInfeasibilities()); // Due to tolerances we can not guarantee that so you may wish to throw in model.primal(1); } } Presolve has a few more options which can be found in the header file, for example whether to treat as an integer problem or whether to keep row and column names.
Status Array The astute reader may have noticed that the status array has been mentioned once or twice. The beginning user will not need to look at it Nevertheless, for completeness the status of a variable can be found and set as shown below. The possible state of a variable are listed in the following table (each may have to be preceded by ClpSimplex::): Possible states of a variable StatusStatus is an enumeration. Description basic In basis isFree Not in basis, has infinite bounds isFixed Not in basis, bounds are equal atUpperBound At upper bound, not in basis atLowerBound At lower bound, not in basis superBasic Between bounds, but not basic or free
To get or set the status of a variable is a simple task: // Get row status... Status status=model.getRowStatus(sequenceNumber) // ... or get column status. Status status=model.getColumnStatus(sequenceNumber) // Set row status to basic (for example)... model.setRowStatus(sequenceNumber,ClpSimplex::basic) // ... or column status to basic. model.setColumnStatus(sequenceNumber,ClpSimplex::basic)
Clp-1.15.10/doc/moresamples.xml0000644000076600007660000003664110430454205014700 0ustar coincoin More Samples
CLP's Samples Directory The CLP dsitribution includes a number of .cpp sample files. Users are encouraged to use them as starting points for their own CLP projects. The files can be found in the &clpsamplesdir; directory. For the latest information on compiling and running these samples, please see the file &clpsamplesdir;INSTALL. 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 CLP "Hello, world" program. It reads a problem from an MPS file, and solves the problem. [More...] &defaultscpp; This is one of the simpler driver programs available. It sets tolerances to defaults and is a good place to find straightforward uses of "set" and "get" methods. It also prints out full MPS-like solutions. [More...] &drivercpp; 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 CLP's presolve functionality. [More...] &networkcpp; This shows the use of non-standard matrices and how to load a problem without the use of MPS files. [More...] &testbarriercpp; This is a basic driver file for the barrier method of CLP, similar to &minimumcpp;. The barrier method is not currently addressed in this guide. [More...]
Advanced Samples Source file        Description &driver2cpp; This sample, in addition to some tasks common to other samples, does some advanced message handling and presolve. &dualcutscpp; This sample implements a method of treating a problem as a collection of cuts. &decomposecpp; This does full Dantzig-Wolfe decomposition. It illustrates the use of many models, adding columns, et cetera. &sprintcpp; This solves a long, thin problem by solving smaller subsets. It is a simplified version of work done by one of the authors on aircrew scheduling problems. It shows the use of two models and their synchronization. A more general version can be found in COIN/Clp/ClpSolve.cpp &sprint2cpp; This is similar to sprint.cpp but is designed for solving large problems with little choice. The idea is that if relatively few variables are fixed, presolve can greatly reduce the problem size so that a series of solves can get close to the optimal solution much faster than would a naïve solve of the full problem.
The remaining Samples listed here are considered unsupported in that they are of a more esoteric nature and are sometimes contributed as a result of an individual's request. The are to be found in &clpsamplesdir;Contributed. Unsupported Samples Source file        Description &testbasiscpp; This sample takes a problem, changes any inequality constraints to equality constraints, solves the problem, and creates the optimal basis. &testgubcpp; This sample illustrates the use of the GUB ("Generalized Upper Bound") technique. &ekkcpp; This sample can be used to compare CLP and OSL. It uses an additional file in the Samples directory, ekk_interface.cpp. These sample files are not likely to be interesting to new CLP users who do not have experience with OSL. &hellocpp; This sample creates a text-based picture of a matrix on screen (limited to an 80x80 matrix). It's not terribly useful but it does illustrate one way to step through the elements of a matrix. &piececpp; This sample takes a matrix read in by CoinMpsIo (can be used to read in MPS files without a solver), deletes every second column and solves the resulting problem. &usevolumecpp; The Volume Algorithm is another solver available as part of the COIN-OR distribution. This sample shows how to use the Volume Algorithm with CLP.
minimum.cpp This sample is examined in more detail in .
defaults.cpp This sample begins by reading an MPS file. The default MPS file is COIN/Mps/Sample/p0033.mps; this can be over-riden by a command-line specification of a (path and) file name). The sample then sets the pivot algorithm to be exact devex. It "gets" the default infeasibility cost and "sets" it to that value (and prints it to standard out). This sort of getting and setting of various parameters constitutes a common theme in this sample, with the purpose of illustrating usage of some of the more common get and set methods available in CLP. At this point the model is solved by the primal method. A sequence of sets, gets and prints is then followed by a number of calls to methods which give specific information about the status of the problem (for example, the code checks that the current solution has been proven to be optimal by assert(model.isProvenOptimal())). Next, a copy of the original model is made. More sets and gets are performed to demonstrate the use of additional options (including the setting of the default message handling as well as changing of the "log level" (amount of output)). The model is solved again a number of times between changes of the optimization direction (i.e. changing from min to max or vice versa). The remaining lines of this sample serve to display solution and problem information in much the same way as is done in driver.cpp.
driver.cpp This sample begins by reading an MPS file. The default MPS file is COIN/Mps/Sample/p0033.mps; this can be over-riden by a command-line specification of a (path and) file name). A second command-line argument can specify that either the "primal" or "dual" method (or even the "barrier", see below) should be used by CLP. Once the problem has been read, there are two options for how to solve it, one of which must be chosen at compile-time (STYLE1 being defined or not determines this choice). The second manner is more flexible and involves more specific directions being given to CLP, including the ability to specify that the barrier method should be used. At this point in the sample, the problem is solved by CLP, and some basic ouput is generated. If more output is desired, at compile-time, an exit(0) statement must either be removed or commented. There are two levels of additional output, the first of which is suppressed by a #if 0 directive which may be modified at compile-time if desired. This first level of output only involves non-zero columns, whereas the second provides additional information.
network.cpp This handy sample reads a network problem generated by netgen, converts it to an LP using CLP's network matrix type, and solves. This entirely avoids the use of an MPS file, as the LP is built in memory from the network data file created by netgen. Also, the factorization frequency is changed, and the problem is solved more than once (demonstrating the change of optimization sense as well as switching from dual to primal methods).
testBarrier.cpp This straightfoward sample begins by reading a problem from an MPS file. It then chooses a Cholesky factorization and solves the problem using the predictor corrector barrier method. It then copies the problem and performs a crossover to a simplex solution in the new copy.
dualCuts.cpp This sample begins with only the equality constraints of a problem. The inequalities are considered to be part of a pool of available cuts in much the same way as is done in integer programming. However, in this case, the cuts are not "generated", they are simply the inequalities of the problem.
decompose.cpp More on this sample coming soon!
driver2.cpp More on this sample coming soon!
Common CLP Tasks in the Samples Below is a listing of a number of common CLP tasks, such as loading a problem from an MPS file, matched with a list of each Sample file which illustrates the performance of a given task. Contents of the Samples directory CLP Task(s) Method(s) Sample(s) Read problem from MPS file int readMps(const char *filename) &defaultscpp;, &drivercpp;, &minimumcpp; Solve by primal method int primal() &drivercpp; Choose pivot rule void setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot &choice) void setDualRowPivotAlgorithm(ClpDualRowPivot &choice) &defaultscpp; Get/set infeasibility cost void setInfeasibilityCost(double value) void setInfeasibilityCost(double value) &defaultscpp; Get string/"double"/integer information bool getStrParam(ClpStrParam key, std::string &value) const bool getDblParam(ClpDblParam key, double &value) const bool getIntParam (ClpIntParam key, int &value) const &defaultscpp; Set maximum number of iterations void setMaximumIterations(int value) &defaultscpp; Check solution status int status() const bool isAbandoned() const bool isProvenOptimal() const bool isProvenPrimalInfeasible() const bool isProvenDualInfeasible() const bool isPrimalObjectiveLimitReached() const bool isDualObjectiveLimitReached() const bool isIterationLimitReached() const
Clp-1.15.10/doc/doxygen.xml0000644000076600007660000000121410430454205014012 0ustar coincoin Doxygen There is Doxygen content for CLP available online at http://www.coin-or.org/Doxygen/Clp/index.html. A local version of the Doxygen content can be generated from the CLP distribution. To do so, in the directory COIN/Clp, enter make doc. The Doxygen content will be created in the directory COIN/Clp/Doc/html. The same can be done for the COIN core, from the COIN/Coin directory. Clp-1.15.10/doc/legal.xml0000644000076600007660000000164611507203075013435 0ustar coincoin 2004 IBM Coportation CLP 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. Clp-1.15.10/doc/faqcontent.xml0000644000076600007660000002170111510660312014500 0ustar coincoin What is CLP? (DN 08/27/04) The COIN-OR LP code is designed to be a high quality Simplex code provided under the terms of the Eclipse Public License. CLP is written in C++, and is primarily intended to be used as a callable library (though a rudimentary stand-alone executable exists). The first release was version .90. The current release is version 1.00.2. What are some of the features of CLP? (DN 08/27/04) CLP includes primal and dual Simplex solvers. Both dual and primal algorithms can use matrix storage methods provided by the user (0-1 and network matrices are already supported in addition to the default sparse matrix). The dual algorithm has Dantzig and Steepest edge row pivot choices; new ones may be provided by the user. The same is true for the column pivot choice of the primal algorithm. The primal can also use a non linear cost which should work for piecewise linear convex functions. CLP also includes a barrier method for solving LPs. How do I obtain and install CLP? (DN 08/27/04) Please see the COIN-OR FAQ for details on how to obtain and install COIN-OR modules. Is CLP reliable? (DN 09/07/04) CLP has been tested on many problems of up to 1.5 million constraints and has shown itself as reliable as OSL. It is also being tested in the context of developing CBC ("Coin Branch and Cut", which is used to solve integer programs); it is now considered reliable enough to be at version 1.0. On which platforms does CLP run? (DN 08/27/04) CLP compiles and has been tested (to varying degrees) on the following platforms: Linux using g++ version 3.1.1 (or later) Windows using Microsoft Visual C++ 6 Windows using cygwin AIX using xIC (not supported in the current Makefile) Is there any documentation for CLP? (DN 09/16/04) An early release of a User Guide is available on the CLP documentation webpage. Also available is a list of CLP class descriptions generated by Doxygen. Is CLP as fast as OSL? (DN 08/27/04) CLP uses sparse matrix techniques designed for very large problems. The design criteria were for it not to be too slow. Some speed has been sacrificed to make the code less opaque OSL (not difficult!). When will version 1.0 of CLP be available? (DN 08/27/04) Version 1.0 was released in time for the 2004 INFORMS Annual Meeting (24-27 October, 2004). The barrier method sounds interesting, what are some of the details? (DN 08/30/04) The CLP barrier method solves convex QPs as well as LPs. In general, a barrier method requires implementation of the algorithm, as well as a fast Cholesky factorization. CLP provides the algorithm, and is expected to have a reasonable factorization implementation by the release of CLP version 1.0. However, the sparse factorization requires a good ordering algorithm, which the user is expected to provide (perhaps a better factorization code as well). Which Cholesky factorizations codes are supported by CLP's barrier method? (DN 09/16/04) The Cholesky interface is flexible enough so that a variety of Cholesky ordering and factorization codes can be used. Interfaces are provided to each of the following: Anshul Gupta's WSSMP parallel enabled ordering and factorization code Sivan Toledo's TAUCS parallel enabled factorization code (the package includes third party ordering codes) University of Florida's Approximate Minimum Degree (AMD) ordering code (the CLP native factorization code is used with this ordering code) CLP native code: very weak ordering but competitive nonparallel factorization Fast dense factorization When will CLP have a good native ordering? (DN 09/16/04) The best outcome would be to have an existing ordering code available as part of the COIN distribution under the EPL. However, if this is not possible, the native ordering will be made respectable. Is the barrier code as mature as the simplex code? (DN 09/16/04) The simplex code has been exposed to user testing for more than a year and and the principal author, John Forrest, knows more about simplex algorithms than interior point algorithms, so the answer is "no". However, it performs well on test sets and seems to be more reliable than some commercially available codes (including OSL). Which algorithm should I use for quadratic programming and should I keep an eye open for any issues? (DN 09/16/04) The interior point algorithm for quadratic programming is much more elegant and normally much faster than the quadratic simplex code. Caution is suggested with the presolve as not all bugs have been found and squashed when a quadratic objective is used. One may wish to switch off the crossover to a basic feasible solution as the simplex code can be slow. The sequential linear code is useful as a "crash" to the simplex code; its convergence is poor but, say, 100 iterations could set up the problem well for the simplex code. What can the community do to help? (DN 09/09/04) A lot! A good first step would be to join the CLP mailing lists. Some other possibilities: Comment on the design Break the code, or better yet, mend it. Add non-English language support in your own favo(u)rite language. Improve the CLP executable. In particular it would be nice to be able to link the executable's online help system with the existing CLP Samples (e.g. entering presol??? would give the user references to all CLP Sample files which use presolve). Implement a dual Simplex method for QPs (quadratic programs) Implement a parametric Simplex method Implement a true network Simplex method (network matrix and factorization are already in place, but the method is not) Fill the holes in the barrier method mentioned above. Clp-1.15.10/doc/revhist.xml0000644000076600007660000000173210430454205014026 0ustar coincoin Revision History 0.4 18 Oct 2004 DdlN Second official release, including some corrections, clarifications, and several improvements (better treatment of clp executable and Samples). 0.3 19 Aug 2004 DdlN Major overhaul, including transition from MS Word to DocBook XML. 0.2 23 Feb 2004 RLH Revisions to make it clearer to the non-author reader. 0.1 Nov 2003 JF First draft Clp-1.15.10/doc/clpuserguide.xml0000644000076600007660000000557510430454205015046 0ustar coincoin defaults.cpp"> driver.cpp"> driver2.cpp"> minimum.cpp"> decompose.cpp"> piece.cpp"> network.cpp"> sprint.cpp"> sprint2.cpp"> ekk.cpp"> hello.cpp"> testBarrier.cpp"> dualCuts.cpp"> testGub.cpp"> testBasis.cpp"> useVolume.cpp"> ]> CLP User Guide &authors; &legal; &intro; &basicmodelclasses; ¬sobasic; &moresamples; &clpexe; &messages; &faq; &doxygen; &revhist; Clp-1.15.10/doc/faq.xml0000644000076600007660000000022410430454205013104 0ustar coincoin FAQ &faqcontent; Clp-1.15.10/doc/intro.xml0000644000076600007660000000321110430454205013467 0ustar coincoin Introduction
Welcome to CLP! The COIN Linear Program code or CLP is an open-source simplex solver written in C++. It is primarily meant to be used as a callable library, but a basic, stand-alone executable version is also available. There are a number of resources available to help new CLP users get started. This document is designed to be used in conjunction with the files in the Samples subdirectory of the main CLP directory (COIN/Clp/Samples). The Samples illustrate how to use CLP and may also serve as useful starting points for user projects. In the rare 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/Clp/include, are the ultimate reference.
Prerequisites CLP is written in C++, so it is expected that users of CLP will be writing C++ programs which use CLP as a library. Thus a working knowledge of C++, including basic object-oriented programming terminology is assumed in this document. In addition, the user should be familiar with the fundamental concepts of Linear Programming.
Clp-1.15.10/doc/Howto/0000755000076600007660000000000012377556130012731 5ustar coincoinClp-1.15.10/doc/Howto/docbook4clp.xml0000644000076600007660000004326410115426415015655 0ustar coincoin
DocBook for Writers of CLP Documentation Davidde la Nuez
Introduction The CLP User Guide is written in DocBook XML. This tutorial serves as an introduction to using DocBook for maintaining the Guide, as well as writing new documentation. There are countless DocBook and XML resources available both in print and online, so this tutorial will be limited in its scope to applying these two technologies to documenting CLP. See to learn more about DocBook and XML.
DocBook? Why DocBook? Why not HTML or LaTeX? Here are a few of the reasons: DocBook and the tools we use to work with it are Open Source. LaTeX is nice for mathematical markup, but DocBook exists for marking-up technical documentation. Basic HTML is easy to learn and use, but it is very clumsy. DocBook does a good job of separating content from presentation (HTML does not do this particularly well, even with the use of CSS), allowing the writer to focus on what really matters, the content. DocBook can transformed into high-quality online and printed output (e.g. HTML and PDF, respectively), while working from a single source. DocBook is very robust, thoroughly documented, and has a strong community behind it. DocBook is a modern though mature standard for documentation of software (or other) projects which is at no risk of obsolescence. The tools needed for creating and manipulating DocBook documents are typically part of existing *nix installations (including Cygwin) so little or no installation of new software is required to use DocBook (editing can be done in any text editor). Many tedious tasks, such as the creation of a table of contents, are handled automatically by a good DocBook configuration.
Getting Ready for DocBook Editing and publishing CLP documentation with DocBook requires that some important tools be installed. It is likely that all or most of these tools are already in place on a typical *nix (e.g. Linux) system. Windows users should strongly consider installing Cygwin, as this tutorial assumes a *nix environment for DocBook development. In fact, the following instructions for installation are for Cygwin and Red Hat Linux, (and should not be altogether different for another *nix system). The necessary Cygwin packages can all be found in the "Doc" section of the categorical view of Cygwin's setup.exe. The user should verify that all of them are selected (because there may not be adequate dependency rules to ensure that all the correct packages are installed). The packages in question are: dockbook-xml42 This is for version 4.2 of DocBook. Future versions will have a slightly different name. docbook-xsl libxml2 libxslt xmlto According to The Selfdocbook (XML Edition), the Red Hat Linux (7.3) packages needed are: sgml-common and xml-common docbook-style-xsl docbook-dtds xmlto The Selfdocbook also lists a few other packages, but they are not necessary for HTML output (this tutorial does not (yet) address how to create output in other formats such as PDF). The last of the packages, xmlto, is a shell script which facilitates the conversion of DocBook documents to HTML and other formats. If all the tools are properly installed, creating an HTML version of this tutorial, for example, is as trivial as typing xmlto html docbook4clp.xml at the command line. But before jumping in to work with DocBook, there are some important issues which need to be addressed.
Need to Know Knowledge of DocBook is like a security clearance: the user is on a need-to-know basis. That is, to start working with DocBook in a properly configured environment, a user needs to know very little, but there is always something more out there to learn. This section addresses a few details of DocBook that the typical user needs to know to get a first DocBook document up and running. Details will be left to the reader to fill-in from other resources (see ). What makes an XML document a DocBook document? It is not difficult to write a "valid" XML document. The following example would constitute a valid XML document: How CLP Won the West In the Beginning There once was a large LP... ]]> This document is not much use, though, without some meaning for the tags in it. The DocBook DTD is what gives a document meaning. The following example works better, and constitutes a valid DocBook document: How CLP Won the West In the Beginning There once was a large LP... ]]> The only difference is the document type declaration which states the document is meant to adhere to the standard described in the file /usr/share/docbook-xml42/docbookx.dtd (see for where to read more about document type declarations the DocBook DTD). In other words, adding the extra line of code makes this little example a genuine DocBook document. In this case, the declaration uses an absolute path for a particular system (Cygwin). DocBook has an elaborate system for eliminating this lack of elegance. Future versions of this tutorial will address this (see for more on this topic). Suppose the name of the file containing the example above is bookex.xml. To create a single HTML document from this file is as simple as typing one command:
$ xmlto html-nochunks bookex.xml
To create a multi-part HTML version is just as easy:
$ xmlto html bookex.xml
A final and very important DocBook topic is that of "entities". For the purposes of writing CLP documentation (i.e. what follows is a gross simplification), entities are a way of "#include-ing" one document into another, and of using certain special characters which would otherwise confuse the tools used to process DocBook documents. The simplest example of the latter is the < symbol, which is used to begin tags in XML. Rather than putting the character directly into the document text, an entity can be used. Specifically, one would use the string instead. The other use of entities, as suggested above, is to split a document into convenient pieces. This is demonstrated in .
DocBook and CLP, Perfect Together The DocBook XML source of the CLP documentation is available via the COIN CVS repository in the COIN/Clp/Docs directory. The first file of interest is clpuserguide.xml. At the time of this tutorial's writing, the file looked like this: ]> CLP User Manual &authors; &legal; &intro; &basicmodelclasses; ¬sobasic; &moresamples; &clpexe; &messages; &faq; &doxygen; &revhist; ]]> Essentially clpuserguide.xml contains a series of entity declarations which refer to other XML files (e.g. ]]>, which are then included into the main file via use of the entities (e.g. . This allows a neat separation of chapters in the Guide, resulting in more manageable and readable source than would be possible without the use of entities. Neither the names nor the order of the declarations of the entities is particularly important, but it is a good practice to follow the informal convention of naming the entity after the chapter filename, and declaring it in a sensible place with respect to the order of the chapters. Editing a particular chapter of the Guide is a matter of editing a single, reasonably sized file. The addition of a new chapter merely entails the declaration of a new entity and the writing of a short additional line in clpuserguide.xml. Suppose a chapter on the barrier method of CLP was planned (it is, in fact). The chapter could be written in a file named barrier.xml, while an entity was declared and used in clpuserguide.xml. If the barrier chapter was to preceed, say, the chapter on the CLP executable, the new clpuserguide.xml would look like this (with changes emphasized): ]]> <!ENTITY barrier SYSTEM "barrier.xml"> ]> CLP User Manual &authors; &legal; &intro; &basicmodelclasses; ¬sobasic; &moresamples; ]]> &barrier; ]]> The barrier chapter source might look something like this: The CLP Barrier Method
The CLP barrier method can be used ]]>…
]]>
Note the absence of a document type declaration; it is not necessary (and in fact "illegal") in this context because this file is included in the main file via the entity mechanism (only one document type declaration is allowed). With some content in the proposed barrier.xml and the appropriate changes made to clpuserguide.xml, a new HTML version of the Guide could be created in much the same manner as the small book example above was transformed to HTML:
$ xmlto html-nochunks clpuserguide.xml
or for a sectioned version:
$ xmlto html clpuserguide.xml
Most of the chapters and appendices in the Guide exist only to be used in the Guide. There is currently one exception, the FAQ. The FAQ is constructed in a way that allows its inclusion in the Guide as well as on the CLP website (i.e. we have a single source document for our frequently asked questions). The file pointed to by the entity faq, faq.xml, is a wrapper for the file faqcontent.xml (with corresponding entity faqcontent). faqcontent.xml has another wrapper in coin-web/Clp named faqwrapper.xml, which will be addressed elsewhere.
Tips and Suggestions This tutorial, as well as the first DocBook release of the CLP User Guide, were written using the Emacs editor. Most any text editor will do as a DocBook editor, but Emacs has its advantages. First, naturally, Emacs is Open Source. Second, there are Emacs modes tailored for editing XML documents which provide features such as syntax highlighting. One such mode is PGSML, which may be part of a system's default Emacs configuration (this appears to be the case with Cygwin, at the very least). As the size of a DocBook project grows, so does the time it takes to transform it to HTML. If one wishes to simply check the validity of a document rather than wait for the entire HTML generation process to complete, the validating parser called by xmlto is easy enough to use:
$ xmllint --nout --postvalid --xinclude clpuserguide.xml
If there are no errors in the document, the parser will terminate without any explicit output. If there is in fact an error, a (sometimes) helpful error message will be printed by the parser. With DocBook, as is the case with any other computer language, it is easiest to learn by example. The existing examples which are part of CLP are this tutorial, of course, and the User Guide itself. The Selfdocbook (XML Edition) is also an excellent example, as it is a DocBook document which includes its own source. The DocBook community is quite active, so the official mailing lists are highly recommended. See for more information on the lists as well as a number of other helpful resources.
Resources Below is a list of some online resources for learning more about DocBook and XML. DocBook.org: The official site for DocBook: The Definitive Guide (see below). DocBook:The Definitive Guide: The number one reference for DocBook tags. The book is very much oriented toward users of the SGML version of DocBook, but is still the best resource available for CLP documenters. The Selfdocbook (XML Edition) is another very useful reference. It is a self-documenting introduction to DocBook XML (it includes its own source, which makes ita great learning tool). DocBook Wiki Full of useful DocBook links. The Official DocBook homepage: Not terribly useful, but it includes information on the DocBook mailing lists, and a page where one can download DocBook. DocBook FAQ A very handy list of frequently asked quesions (with answers!) about DocBook.
Clp-1.15.10/doc/messages.xml0000644000076600007660000005556310430454205014164 0ustar coincoin Messages Some of the more common messages and codes passed by CLP are listed in the tables below. This is list is not meant to exhaustive. The notation is as for printf from "C": %s is a string %d is an integer %g or %f is a floating point value COIN Messages passed at or above logging level 1 Code Area Text and notes 1 MPSREAD At line %d %s This just prints out NAME line, ROW line, etc 2 MPSREAD Problem %s has %d rows, %d columns and %d elements This gives statistics after reading an MPS file 8 MPSREAD %s read with %d errors This gives error statistics for file 505 PRESOLVE Presolved poblem not optimal, resolve after postsolve This could be because it was not feasible or because of maximum iterations. If this message occurs then consider using primal clean up 506 PRESOLVE Presolve %d (%d) rows, %d (%d) columns and %d (%d) elements The first number is the number after presolve and the number in parentheses is amount of reduction 510 PRESOLVE Presolve is modifying %d integer bounds and re-presolving If presolve determines at the end that an integer variable have its bounds changed then it will repeat the entrire presolve 511 PRESOLVE After Postsolve, objective %g, infeasibilities - dual %g (%d), primal %g (%d) This gives the state after postsolve - this gives the objective value and the sum of dual and primal infeasibilities with the number of infeasibilities in parentheses. Hopefully these should be zero 512 PRESOLVE Presolved model was optimal, full model needs cleaning up If the numbers in previous message (511) were large then maybe we need to know, if small then that's life
CLP Messages passed at or above logging level 1 Code Area Text and notes 0 SIMPLEX Optimal - objective value %g The only message you want to see 1 SIMPLEX Primal infeasible - objective value %g You may need to look at previous messages or use methods. Such as sumPrimalInfeasibilities() to find cause 2 SIMPLEX Dual infeasible - objective value %g You may need to look at previous messages or use methods. Such as sumDualInfeasibilities() to find cause 3 SIMPLEX Stopped - objective value %g The algorithm stopped as requested by the user. 4 SIMPLEX Stopped due to errors - objective value %g Switch on log level 2 to see information on size of elements etc. If they look reasonable then maybe we need to know. 5 SIMPLEX %d Obj %g Primal inf %g (%d) Dual inf %g (%d) At each re-factorization this gives the number of iterations and the value of the objective function. If there are primal infeasibilities then the sum and number are given and similarly for dual infeasibilities. (This is a simplified form of message.) 14 SIMPLEX Perturbing problem by %g % of %g There is more to this message but if the user sees this then s/he has chosen to perturb the problem or the algorithm has decided to do so. If the numbers look too large the user may wish to think again. 19 SIMPLEX %d variables/rows fixed as scaled bounds too close If this occurs look carefully at your input data 24 SIMPLEX Matrix will be packed to eliminate small elements If this occurs the user should look carefully at data. 26 SIMPLEX Matrix will be packed to eliminate %d duplicate elements If this occurs the user should look carefully at data. 28 SIMPLEX Crash put %d variables in basis, %d dual infeasibilities 29 SIMPLEX End of values pass after %d iterations ??? If primal(1) or dual(1) the a sweep through model is made and this signals end of pass.
COIN Messages passed at or above logging level 0 Code Area Text and notes 3001 MPSREAD Illegal value for %s of %g String will be "infinity" if setInfinity passed bad value, or "default integer bound" if setDefaultBound passed bad value. 3002 MPSREAD Bad image at line %d < %s > This gives line number and the offending line 3003 MPSREAD Duplicate objective at line %d < %s > An objective row appears twice in one column 3004 MPSREAD Duplicate row %s at line %d %s The named row appears twice in one column. 3005 MPSREAD No match for row %s at line %d < %s > The named row did not appear in ROWS section. 3006 MPSREAD No match for column at line %d < %s > The named column (in BOUNDS section) did not appear in COLUMNS section. 6001 MPSREAD Unable to open mps input file %s 6002 MPSREAD Unknown image %s at line %d of file %s The Mps reader could not make sense of the image file specified. 6003 MPSREAD Consider the possibility of a compressed file which zlib is unable to read. Some .gz files can not be read by zlib. Using gunzip and then gzip normally cures problem. 6004 MPSREAD EOF on file %s The Mps reader did not find expected section marker. 6005 MPSREAD Returning as too many errors The reader has put out 100 messages and is giving up. 507 PRESOLVE Presolve determined that the problem is infeasible with tolerance of %g If you want you can try with a larger tolerance 508 PRESOLVE Presolve thinks problem is unbounded Perhaps the user should maximize if initially minimizing or vice versa. 509 PRESOLVE Presolve thinks problem is infeasible AND unbounded??? If you get this message we want to know
CLP Messages passed at or above logging level 0 Code Area Text and notes 3002 SIMPLEX Not solving empty problem - %d rows, %d columns and %d elements Test problem size before solving. 6002 SIMPLEX %d bad bound pairs or bad objectives were found Either the value in the objective was too large or a lower bound was greater than an upper bound. 6003 SIMPLEX Matrix has %d large values, first at column %d, row %d is %g Some of the values in matrix are ridiculous. 6004 SIMPLEX Can't get out of loop ...
There are also messages available at log level 2 (the most likely useful relate to scaling), and will be addressed in a future version of this User Guide.
Clp-1.15.10/doc/clpexe.xml0000644000076600007660000002067610430454205013632 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
Clp-1.15.10/doc/authors.xml0000644000076600007660000000150510430454205014025 0ustar coincoin John Forrest jjforre at us dot ibm dot com IBM Research David de la Nuez dmd57 at columbia dot edu Columbia University & IBM Research Robin Lougee-Heimer robinlh at us dot ibm dot com IBM Research Clp-1.15.10/doc/notsobasic.xml0000644000076600007660000002012610430454205014504 0ustar coincoin Not-Quite-So-Basic Model Classes
Pivot Choices In the dual algorithm, any infeasible basic variable may be chosen to leave the basis. Similarly in the primal algorithm, any non-basic variable with a "bad" reduced cost may be chosen to enter the basis. This choice is probably the most important factor in determining the number of iterations it will take to solve a problem. Clp provides a abstract base class for each case and then instances of each. It is relatively simple for an advanced user to create new instances. For the dual method the base class is ClpDualRowPivot. The two existing instances are ClpDualRowDantzig and ClpDualRowSteepest. The Dantzig version implements the "standard" pivot rule: choose the most violated basic variable. It is easily dominated by the Steepest instance which should normally be used. The default is to use un-initialized weights where the initial weight for each basic variable is 1.0. If an all-slack basis is being used then these are the correct weights. To use a version which calculates the weights, create an instance and pass it to ClpSimplex model as in the following code fragment: ClpDualRowSteepest steep(1); // 0 uninitialized, 1 compute weights model.setDualRowPivotAlgorithm(steep); Similarly for the primal method the base class is ClpPrimalColumnPivot. The two existing instances are ClpPrimalColumnDantzig and ClpPrimalColumnSteepest. The Dantzig version implements "standard" pivot rule: choose the most "violated" non-basic variable. It is dominated by the Steepest instance which should normally be used. The default is to use exact Devex where the initial weight for each non-basic variable is 1.0. Unlike for the dual, this is never the same as normal steepest edge. To use a version which does steepest edge create an instance and pass it to ClpSimplex model as in the following code fragment: ClpPrimalColumnSteepest steep(1); // 0 devex, 1 steepest model.setPrimalColumnPivotAlgorithm(steep); The partial pricing scheme (for long, thin problems) currently does not exist. This could be implemented by anyone who is interested.
Matrix Classes The next abstract class of interest is ClpMatrixBase. CLP encapsulates its knowledge of how a matrix is stored in this class. The default instance of this is the ClpPackedMatrix class. This is identical in format to CoinPackedMatrix. Below is a diagram summarizing the hierarchy of the most important matrix classes: The important new methods implemented are for filling a basis, checking validity of elements and faster "times" and "transposeTimes" when the input array is sparse and/or we have a row copy of the matrix. Advanced users should note that not all methods have to be implemented. In particular, scaling need not be implemented and reverseOrderedCopy can return NULL if a row copy does not make sense. In addition to the default class, there are two others at present: ClpPlusMinusOneMatrix and ClpNetworkMatrix. As the name implies, the first one is useful when all elements are ±1. In this case multiplies are not needed and more importantly less memory is used and there are fewer cache misses. A class for a matrix where all elements are +1 would be trivial to create. If there were fewer than 64000 rows one could even store row indices as shorts etc. The use of ClpPlusMinusOneMatrix involves some work as one cannot simply read-in an MPS file. The key is to use loadProblem to pass in a matrix. So if matrix was a CoinPackedMatrix one could do the following: ClpPlusMinusOneMatrix plusMinus(matrix); assert (plusMinus.getIndices()); // would be zero if not +- one model.loadProblem(plusMinus, lowerColumn,upperColumn,objective, lower,upper); ClpNetworkMatrix is similar, but represents a network, thus may only have one element per column. Fortunately, using is is very easy. Given head and tail, one could do the following: ClpNetworkMatrix network(numberColumns,head,tail); model.loadProblem(network, lowerColumn,upperColumn,objective, lower,upper); Actual code is in COIN/Clp/Test/unitTest.cpp. A quick glance at the output of this program shows that use of ClpNetworkMatrix gives much faster run times. This is not because of storage issues, but because CLP recognizes the network and uses a network basis factorization which is much faster. However, in this mode CLP is not a genuine network code as it does not take full advantage of the structure by combining operations but it does have the advantage of flexibility. Other instances are possible. In particular, it should be possible to use the abstract class for column generation or for dynamic matrices which change over time. Minor modifications may be needed but it should work quite smoothly (there is already a dummy "refresh" method which would be used).
Message Handling Strictly speaking, message handling is a general COIN topic, but it won't hurt to repeat a few important things here. A simple user you may wish to turn off some output. This is done with model.setLogLevel(int value) where 0 gives nothing and each increase in value switches on more messages. See ClpMessage.cpp, CoinMessage.cpp and to see which messages are at which level. A more sophisticated user may wish to handle messages in a different way. This is done using passInMessageHandler with a pointer to a handler of the user's own design. The simplest case would be to use the default handler but use a constructor which writes to file. The code would be: FILE * fp; // assumed open CoinMessageHandler handler(fp); model.passInMessageHandler(&handler); A still more sophisticated use would be to write a class derived from CoinMessageHandler and then override the print method. Below follows an example which would print only a message for optimality (or infeasibility): Sophisticated message handling class DerivedHandler : public CoinMessageHandler { public: virtual int print() ; }; int DerivedHandler::print() { if (currentSource()=="Clp") { if (currentMessage().externalNumber()>=0 && currentMessage().externalNumber()<4) { // finished return CoinMessageHandler::print(); // print } } return 0; }
Clp-1.15.10/install-sh0000755000076600007660000002202111405215425013053 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: Clp-1.15.10/examples/0000755000076600007660000000000012377556130012702 5ustar coincoinClp-1.15.10/examples/defaults.cpp0000644000076600007660000003050111510657150015204 0ustar coincoin/* $Id: defaults.cpp 1662 2011-01-04 17:52:40Z 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). #include "ClpSimplex.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpDualRowSteepest.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1], true); /* This driver is similar to minimum.cpp, but it sets all parameter values to their defaults. The purpose of this is to give a list of most of the methods that the end user will need. There are also some more methods as for OsiSolverInterface e.g. some loadProblem methods and deleteRows and deleteColumns. Often two methods do the same thing, one having a name I like while the other adheres to OsiSolverInterface standards */ // Use exact devex ( a variant of steepest edge) ClpPrimalColumnSteepest primalSteepest; model.setPrimalColumnPivotAlgorithm(primalSteepest); int integerValue; double value; // Infeasibility cost value = model.infeasibilityCost(); std::cout << "Default value of infeasibility cost is " << value << std::endl; model.setInfeasibilityCost(value); if (!status) { model.primal(); } // Number of rows and columns - also getNumRows, getNumCols std::string modelName; model.getStrParam(ClpProbName, modelName); std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " << model.numberColumns() << " columns" << std::endl; /* Some parameters as in OsiSolverParameters. ObjectiveLimits are not active yet. dualTolerance, setDualTolerance, primalTolerance and setPrimalTolerance may be used as well */ model.getDblParam(ClpDualObjectiveLimit, value); std::cout << "Value of ClpDualObjectiveLimit is " << value << std::endl; model.getDblParam(ClpPrimalObjectiveLimit, value); std::cout << "Value of ClpPrimalObjectiveLimit is " << value << std::endl; model.getDblParam(ClpDualTolerance, value); std::cout << "Value of ClpDualTolerance is " << value << std::endl; model.getDblParam(ClpPrimalTolerance, value); std::cout << "Value of ClpPrimalTolerance is " << value << std::endl; model.getDblParam(ClpObjOffset, value); std::cout << "Value of ClpObjOffset is " << value << std::endl; // setDblParam(ClpPrimalTolerance) is same as this model.getDblParam(ClpPrimalTolerance, value); model.setPrimalTolerance(value); model.setDualTolerance(model.dualTolerance()) ; // Other Param stuff // Can also use maximumIterations model.getIntParam(ClpMaxNumIteration, integerValue); std::cout << "Value of ClpMaxNumIteration is " << integerValue << std::endl; model.setMaximumIterations(integerValue); // Not sure this works yet model.getIntParam(ClpMaxNumIterationHotStart, integerValue); std::cout << "Value of ClpMaxNumIterationHotStart is " << integerValue << std::endl; // Can also use getIterationCount and getObjValue /* Status of problem: 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations etc 4 - stopped due to errors */ std::cout << "Model status is " << model.status() << " after " << model.numberIterations() << " iterations - objective is " << model.objectiveValue() << std::endl; assert(!model.isAbandoned()); assert(model.isProvenOptimal()); assert(!model.isProvenPrimalInfeasible()); assert(!model.isProvenDualInfeasible()); assert(!model.isPrimalObjectiveLimitReached()); assert(!model.isDualObjectiveLimitReached()); assert(!model.isIterationLimitReached()); // Things to help you determine if optimal assert(model.primalFeasible()); assert(!model.numberPrimalInfeasibilities()); assert(model.sumPrimalInfeasibilities() < 1.0e-7); assert(model.dualFeasible()); assert(!model.numberDualInfeasibilities()); assert(model.sumDualInfeasibilities() < 1.0e-7); // Save warm start and set to all slack unsigned char * basis1 = model.statusCopy(); model.createStatus(); // Now create another model and do hot start ClpSimplex model2 = model; model2.copyinStatus(basis1); delete [] basis1; // Check model has not got basis (should iterate) model.dual(); // Can use getObjSense model2.setOptimizationDirection(model.optimizationDirection()); // Can use scalingFlag() to check if scaling on // But set up scaling model2.scaling(); // Could play with sparse factorization on/off model2.setSparseFactorization(model.sparseFactorization()); // Sets row pivot choice algorithm in dual ClpDualRowSteepest dualSteepest; model2.setDualRowPivotAlgorithm(dualSteepest); // Dual bound (i.e. dual infeasibility cost) value = model.dualBound(); std::cout << "Default value of dual bound is " << value << std::endl; model.setDualBound(value); // Do some deafult message handling // To see real use - see OsiOslSolverInterfaceTest.cpp CoinMessageHandler handler; model2.passInMessageHandler(& handler); model2.newLanguage(CoinMessages::us_en); //Increase level of detail model2.setLogLevel(4); // solve model2.dual(); // flip direction twice and solve model2.setOptimizationDirection(-1); model2.dual(); model2.setOptimizationDirection(1); //Decrease level of detail model2.setLogLevel(1); model2.dual(); /* Now for getting at information. This will not deal with: ClpMatrixBase * rowCopy() and ClpMatrixbase * clpMatrix() nor with double * infeasibilityRay() and double * unboundedRay() (NULL returned if none/wrong) Up to user to use delete [] on these arrays. */ /* 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 */ int numberRows = model2.numberRows(); // Alternatively getRowActivity() double * rowPrimal = model2.primalRowSolution(); // Alternatively getRowPrice() double * rowDual = model2.dualRowSolution(); // Alternatively getRowLower() double * rowLower = model2.rowLower(); // Alternatively getRowUpper() double * rowUpper = model2.rowUpper(); // Alternatively getRowObjCoefficients() double * rowObjective = model2.rowObjective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model2.lengthNames()); // Row names const std::vector * rowNames = model2.rowNames(); int iRow; std::cout << " Primal Dual Lower Upper (Cost)" << std::endl; for (iRow = 0; iRow < numberRows; iRow++) { double value; std::cout << std::setw(6) << iRow << " " << std::setw(8) << (*rowNames)[iRow]; value = rowPrimal[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowDual[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowLower[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowUpper[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; if (rowObjective) { value = rowObjective[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; } std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; // Columns int numberColumns = model2.numberColumns(); // Alternatively getColSolution() double * columnPrimal = model2.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model2.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model2.columnLower(); // Alternatively getColUpper() double * columnUpper = model2.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model2.objective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model2.lengthNames()); // Column names const std::vector * columnNames = model2.columnNames(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; std::cout << std::setw(6) << iColumn << " " << std::setw(8) << (*columnNames)[iColumn]; value = columnPrimal[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific); // Now matrix CoinPackedMatrix * matrix = model2.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const int * start = matrix->getVectorStarts(); const int * length = matrix->getVectorLengths(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { std::cout << "Column " << iColumn; int j; for (j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++) std::cout << " ( " << row[j] << ", " << element[j] << ")"; std::cout << std::endl; } return 0; } Clp-1.15.10/examples/useVolume.cpp0000644000076600007660000002325612131314313015361 0ustar coincoin/* $Id: useVolume.cpp 1941 2013-04-10 16:52:27Z 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). #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "VolVolume.hpp" //############################################################################# class lpHook : public VOL_user_hooks { private: lpHook(const lpHook&); lpHook& operator= (const lpHook&); private: /// Pointer to dense vector of structural variable upper bounds double *colupper_; /// Pointer to dense vector of structural variable lower bounds double *collower_; /// Pointer to dense vector of objective coefficients double *objcoeffs_; /// Pointer to dense vector of right hand sides double *rhs_; /// Pointer to dense vector of senses char *sense_; /// The problem matrix in a row ordered form CoinPackedMatrix rowMatrix_; /// The problem matrix in a column ordered form CoinPackedMatrix colMatrix_; public: lpHook(const double* clb, const double* cub, const double* obj, const double* rhs, const char* sense, const CoinPackedMatrix& mat); virtual ~lpHook(); public: // for all hooks: return value of -1 means that volume should quit /** compute reduced costs @param u (IN) the dual variables @param rc (OUT) the reduced cost with respect to the dual values */ virtual int compute_rc(const VOL_dvector& u, VOL_dvector& rc); /** Solve the subproblem for the subgradient step. @param dual (IN) the dual variables @param rc (IN) the reduced cost with respect to the dual values @param lcost (OUT) the lagrangean cost with respect to the dual values @param x (OUT) the primal result of solving the subproblem @param v (OUT) b-Ax for the relaxed constraints @param pcost (OUT) the primal objective value of x */ virtual int solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc, double& lcost, VOL_dvector& x, VOL_dvector& v, double& pcost); /** Starting from the primal vector x, run a heuristic to produce an integer solution @param x (IN) the primal vector @param heur_val (OUT) the value of the integer solution (return DBL_MAX here if no feas sol was found */ virtual int heuristics(const VOL_problem& p, const VOL_dvector& x, double& heur_val) { return 0; } }; //############################################################################# lpHook::lpHook(const double* clb, const double* cub, const double* obj, const double* rhs, const char* sense, const CoinPackedMatrix& mat) { const int colnum = mat.getNumCols(); const int rownum = mat.getNumRows(); colupper_ = new double[colnum]; collower_ = new double[colnum]; objcoeffs_ = new double[colnum]; rhs_ = new double[rownum]; sense_ = new char[rownum]; std::copy(clb, clb + colnum, collower_); std::copy(cub, cub + colnum, colupper_); std::copy(obj, obj + colnum, objcoeffs_); std::copy(rhs, rhs + rownum, rhs_); std::copy(sense, sense + rownum, sense_); if (mat.isColOrdered()) { colMatrix_.copyOf(mat); rowMatrix_.reverseOrderedCopyOf(mat); } else { rowMatrix_.copyOf(mat); colMatrix_.reverseOrderedCopyOf(mat); } } //----------------------------------------------------------------------------- lpHook::~lpHook() { delete[] colupper_; delete[] collower_; delete[] objcoeffs_; delete[] rhs_; delete[] sense_; } //############################################################################# int lpHook::compute_rc(const VOL_dvector& u, VOL_dvector& rc) { rowMatrix_.transposeTimes(u.v, rc.v); const int psize = rowMatrix_.getNumCols(); for (int i = 0; i < psize; ++i) rc[i] = objcoeffs_[i] - rc[i]; return 0; } //----------------------------------------------------------------------------- int lpHook::solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc, double& lcost, VOL_dvector& x, VOL_dvector& v, double& pcost) { int i; const int psize = x.size(); const int dsize = v.size(); // compute the lagrangean solution corresponding to the reduced costs for (i = 0; i < psize; ++i) x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i]; // compute the lagrangean value (rhs*dual + primal*rc) lcost = 0; for (i = 0; i < dsize; ++i) lcost += rhs_[i] * dual[i]; for (i = 0; i < psize; ++i) lcost += x[i] * rc[i]; // compute the rhs - lhs colMatrix_.times(x.v, v.v); for (i = 0; i < dsize; ++i) v[i] = rhs_[i] - v[i]; // compute the lagrangean primal objective pcost = 0; for (i = 0; i < psize; ++i) pcost += x[i] * objcoeffs_[i]; return 0; } //############################################################################# int main(int argc, const char *argv[]) { ClpSimplex model; int status; if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1], true); if( status != 0 ) { printf("Error %d reading MPS file\n", status); return status; } /* This driver uses volume algorithm then does dual - after adjusting costs then solves real problem */ // do volume for a bit VOL_problem volprob; const CoinPackedMatrix* mat = model.matrix(); const int psize = mat->getNumCols(); const int dsize = mat->getNumRows(); char * sense = new char[dsize]; double * rhs = new double[dsize]; const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); // Set the lb/ub on the duals volprob.dsize = dsize; volprob.psize = psize; volprob.dual_lb.allocate(dsize); volprob.dual_ub.allocate(dsize); volprob.dsol.allocate(dsize); int i; for (i = 0; i < dsize; ++i) { if (rowUpper[i] == rowLower[i]) { // 'E': volprob.dual_lb[i] = -1.0e31; volprob.dual_ub[i] = 1.0e31; rhs[i] = rowUpper[i]; sense[i] = 'E'; } else if (rowLower[i] < -0.99e10 && rowUpper[i] < 0.99e10) { // 'L': volprob.dual_lb[i] = -1.0e31; volprob.dual_ub[i] = 0.0; rhs[i] = rowUpper[i]; sense[i] = 'L'; } else if (rowLower[i] > -0.99e10 && rowUpper[i] > 0.99e10) { // 'G': volprob.dual_lb[i] = 0.0; volprob.dual_ub[i] = 1.0e31; rhs[i] = rowLower[i]; sense[i] = 'G'; } else { printf("Volume Algorithm can't work if there is a non ELG row\n"); abort(); } } // Can't use read_param as private // anyway I want automatic use - so maybe this is problem #if 0 FILE* infile = fopen("parameters", "r"); if (!infile) { printf("Failure to open parameter file\n"); } else { volprob.read_params("parameters"); } #endif #if 0 // should save and restore bounds model.tightenPrimalBounds(); #else double * colUpper = model.columnUpper(); for (i = 0; i < psize; i++) colUpper[i] = 1.0; #endif lpHook myHook(model.getColLower(), model.getColUpper(), model.getObjCoefficients(), rhs, sense, *mat); // move duals double * pi = model.dualRowSolution(); memcpy(volprob.dsol.v, pi, dsize * sizeof(double)); volprob.solve(myHook, false /* not warmstart */); // For now stop as not doing any good exit(77); // create objectives int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); memcpy(pi, volprob.dsol.v, numberRows * sizeof(double)); #define MODIFYCOSTS #ifdef MODIFYCOSTS double * saveObj = new double[numberColumns]; memcpy(saveObj, model.objective(), numberColumns * sizeof(double)); memcpy(model.dualColumnSolution(), model.objective(), numberColumns * sizeof(double)); model.clpMatrix()->transposeTimes(-1.0, pi, model.dualColumnSolution()); memcpy(model.objective(), model.dualColumnSolution(), numberColumns * sizeof(double)); const double * rowsol = model.primalRowSolution(); //const double * rowLower = model.rowLower(); //const double * rowUpper = model.rowUpper(); double offset = 0.0; for (i = 0; i < numberRows; i++) { offset += pi[i] * rowsol[i]; } double value2; model.getDblParam(ClpObjOffset, value2); printf("Offset %g %g\n", offset, value2); model.setRowObjective(pi); // zero out pi memset(pi, 0, numberRows * sizeof(double)); #endif // Could put some in basis - only partially tested model.allSlackBasis(); model.factorization()->maximumPivots(1000); //model.setLogLevel(63); // solve model.dual(1); //model.primal(1); #ifdef MODIFYCOSTS memcpy(model.objective(), saveObj, numberColumns * sizeof(double)); // zero out pi memset(pi, 0, numberRows * sizeof(double)); model.setRowObjective(pi); delete [] saveObj; model.primal(); #endif return 0; } Clp-1.15.10/examples/gparm.tiny0000644000076600007660000000000610763274574014717 0ustar coincoin12 15 Clp-1.15.10/examples/myPdco.cpp0000644000076600007660000002206511510657150014636 0ustar coincoin/* $Id: myPdco.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "ClpInterior.hpp" #include "myPdco.hpp" #include "ClpDummyMatrix.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- myPdco::myPdco() : ClpPdcoBase(), rowIndex_(NULL), numlinks_(0), numnodes_(0) { setType(11); } // Constructor from stuff myPdco::myPdco(double d1, double d2, int numnodes, int numlinks) : ClpPdcoBase(), rowIndex_(NULL), numlinks_(numlinks), numnodes_(numnodes) { d1_ = d1; d2_ = d2; setType(11); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- myPdco::myPdco(const myPdco & rhs) : ClpPdcoBase(rhs), numlinks_(rhs.numlinks_), numnodes_(rhs.numnodes_) { rowIndex_ = ClpCopyOfArray(rhs.rowIndex_, 2 * (numlinks_ + 2 * numnodes_)); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- myPdco::~myPdco() { delete [] rowIndex_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- myPdco & myPdco::operator= (const myPdco & rhs) { if (this != &rhs) { ClpPdcoBase::operator= (rhs); numlinks_ = rhs.numlinks_; numnodes_ = rhs.numnodes_; rowIndex_ = ClpCopyOfArray(rhs.rowIndex_, 2 * (numlinks_ + 2 * numnodes_)); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpPdcoBase * myPdco::clone() const { return new myPdco(*this); } void myPdco::matVecMult(ClpInterior * model, int mode, double* x_elts, double* y_elts) const { int nrow = model->numberRows(); if (mode == 1) { double y_sum = 0.0; for (int k = 0; k < numlinks_; k++) { y_sum += y_elts[k]; int i1 = rowIndex_[2*k]; assert(i1 >= 0); x_elts[i1] += y_elts[k]; int i2 = rowIndex_[2*k+1]; assert(i2 >= 0); x_elts[i2] -= y_elts[k]; } double y_suma = 0.0; double y_sumb = 0.0; for (int k = 0; k < numnodes_; k++) { y_suma -= y_elts[numlinks_ + k]; y_sumb += y_elts[numlinks_ + numnodes_ + k]; x_elts[k] += y_elts[numlinks_ + k]; x_elts[k] -= y_elts[numlinks_ + numnodes_ + k]; } x_elts[nrow-3] += y_suma; x_elts[nrow-2] += y_sumb; x_elts[nrow-1] += (y_sum - y_suma + y_sumb); } else { for (int k = 0; k < numlinks_; k++) { x_elts[k] += y_elts[nrow-1]; int i1 = rowIndex_[2*k]; x_elts[k] += y_elts[i1]; int i2 = rowIndex_[2*k+1]; x_elts[k] -= y_elts[i2]; } for (int k = 0; k < numnodes_; k++) { x_elts[numlinks_ + k] += (y_elts[k] - y_elts[nrow-3] + y_elts[nrow-1]); x_elts[numlinks_ + numnodes_ + k] += (y_elts[nrow-2] - y_elts[k] + y_elts[nrow-1]); } } return; } void myPdco::matPrecon(ClpInterior * model, double delta, double* x_elts, double* y_elts) const { double y_sum = 0.0; int ncol = model->numberColumns(); int nrow = model->numberRows(); double *ysq = new double[ncol]; for (int k = 0; k < nrow; k++) x_elts[k] = 0.0; for (int k = 0; k < ncol; k++) ysq[k] = y_elts[k] * y_elts[k]; for (int k = 0; k < numlinks_; k++) { y_sum += ysq[k]; int i1 = rowIndex_[2*k]; x_elts[i1] += ysq[k]; int i2 = rowIndex_[2*k+1]; x_elts[i2] += ysq[k]; } double y_suma = 0.0; double y_sumb = 0.0; for (int k = 0; k < numnodes_; k++) { y_suma += ysq[numlinks_ + k]; y_sumb += ysq[numlinks_ + numnodes_ + k]; x_elts[k] += ysq[numlinks_ + k]; x_elts[k] += ysq[numlinks_ + numnodes_ + k]; } x_elts[nrow-3] += y_suma; x_elts[nrow-2] += y_sumb; x_elts[nrow-1] += (y_sum + y_suma + y_sumb); delete [] ysq; double delsq = delta * delta; for (int k = 0; k < nrow; k++) x_elts[k] = 1.0 / (sqrt(x_elts[k] + delsq)); return; } double myPdco::getObj(ClpInterior * model, CoinDenseVector &x) const { double obj = 0; double *x_elts = x.getElements(); int ncol = model->numberColumns(); for (int k = 0; k < ncol; k++) obj += x_elts[k] * log(x_elts[k]); return obj; } void myPdco::getGrad(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &g) const { double *x_elts = x.getElements(); double *g_elts = g.getElements(); int ncol = model->numberColumns(); for (int k = 0; k < ncol; k++) g_elts[k] = 1.0 + log(x_elts[k]); return; } void myPdco::getHessian(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &H) const { double *x_elts = x.getElements(); double *H_elts = H.getElements(); int ncol = model->numberColumns(); for (int k = 0; k < ncol; k++) H_elts[k] = 1.0 / x_elts[k]; return; } myPdco::myPdco(ClpInterior & model, FILE * fpData, FILE * fpParam) { int nrow; int ncol; int numelts; double *rowUpper; double *rowLower; double *colUpper; double *colLower; double *rhs; double *x; double *y; double *dj; int ipair[2], igparm[4], maxrows, maxlinks; // Read max array sizes and allocate them fscanf(fpParam, "%d %d", &maxrows, &maxlinks); int *ir = new int[2*maxlinks + 5]; /********************** alpha parameter hrdwired here ***********/ double alpha = 0.9; int kct = 0; int imax = 0; int imin = 0x7fffffff; int *ifrom = &ipair[0]; int *ito = &ipair[1]; int nonzpt = 0; numlinks_ = 0; while (fscanf(fpData, "%d %d", ifrom, ito) && kct++ < maxlinks) { // while(fread(ipair, 4,2, fpData) && kct++ < maxlinks){ if ((*ifrom) < 0) { printf("Bad link %d %d\n", *ifrom, *ito); continue; } ipair[0]--; ipair[1]--; //assert(*ifrom>=0&&*ifrom=0&&*ifrom= maxrows || *ito < 0 || *ito >= maxrows) { printf("bad link %d %d\n", *ifrom, *ito); continue; } numlinks_++; ir[nonzpt++] = *ifrom; ir[nonzpt++] = *ito; imax = CoinMax(imax, *ifrom); imax = CoinMax(imax, *ito); imin = CoinMin(imin, *ifrom); imin = CoinMin(imin, *ito); } fclose(fpData); fclose(fpParam); printf("imax %d imin %d\n", imax, imin); // Set model size numnodes_ = imax + 1; nrow = numnodes_ + 3; ncol = numlinks_ + 2 * numnodes_; numelts = 3 * ncol; rowIndex_ = ir; d1_ = 1.0e-3; d2_ = 1.0e-3; double* rhs_def = new double[nrow]; for (int k = 0; k < nrow; k++) rhs_def[k] = 0.0; rhs_def[nrow-3] = alpha - 1.0; rhs_def[nrow-2] = 1.0 - alpha; rhs_def[nrow-1] = 1.0; // rhs_ etc should not be public rhs = rhs_def; rowUpper = rhs_def; rowLower = rhs_def; double *x_def = new double[ncol]; double *U_def = new double[ncol]; double *L_def = new double[ncol]; for (int k = 0; k < ncol; k++) { // x_def[k] = 10.0/ncol; x_def[k] = 1.0 / ncol; U_def[k] = 1e20;; L_def[k] = 0.0; } x = x_def; colUpper = U_def; colLower = L_def; // We have enough to create a model ClpDummyMatrix dummy(ncol, nrow, numelts); model.loadProblem(dummy, colLower, colUpper, NULL, rowLower, rowUpper); double *y_def = new double[nrow]; for (int k = 0; k < nrow; k++) y_def[k] = 0.0; y = y_def; double *dj_def = new double[ncol]; for (int k = 0; k < ncol; k++) dj_def[k] = 1.0; dj = dj_def; // delete arrays delete [] U_def; delete [] L_def; // Should be sets model.rhs_ = rhs; model.x_ = x; model.y_ = y; model.dj_ = dj; model.xsize_ = 50 / ncol; model.xsize_ = CoinMin(model.xsize_, 1.0); model.zsize_ = 1; } Clp-1.15.10/examples/ekk_interface.cpp0000644000076600007660000002413211510657150016172 0ustar coincoin/* $Id: ekk_interface.cpp 1662 2011-01-04 17:52:40Z 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). #include #include "ClpSimplexPrimal.hpp" #include "ClpFactorization.hpp" #include "ClpPresolve.hpp" #include "ekk_c_api.h" //#include "ekk_c_api_undoc.h" extern "C" { OSLLIBAPI void * OSLLINKAGE ekk_compressModel(EKKModel * model); OSLLIBAPI void OSLLINKAGE ekk_decompressModel(EKKModel * model, void * compressInfo); } static ClpPresolve * presolveInfo = NULL; static ClpSimplex * clpmodel(EKKModel * model, int startup) { ClpSimplex * clp = new ClpSimplex();; int numberRows = ekk_getInumrows(model); int numberColumns = ekk_getInumcols(model); clp->loadProblem(numberColumns, numberRows, ekk_blockColumn(model, 0), ekk_blockRow(model, 0), ekk_blockElement(model, 0), ekk_collower(model), ekk_colupper(model), ekk_objective(model), ekk_rowlower(model), ekk_rowupper(model)); clp->setOptimizationDirection((int) ekk_getRmaxmin(model)); clp->setPrimalTolerance(ekk_getRtolpinf(model)); if (ekk_getRpweight(model) != 0.1) clp->setInfeasibilityCost(1.0 / ekk_getRpweight(model)); clp->setDualTolerance(ekk_getRtoldinf(model)); if (ekk_getRdweight(model) != 0.1) clp->setDualBound(1.0 / ekk_getRdweight(model)); clp->setDblParam(ClpObjOffset, ekk_getRobjectiveOffset(model)); const int * rowStatus = ekk_rowstat(model); const double * rowSolution = ekk_rowacts(model); int i; clp->createStatus(); double * clpSolution; clpSolution = clp->primalRowSolution(); memcpy(clpSolution, rowSolution, numberRows * sizeof(double)); const double * rowLower = ekk_rowlower(model); const double * rowUpper = ekk_rowupper(model); for (i = 0; i < numberRows; i++) { ClpSimplex::Status status; if ((rowStatus[i] & 0x80000000) != 0) { status = ClpSimplex::basic; } else { if (!startup) { // believe bits int ikey = rowStatus[i] & 0x60000000; if (ikey == 0x40000000) { // at ub status = ClpSimplex::atUpperBound; clpSolution[i] = rowUpper[i]; } else if (ikey == 0x20000000) { // at lb status = ClpSimplex::atLowerBound; clpSolution[i] = rowLower[i]; } else if (ikey == 0x60000000) { // free status = ClpSimplex::isFree; clpSolution[i] = 0.0; } else { // fixed status = ClpSimplex::atLowerBound; clpSolution[i] = rowLower[i]; } } else { status = ClpSimplex::superBasic; } } clp->setRowStatus(i, status); } const int * columnStatus = ekk_colstat(model); const double * columnSolution = ekk_colsol(model); clpSolution = clp->primalColumnSolution(); memcpy(clpSolution, columnSolution, numberColumns * sizeof(double)); const double * columnLower = ekk_collower(model); const double * columnUpper = ekk_colupper(model); for (i = 0; i < numberColumns; i++) { ClpSimplex::Status status; if ((columnStatus[i] & 0x80000000) != 0) { status = ClpSimplex::basic; } else { if (!startup) { // believe bits int ikey = columnStatus[i] & 0x60000000; if (ikey == 0x40000000) { // at ub status = ClpSimplex::atUpperBound; clpSolution[i] = columnUpper[i]; } else if (ikey == 0x20000000) { // at lb status = ClpSimplex::atLowerBound; clpSolution[i] = columnLower[i]; } else if (ikey == 0x60000000) { // free status = ClpSimplex::isFree; clpSolution[i] = 0.0; } else { // fixed status = ClpSimplex::atLowerBound; clpSolution[i] = columnLower[i]; } } else { status = ClpSimplex::superBasic; } } clp->setColumnStatus(i, status); } return clp; } static int solve(EKKModel * model, int startup, int algorithm, int presolve) { // values pass or not if (startup) startup = 1; // if scaled then be careful bool scaled = ekk_scaling(model) == 1; if (scaled) ekk_scaleRim(model, 1); void * compressInfo = NULL; ClpSimplex * clp; if (!presolve || !presolveInfo) { // no presolve or osl presolve - compact columns compressInfo = ekk_compressModel(model); clp = clpmodel(model, startup);; } else { // pick up clp model clp = presolveInfo->model(); } // don't scale if alreday scaled if (scaled) clp->scaling(false); if (clp->numberRows() > 10000) clp->factorization()->maximumPivots(100 + clp->numberRows() / 100); if (algorithm > 0) clp->primal(startup); else clp->dual(); int numberIterations = clp->numberIterations(); if (presolve && presolveInfo) { // very wasteful - create a clp copy of osl model ClpSimplex * clpOriginal = clpmodel(model, 0); presolveInfo->setOriginalModel(clpOriginal); // do postsolve presolveInfo->postsolve(true); delete clp; delete presolveInfo; presolveInfo = NULL; clp = clpOriginal; if (presolve == 3 || (presolve == 2 && clp->status())) { printf("Resolving from postsolved model\n"); clp->primal(1); numberIterations += clp->numberIterations(); } } // put back solution double * rowDual = (double *) ekk_rowduals(model); int numberRows = ekk_getInumrows(model); int numberColumns = ekk_getInumcols(model); int * rowStatus = (int *) ekk_rowstat(model); double * rowSolution = (double *) ekk_rowacts(model); int i; int * columnStatus = (int *) ekk_colstat(model); double * columnSolution = (double *) ekk_colsol(model); memcpy(rowSolution, clp->primalRowSolution(), numberRows * sizeof(double)); memcpy(rowDual, clp->dualRowSolution(), numberRows * sizeof(double)); for (i = 0; i < numberRows; i++) { if (clp->getRowStatus(i) == ClpSimplex::basic) rowStatus[i] = 0x80000000; else rowStatus[i] = 0; } double * columnDual = (double *) ekk_colrcosts(model); memcpy(columnSolution, clp->primalColumnSolution(), numberColumns * sizeof(double)); memcpy(columnDual, clp->dualColumnSolution(), numberColumns * sizeof(double)); for (i = 0; i < numberColumns; i++) { if (clp->getColumnStatus(i) == ClpSimplex::basic) columnStatus[i] = 0x80000000; else columnStatus[i] = 0; } ekk_setIprobstat(model, clp->status()); ekk_setRobjvalue(model, clp->objectiveValue()); ekk_setInumpinf(model, clp->numberPrimalInfeasibilities()); ekk_setInumdinf(model, clp->numberDualInfeasibilities()); ekk_setIiternum(model, numberIterations); ekk_setRsumpinf(model, clp->sumPrimalInfeasibilities()); ekk_setRsumdinf(model, clp->sumDualInfeasibilities()); delete clp; if (compressInfo) ekk_decompressModel(model, compressInfo); if (scaled) ekk_scaleRim(model, 2); return 0; } /* As ekk_primalSimplex + postsolve instructions: presolve - 0 , no presolve, 1 presolve but no primal after postsolve, 2 do primal if any infeasibilities, 3 always do primal. */ extern "C" int ekk_primalClp(EKKModel * model, int startup, int presolve) { if (presolveInfo) { if (!presolve) presolve = 3; return solve(model, startup, 1, presolve); } else { return solve(model, startup, 1, 0); } } /* As ekk_dualSimplex + postsolve instructions: presolve - 0 , no presolve, 1 presolve but no primal after postsolve, 2 do primal if any infeasibilities, 3 always do primal. */ extern "C" int ekk_dualClp(EKKModel * model, int presolve) { if (presolveInfo) { if (!presolve) presolve = 3; return solve(model, 0, -1, presolve); } else { return solve(model, 0, -1, 0); } } /* rather like ekk_preSolve (3) plus: keepIntegers - false to treat as if continuous pass - do this many passes (0==default(5)) returns 1 if infeasible */ extern "C" int ekk_preSolveClp(EKKModel * model, bool keepIntegers, int pass) { delete presolveInfo; presolveInfo = new ClpPresolve(); bool scaled = ekk_scaling(model) == 1; if (scaled) ekk_scaleRim(model, 1); if (!pass) pass = 5; // very wasteful - create a clp copy of osl model // 1 to keep solution as is ClpSimplex * clp = clpmodel(model, 1); // could get round with tailored version of ClpPresolve.cpp ClpSimplex * newModel = presolveInfo->presolvedModel(*clp, ekk_getRtolpinf(model), keepIntegers, pass, true); delete clp; presolveInfo->setOriginalModel(NULL); if (scaled) ekk_scaleRim(model, 2); if (newModel) { return 0; } else { delete presolveInfo; presolveInfo = NULL; return 1; } } Clp-1.15.10/examples/INSTALL0000644000076600007660000000112010445377214013723 0ustar coincoinThere are a number of example/test programs in this directory. Before any of these sample programs could be compiled one needs to install the COIN libraries used. This includes Clp for sure, and may include others (like Vol). Please go to the appropriate directories, read the INSTALL file there and install the libraries. The examples here can be compiled by `make DRIVER=`, where should be replaced with the name of the source file you want to compile (without the .cpp or .c). The output of the compilation is an executable named (or .exe on Windows). Clp-1.15.10/examples/sprint.cpp0000644000076600007660000002304012131314313014703 0ustar coincoin/* $Id: sprint.cpp 1941 2013-04-10 16:52:27Z 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). #include "ClpSimplex.hpp" #include "CoinSort.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { status = model.readMps("small.mps", true); } else { status = model.readMps(argv[1], true); } if (status) exit(10); /* This driver implements what I called Sprint. Cplex calls it "sifting" which is just as silly. When I thought of this trivial idea it reminded me of an LP code of the 60's called sprint which after every factorization took a subset of the matrix into memory (all 64K words!) and then iterated very fast on that subset. On the problems of those days it did not work very well, but it worked very well on aircrew scheduling problems where there were very large numbers of columns all with the same flavor. */ /* The idea works best if you can get feasible easily. To make it more general we can add in costed slacks */ int originalNumberColumns = model.numberColumns(); int numberRows = model.numberRows(); // We will need arrays to choose variables. These are too big but .. double * weight = new double [numberRows+originalNumberColumns]; int * sort = new int [numberRows+originalNumberColumns]; int numberSort = 0; // Say we are going to add slacks - if you can get a feasible // solution then do that at the comment - Add in your own coding here bool addSlacks = true; if (addSlacks) { // initial list will just be artificials // first we will set all variables as close to zero as possible int iColumn; const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); double * columnSolution = model.primalColumnSolution(); for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { double value = 0.0; if (columnLower[iColumn] > 0.0) value = columnLower[iColumn]; else if (columnUpper[iColumn] < 0.0) value = columnUpper[iColumn]; columnSolution[iColumn] = value; } // now see what that does to row solution double * rowSolution = model.primalRowSolution(); memset(rowSolution, 0, numberRows * sizeof(double)); model.times(1.0, columnSolution, rowSolution); int * addStarts = new int [numberRows+1]; int * addRow = new int[numberRows]; double * addElement = new double[numberRows]; const double * lower = model.rowLower(); const double * upper = model.rowUpper(); addStarts[0] = 0; int numberArtificials = 0; double * addCost = new double [numberRows]; const double penalty = 1.0e8; int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > rowSolution[iRow]) { addRow[numberArtificials] = iRow; addElement[numberArtificials] = 1.0; addCost[numberArtificials] = penalty; numberArtificials++; addStarts[numberArtificials] = numberArtificials; } else if (upper[iRow] < rowSolution[iRow]) { addRow[numberArtificials] = iRow; addElement[numberArtificials] = -1.0; addCost[numberArtificials] = penalty; numberArtificials++; addStarts[numberArtificials] = numberArtificials; } } model.addColumns(numberArtificials, NULL, NULL, addCost, addStarts, addRow, addElement); delete [] addStarts; delete [] addRow; delete [] addElement; delete [] addCost; // Set up initial list numberSort = numberArtificials; int i; for (i = 0; i < numberSort; i++) sort[i] = i + originalNumberColumns; } else { // Get initial list in some magical way // Add in your own coding here abort(); } int numberColumns = model.numberColumns(); const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); double * fullSolution = model.primalColumnSolution(); // Just do this number of passes int maxPass = 100; int iPass; double lastObjective = 1.0e31; // Just take this number of columns in small problem int smallNumberColumns = CoinMin(3 * numberRows, numberColumns); smallNumberColumns = CoinMax(smallNumberColumns, 3000); // To stop seg faults on unsuitable problems smallNumberColumns = CoinMin(smallNumberColumns,numberColumns); // We will be using all rows int * whichRows = new int [numberRows]; for (int iRow = 0; iRow < numberRows; iRow++) whichRows[iRow] = iRow; double originalOffset; model.getDblParam(ClpObjOffset, originalOffset); for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); //printf("Bug until submodel new version\n"); CoinSort_2(sort, sort + numberSort, weight); // Create small problem ClpSimplex small(&model, numberRows, whichRows, numberSort, sort); // now see what variables left out do to row solution double * rowSolution = model.primalRowSolution(); memset(rowSolution, 0, numberRows * sizeof(double)); int iRow, iColumn; // zero out ones in small problem for (iColumn = 0; iColumn < numberSort; iColumn++) { int kColumn = sort[iColumn]; fullSolution[kColumn] = 0.0; } // Get objective offset double offset = 0.0; const double * objective = model.objective(); for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) offset += fullSolution[iColumn] * objective[iColumn]; small.setDblParam(ClpObjOffset, originalOffset - offset); model.times(1.0, fullSolution, rowSolution); double * lower = small.rowLower(); double * upper = small.rowUpper(); for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > -1.0e50) lower[iRow] -= rowSolution[iRow]; if (upper[iRow] < 1.0e50) upper[iRow] -= rowSolution[iRow]; } /* For some problems a useful variant is to presolve problem. In this case you need to adjust smallNumberColumns to get right size problem. Also you can dispense with creating small problem and fix variables in large problem and do presolve on that. */ // Solve small.primal(); // move solution back const double * solution = small.primalColumnSolution(); for (iColumn = 0; iColumn < numberSort; iColumn++) { int kColumn = sort[iColumn]; model.setColumnStatus(kColumn, small.getColumnStatus(iColumn)); fullSolution[kColumn] = solution[iColumn]; } for (iRow = 0; iRow < numberRows; iRow++) model.setRowStatus(iRow, small.getRowStatus(iRow)); memcpy(model.primalRowSolution(), small.primalRowSolution(), numberRows * sizeof(double)); if ((small.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) || !small.numberIterations() || iPass == maxPass - 1) { break; // finished } else { lastObjective = small.objectiveValue(); // get reduced cost for large problem // this assumes minimization memcpy(weight, model.objective(), numberColumns * sizeof(double)); model.transposeTimes(-1.0, small.dualRowSolution(), weight); // now massage weight so all basic in plus good djs for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = weight[iColumn]; double value = fullSolution[iColumn]; if (model.getColumnStatus(iColumn) == ClpSimplex::basic) dj = -1.0e50; else if (dj < 0.0 && value < columnUpper[iColumn]) dj = dj; else if (dj > 0.0 && value > columnLower[iColumn]) dj = -dj; else if (columnUpper[iColumn] > columnLower[iColumn]) dj = fabs(dj); else dj = 1.0e50; weight[iColumn] = dj; sort[iColumn] = iColumn; } // sort CoinSort_2(weight, weight + numberColumns, sort); numberSort = smallNumberColumns; } } if (addSlacks) { int i; int numberArtificials = numberColumns - originalNumberColumns; for (i = 0; i < numberArtificials; i++) sort[i] = i + originalNumberColumns; model.deleteColumns(numberArtificials, sort); } delete [] weight; delete [] sort; delete [] whichRows; model.primal(1); return 0; } Clp-1.15.10/examples/network.cpp0000644000076600007660000001351311510657150015072 0ustar coincoin/* $Id: network.cpp 1662 2011-01-04 17:52:40Z 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). // The point of this example is to show how to create a model without // using mps files. // This reads a network problem created by netgen which can be // downloaded from www.netlib.org/lp/generators/netgen // This is a generator due to Darwin Klingman #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpNetworkMatrix.hpp" #include #include #include int main(int argc, const char *argv[]) { int numberColumns; int numberRows; FILE * fp; if (argc > 1) { fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Unable to open file %s\n", argv[1]); exit(1); } } else { fp = fopen("input.130", "r"); if (!fp) { fprintf(stderr, "Unable to open file input.l30 in Samples directory\n"); exit(1); } } int problem; char temp[100]; // read and skip fscanf(fp, "%s", temp); assert(!strcmp(temp, "BEGIN")); fscanf(fp, "%*s %*s %d %d %*s %*s %d %*s", &problem, &numberRows, &numberColumns); // scan down to SUPPLY while (fgets(temp, 100, fp)) { if (!strncmp(temp, "SUPPLY", 6)) break; } if (strncmp(temp, "SUPPLY", 6)) { fprintf(stderr, "Unable to find SUPPLY\n"); exit(2); } // get space for rhs double * lower = new double[numberRows]; double * upper = new double[numberRows]; int i; for (i = 0; i < numberRows; i++) { lower[i] = 0.0; upper[i] = 0.0; } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "ARCS", 4)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = -value; lower[row-1] = -value; } if (strncmp(temp, "ARCS", 4)) { fprintf(stderr, "Unable to find ARCS\n"); exit(2); } // number of columns may be underestimate int * head = new int[2*numberColumns]; int * tail = new int[2*numberColumns]; int * ub = new int[2*numberColumns]; int * cost = new int[2*numberColumns]; // ***** Remember to convert to C notation numberColumns = 0; while (fgets(temp, 100, fp)) { int iHead; int iTail; int iUb; int iCost; if (!strncmp(temp, "DEMAND", 6)) break; sscanf(temp, "%d %d %d %d", &iHead, &iTail, &iCost, &iUb); iHead--; iTail--; head[numberColumns] = iHead; tail[numberColumns] = iTail; ub[numberColumns] = iUb; cost[numberColumns] = iCost; numberColumns++; } if (strncmp(temp, "DEMAND", 6)) { fprintf(stderr, "Unable to find DEMAND\n"); exit(2); } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "END", 3)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = value; lower[row-1] = value; } if (strncmp(temp, "END", 3)) { fprintf(stderr, "Unable to find END\n"); exit(2); } printf("Problem %d has %d rows and %d columns\n", problem, numberRows, numberColumns); fclose(fp); ClpSimplex model; // now build model - we have rhs so build columns - two elements // per column double * objective = new double[numberColumns]; double * lowerColumn = new double[numberColumns]; double * upperColumn = new double[numberColumns]; double * element = new double [2*numberColumns]; int * start = new int[numberColumns+1]; int * row = new int[2*numberColumns]; start[numberColumns] = 2 * numberColumns; for (i = 0; i < numberColumns; i++) { start[i] = 2 * i; element[2*i] = -1.0; element[2*i+1] = 1.0; row[2*i] = head[i]; row[2*i+1] = tail[i]; lowerColumn[i] = 0.0; upperColumn[i] = ub[i]; objective[i] = cost[i]; } // Create Packed Matrix CoinPackedMatrix matrix; int * lengths = NULL; matrix.assignMatrix(true, numberRows, numberColumns, 2 * numberColumns, element, row, start, lengths); ClpNetworkMatrix network(matrix); // load model model.loadProblem(network, lowerColumn, upperColumn, objective, lower, upper); delete [] lower; delete [] upper; delete [] head; delete [] tail; delete [] ub; delete [] cost; delete [] objective; delete [] lowerColumn; delete [] upperColumn; delete [] element; delete [] start; delete [] row; /* The confusing flow below is in to exercise both dual and primal when ClpNetworkMatrix storage used. For practical use just one call e.g. model.dual(); would be used. If network then factorization scheme is changed to be much faster. Still not as fast as a real network code, but more flexible */ model.factorization()->maximumPivots(200 + model.numberRows() / 100); model.factorization()->maximumPivots(1000); //model.factorization()->maximumPivots(1); if (model.numberRows() < 50) model.messageHandler()->setLogLevel(63); model.dual(); model.setOptimizationDirection(-1); //model.messageHandler()->setLogLevel(63); model.primal(); model.setOptimizationDirection(1); model.primal(); return 0; } Clp-1.15.10/examples/testBarrier.cpp0000644000076600007660000000266011573730475015703 0ustar coincoin/* $Id: testBarrier.cpp 1734 2011-06-08 17:28:29Z 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). // @TODO the ifdef WSSMP_BARRIER currently does not work - the define is never set // best would be if one could tell ClpModel to use the wssmp factorization code, if available, without having to check for some define #include "ClpInterior.hpp" #include "ClpSimplex.hpp" #ifdef WSSMP_BARRIER #include "ClpCholeskyWssmp.hpp" #endif #include "ClpCholeskyDense.hpp" int main(int argc, const char *argv[]) { ClpInterior model; int status; if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1]); if (status) { printf("errors on input\n"); exit(77); } // ** note this does not have presolve #ifdef WSSMP_BARRIER ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(); #else ClpCholeskyDense * cholesky = new ClpCholeskyDense(); #endif model.setCholesky(cholesky); model.primalDual(); // Do crossover ClpSimplex model2(model); // make sure no status left model2.createStatus(); model2.primal(1); return 0; } Clp-1.15.10/examples/testGub2.cpp0000644000076600007660000004127711510657150015110 0ustar coincoin/* $Id: testGub2.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include "ClpSimplex.hpp" #include "ClpGubDynamicMatrix.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "CoinSort.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinMpsIO.hpp" int main(int argc, const char *argv[]) { ClpSimplex model; int status; int maxIts = 0; int maxFactor = 100; if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1]); if (status) { printf("errors on input\n"); exit(77); } if (argc > 2) { maxFactor = atoi(argv[2]); printf("max factor %d\n", maxFactor); } if (argc > 3) { maxIts = atoi(argv[3]); printf("max its %d\n", maxIts); } // For now scaling off model.scaling(0); if (maxIts) { // Do partial dantzig ClpPrimalColumnSteepest dantzig(5); model.setPrimalColumnPivotAlgorithm(dantzig); //model.messageHandler()->setLogLevel(63); model.setFactorizationFrequency(maxFactor); model.setMaximumIterations(maxIts); model.primal(); if (!model.status()) exit(1); } // find gub int numberRows = model.numberRows(); int * gubStart = new int[numberRows+1]; int * gubEnd = new int[numberRows]; int * which = new int[numberRows]; int * whichGub = new int[numberRows]; int numberColumns = model.numberColumns(); int * mark = new int[numberColumns]; int iRow, iColumn; // delete variables fixed to zero const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberDelete = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0) mark[numberDelete++] = iColumn; } if (numberDelete) { model.deleteColumns(numberDelete, mark); numberColumns -= numberDelete; columnLower = model.columnLower(); columnUpper = model.columnUpper(); #if 0 CoinMpsIO writer; writer.setMpsData(*model.matrix(), COIN_DBL_MAX, model.getColLower(), model.getColUpper(), model.getObjCoefficients(), (const char*) 0 /*integrality*/, model.getRowLower(), model.getRowUpper(), NULL, NULL); writer.writeMps("cza.mps", 0, 0, 1); #endif } double * lower = new double[numberRows]; double * upper = new double[numberRows]; const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) mark[iColumn] = -1; CoinPackedMatrix * matrix = model.matrix(); // 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(); int putGub = numberRows; int putNonGub = numberRows; int * rowIsGub = new int [numberRows]; for (iRow = numberRows - 1; iRow >= 0; iRow--) { bool gubRow = true; int first = numberColumns + 1; int last = -1; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { if (element[j] != 1.0) { gubRow = false; break; } else { int iColumn = column[j]; if (mark[iColumn] >= 0) { gubRow = false; break; } else { last = CoinMax(last, iColumn); first = CoinMin(first, iColumn); } } } if (last - first + 1 != rowLength[iRow] || !gubRow) { which[--putNonGub] = iRow; rowIsGub[iRow] = 0; } else { for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; mark[iColumn] = iRow; } rowIsGub[iRow] = -1; putGub--; gubStart[putGub] = first; gubEnd[putGub] = last + 1; lower[putGub] = rowLower[iRow]; upper[putGub] = rowUpper[iRow]; whichGub[putGub] = iRow; } } int numberNonGub = numberRows - putNonGub; int numberGub = numberRows - putGub; if (numberGub > 0) { printf("** %d gub rows\n", numberGub); int numberNormal = 0; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int numberElements = 0; bool doLower = false; bool doUpper = false; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (mark[iColumn] < 0) { mark[numberNormal++] = iColumn; } else { numberElements += columnLength[iColumn]; if (columnLower[iColumn] != 0.0) doLower = true; if (columnUpper[iColumn] < 1.0e20) doUpper = true; } } if (!numberNormal) { printf("Putting back one gub row to make non-empty\n"); for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++) mark[numberNormal++] = iColumn; putGub++; numberGub--; } ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark); int numberGubColumns = numberColumns - numberNormal; // sort gubs so monotonic int * which = new int[numberGub]; int i; for (i = 0; i < numberGub; i++) which[i] = i; CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which); int * temp1 = new int [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp1[i] = gubEnd[putGub+k]; } memcpy(gubEnd + putGub, temp1, numberGub * sizeof(int)); delete [] temp1; double * temp2 = new double [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = lower[putGub+k]; } memcpy(lower + putGub, temp2, numberGub * sizeof(double)); for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = upper[putGub+k]; } memcpy(upper + putGub, temp2, numberGub * sizeof(double)); delete [] temp2; delete [] which; numberElements -= numberGubColumns; int * start2 = new int[numberGubColumns+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; double * cost2 = new double [numberGubColumns]; double * lowerColumn2 = NULL; if (doLower) { lowerColumn2 = new double [numberGubColumns]; CoinFillN(lowerColumn2, numberGubColumns, 0.0); } double * upperColumn2 = NULL; if (doUpper) { upperColumn2 = new double [numberGubColumns]; CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX); } numberElements = 0; int numberNonGubRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (!rowIsGub[iRow]) rowIsGub[iRow] = numberNonGubRows++; } numberColumns = 0; gubStart[0] = 0; start2[0] = 0; const double * cost = model.objective(); for (int iSet = 0; iSet < numberGub; iSet++) { int iStart = gubStart[iSet+putGub]; int iEnd = gubEnd[iSet+putGub]; for (int k = iStart; k < iEnd; k++) { cost2[numberColumns] = cost[k]; if (columnLower[k]) lowerColumn2[numberColumns] = columnLower[k]; if (columnUpper[k] < 1.0e20) upperColumn2[numberColumns] = columnUpper[k]; for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int iRow = rowIsGub[row[j]]; if (iRow >= 0) { row2[numberElements] = iRow; element2[numberElements++] = elementByColumn[j]; } } start2[++numberColumns] = numberElements; } gubStart[iSet+1] = numberColumns; } model2.replaceMatrix(new ClpGubDynamicMatrix(&model2, numberGub, numberColumns, gubStart, lower + putGub, upper + putGub, start2, row2, element2, cost2, lowerColumn2, upperColumn2)); delete [] rowIsGub; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lowerColumn2; delete [] upperColumn2; // For now scaling off model2.scaling(0); // Do partial dantzig ClpPrimalColumnSteepest dantzig(5); model2.setPrimalColumnPivotAlgorithm(dantzig); //model2.messageHandler()->setLogLevel(63); model2.setFactorizationFrequency(maxFactor); model2.setMaximumIterations(4000000); double time1 = CoinCpuTime(); model2.primal(); { ClpGubDynamicMatrix * gubMatrix = dynamic_cast< ClpGubDynamicMatrix*>(model2.clpMatrix()); assert(gubMatrix); const double * solution = model2.primalColumnSolution(); int numberGubColumns = gubMatrix->numberGubColumns(); int firstOdd = gubMatrix->firstDynamic(); int lastOdd = gubMatrix->firstAvailable(); int numberTotalColumns = firstOdd + numberGubColumns; int numberRows = model2.numberRows(); char * status = new char [numberTotalColumns]; double * gubSolution = new double [numberTotalColumns]; int numberSets = gubMatrix->numberSets(); const int * id = gubMatrix->id(); int i; const double * lowerColumn = gubMatrix->lowerColumn(); const double * upperColumn = gubMatrix->upperColumn(); for (i = 0; i < numberGubColumns; i++) { if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atUpperBound) { gubSolution[i+firstOdd] = upperColumn[i]; status[i+firstOdd] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpGubDynamicMatrix::atLowerBound && lowerColumn) { gubSolution[i+firstOdd] = lowerColumn[i]; status[i+firstOdd] = 1; } else { gubSolution[i+firstOdd] = 0.0; status[i+firstOdd] = 1; } } for (i = 0; i < firstOdd; i++) { ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[i] = 2; else if (thisStatus == ClpSimplex::isFixed) status[i] = 3; else abort(); gubSolution[i] = solution[i]; } for (i = firstOdd; i < lastOdd; i++) { int iBig = id[i-firstOdd] + firstOdd; ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[iBig] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[iBig] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[iBig] = 2; else if (thisStatus == ClpSimplex::isFixed) status[iBig] = 3; else abort(); gubSolution[iBig] = solution[i]; } char * rowStatus = new char[numberRows]; for (i = 0; i < numberRows; i++) { ClpSimplex::Status thisStatus = model2.getRowStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[i] = 3; else abort(); } char * setStatus = new char[numberSets]; int * keyVariable = new int[numberSets]; memcpy(keyVariable, gubMatrix->keyVariable(), numberSets * sizeof(int)); for (i = 0; i < numberSets; i++) { int iKey = keyVariable[i]; if (iKey > lastOdd) iKey = numberTotalColumns + i; else iKey = id[iKey-firstOdd] + firstOdd; keyVariable[i] = iKey; ClpSimplex::Status thisStatus = gubMatrix->getStatus(i); if (thisStatus == ClpSimplex::basic) setStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) setStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) setStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) setStatus[i] = 3; else abort(); } FILE * fp = fopen("xx.sol", "w"); fwrite(gubSolution, sizeof(double), numberTotalColumns, fp); fwrite(status, sizeof(char), numberTotalColumns, fp); const double * rowsol = model2.primalRowSolution(); int originalNumberRows = model.numberRows(); double * rowsol2 = new double[originalNumberRows]; memset(rowsol2, 0, originalNumberRows * sizeof(double)); model.times(1.0, gubSolution, rowsol2); for (i = 0; i < numberRows; i++) assert(fabs(rowsol[i] - rowsol2[i]) < 1.0e-3); //for (;i // 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. */ class ClpSimplex; class MyMessageHandler : public CoinMessageHandler { public: /**@name Overrides */ //@{ virtual int print(); //@} /**@name set and get */ //@{ /// Model const ClpSimplex * model() const; void setModel(ClpSimplex * model); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ MyMessageHandler(); /// Constructor with pointer to model MyMessageHandler(ClpSimplex * model, FILE * userPointer = NULL); /** Destructor */ virtual ~MyMessageHandler(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ MyMessageHandler(const MyMessageHandler&); /** The copy constructor from an CoinSimplexMessageHandler. */ MyMessageHandler(const CoinMessageHandler&); MyMessageHandler& operator= (const MyMessageHandler&); /// Clone virtual CoinMessageHandler * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer back to model ClpSimplex * model_; //@} }; //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyMessageHandler::MyMessageHandler() : CoinMessageHandler(), model_(NULL) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyMessageHandler::MyMessageHandler(const MyMessageHandler & rhs) : CoinMessageHandler(rhs), model_(rhs.model_) { } MyMessageHandler::MyMessageHandler(const CoinMessageHandler & rhs) : CoinMessageHandler(), model_(NULL) { } // Constructor with pointer to model MyMessageHandler::MyMessageHandler(ClpSimplex * model, FILE * userPointer) : CoinMessageHandler(), model_(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyMessageHandler::~MyMessageHandler() { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyMessageHandler & MyMessageHandler::operator= (const MyMessageHandler & rhs) { if (this != &rhs) { CoinMessageHandler::operator= (rhs); model_ = rhs.model_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CoinMessageHandler * MyMessageHandler::clone() const { return new MyMessageHandler(*this); } // Print out values from first 20 messages static int times = 0; int MyMessageHandler::print() { // You could have added a callback flag if you had wanted - see Clp_C_Interface.c times++; if (times <= 20) { int messageNumber = currentMessage().externalNumber(); if (currentSource() != "Clp") messageNumber += 1000000; int i; int nDouble = numberDoubleFields(); printf("%d doubles - ", nDouble); for (i = 0; i < nDouble; i++) printf("%g ", doubleValue(i)); printf("\n");; int nInt = numberIntFields(); printf("%d ints - ", nInt); for (i = 0; i < nInt; i++) printf("%d ", intValue(i)); printf("\n");; int nString = numberStringFields(); printf("%d strings - ", nString); for (i = 0; i < nString; i++) printf("%s ", stringValue(i).c_str()); printf("\n");; } return CoinMessageHandler::print(); } const ClpSimplex * MyMessageHandler::model() const { return model_; } void MyMessageHandler::setModel(ClpSimplex * model) { model_ = model; } int main(int argc, const char *argv[]) { ClpSimplex model; // Message handler MyMessageHandler messageHandler(&model); std::cout << "Testing derived message handler" << std::endl; model.passInMessageHandler(&messageHandler); int status; // Keep names when reading an mps file if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1], true); if (status) { fprintf(stderr, "Bad readMps %s\n", argv[1]); fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } double time1 = CoinCpuTime(); /* This driver shows how to do presolve.by hand (rather than with initialSolve) */ ClpSimplex * model2; ClpPresolve pinfo; int numberPasses = 5; // can change this /* Use a tolerance of 1.0e-8 for feasibility, treat problem as not being integer, do "numberpasses" passes and throw away names in presolved model */ model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false); if (!model2) { fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-8); fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-8); // model was infeasible - maybe try again with looser tolerances model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false); if (!model2) { fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-7); fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-7); exit(2); } } // change factorization frequency from 200 model2->setFactorizationFrequency(100 + model2->numberRows() / 50); if (argc < 3 || !strstr(argv[2], "primal")) { // Use the dual algorithm unless user said "primal" /* faster if bounds tightened as then dual can flip variables to other bound to stay dual feasible. We can trash the bounds as this model is going to be thrown away */ int numberInfeasibilities = model2->tightenPrimalBounds(); if (numberInfeasibilities) std::cout << "** Analysis indicates model infeasible" << std::endl; model2->crash(1000.0, 2); ClpDualRowSteepest steep(1); model2->setDualRowPivotAlgorithm(steep); model2->dual(); } else { ClpPrimalColumnSteepest steep(1); model2->setPrimalColumnPivotAlgorithm(steep); model2->primal(); } pinfo.postsolve(true); int numberIterations = model2->numberIterations();; delete model2; /* After this postsolve model should be optimal. We can use checkSolution and test feasibility */ model.checkSolution(); if (model.numberDualInfeasibilities() || model.numberPrimalInfeasibilities()) printf("%g dual %g(%d) Primal %g(%d)\n", model.objectiveValue(), model.sumDualInfeasibilities(), model.numberDualInfeasibilities(), model.sumPrimalInfeasibilities(), model.numberPrimalInfeasibilities()); // But resolve for safety model.primal(1); numberIterations += model.numberIterations();; // for running timing tests std::cout << argv[1] << " Objective " << model.objectiveValue() << " took " << numberIterations << " iterations and " << CoinCpuTime() - time1 << " seconds" << std::endl; std::string modelName; model.getStrParam(ClpProbName, modelName); std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " << model.numberColumns() << " columns" << std::endl; // remove this to print solution exit(0); /* 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 columns */ #if 0 int numberRows = model.numberRows(); // Alternatively getRowActivity() double * rowPrimal = model.primalRowSolution(); // Alternatively getRowPrice() double * rowDual = model.dualRowSolution(); // Alternatively getRowLower() double * rowLower = model.rowLower(); // Alternatively getRowUpper() double * rowUpper = model.rowUpper(); // Alternatively getRowObjCoefficients() double * rowObjective = model.rowObjective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Row names const std::vector * rowNames = model.rowNames(); int iRow; std::cout << " Primal Dual Lower Upper (Cost)" << std::endl; for (iRow = 0; iRow < numberRows; iRow++) { double value; std::cout << std::setw(6) << iRow << " " << std::setw(8) << (*rowNames)[iRow]; value = rowPrimal[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowDual[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowLower[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowUpper[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; if (rowObjective) { value = rowObjective[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; } std::cout << std::endl; } #endif std::cout << "--------------------------------------" << std::endl; // Columns int numberColumns = model.numberColumns(); // Alternatively getColSolution() double * columnPrimal = model.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model.columnLower(); // Alternatively getColUpper() double * columnUpper = model.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model.objective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Column names const std::vector * columnNames = model.columnNames(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; value = columnPrimal[iColumn]; if (fabs(value) > 1.0e-8) { std::cout << std::setw(6) << iColumn << " " << std::setw(8) << (*columnNames)[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } } std::cout << "--------------------------------------" << std::endl; return 0; } Clp-1.15.10/examples/piece.cpp0000644000076600007660000002451112131314313014455 0ustar coincoin/* $Id: piece.cpp 1941 2013-04-10 16:52:27Z 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). /* This simple example takes a matrix read in by CoinMpsIo, deletes every second column and solves the resulting problem */ #include "ClpSimplex.hpp" #include "ClpNonLinearCost.hpp" #include "CoinMpsIO.hpp" #include int main(int argc, const char *argv[]) { int status; CoinMpsIO m; if (argc < 2) status = m.readMps("model1.mps", ""); else status = m.readMps(argv[1], ""); if (status) { fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } // Load up model1 - so we can use known good solution ClpSimplex model1; model1.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model1.dual(); // Get data arrays const CoinPackedMatrix * matrix1 = m.getMatrixByCol(); const int * start1 = matrix1->getVectorStarts(); const int * length1 = matrix1->getVectorLengths(); const int * row1 = matrix1->getIndices(); const double * element1 = matrix1->getElements(); const double * columnLower1 = m.getColLower(); const double * columnUpper1 = m.getColUpper(); const double * rowLower1 = m.getRowLower(); const double * rowUpper1 = m.getRowUpper(); const double * objective1 = m.getObjCoefficients(); int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); int numberElements = m.getNumElements(); // Get new arrays int numberColumns2 = (numberColumns + 1); int * start2 = new int[numberColumns2+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; int * segstart = new int[numberColumns+1]; double * breakpt = new double[2*numberColumns]; double * slope = new double[2*numberColumns]; double * objective2 = new double[numberColumns2]; double * columnLower2 = new double[numberColumns2]; double * columnUpper2 = new double[numberColumns2]; double * rowLower2 = new double[numberRows]; double * rowUpper2 = new double[numberRows]; // We need to modify rhs memcpy(rowLower2, rowLower1, numberRows * sizeof(double)); memcpy(rowUpper2, rowUpper1, numberRows * sizeof(double)); double objectiveOffset = 0.0; // For new solution double * newSolution = new double [numberColumns]; const double * oldSolution = model1.primalColumnSolution(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) printf("%g ", oldSolution[iColumn]); printf("\n"); numberColumns2 = 0; numberElements = 0; start2[0] = 0; int segptr = 0; segstart[0] = 0; // Now check for duplicates for (iColumn = 0; iColumn < numberColumns; iColumn++) { // test if column identical to next column bool ifcopy = 1; if (iColumn < numberColumns - 1) { int joff = length1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { if (row1[j] != row1[j+joff]) { ifcopy = 0; break; } if (element1[j] != element1[j+joff]) { ifcopy = 0; break; } } } else { ifcopy = 0; } //if (iColumn>47||iColumn<45) //ifcopy=0; if (ifcopy) { double lo1 = columnLower1[iColumn]; double up1 = columnUpper1[iColumn]; double obj1 = objective1[iColumn]; double sol1 = oldSolution[iColumn]; double lo2 = columnLower1[iColumn+1]; double up2 = columnUpper1[iColumn+1]; double obj2 = objective1[iColumn+1]; double sol2 = oldSolution[iColumn+1]; if (fabs(up1 - lo2) > 1.0e-8) { // try other way double temp; temp = lo1; lo1 = lo2; lo2 = temp; temp = up1; up1 = up2; up2 = temp; temp = obj1; obj1 = obj2; obj2 = temp; temp = sol1; sol1 = sol2; sol2 = temp; assert(fabs(up1 - lo2) < 1.0e-8); } // subtract out from rhs double fixed = up1; // do offset objectiveOffset += fixed * obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { int iRow = row1[j]; double value = element1[j]; if (rowLower2[iRow] > -1.0e30) rowLower2[iRow] -= value * fixed; if (rowUpper2[iRow] < 1.0e30) rowUpper2[iRow] -= value * fixed; } newSolution[numberColumns2] = fixed; if (fabs(sol1 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol1; if (fabs(sol2 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol2; columnLower2[numberColumns2] = lo1; columnUpper2[numberColumns2] = up2; objective2[numberColumns2] = 0.0; breakpt[segptr] = lo1; slope[segptr++] = obj1; breakpt[segptr] = lo2; slope[segptr++] = obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } start2[++numberColumns2] = numberElements; breakpt[segptr] = up2; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; iColumn++; // skip next column } else { // normal column columnLower2[numberColumns2] = columnLower1[iColumn]; columnUpper2[numberColumns2] = columnUpper1[iColumn]; objective2[numberColumns2] = objective1[iColumn]; breakpt[segptr] = columnLower1[iColumn]; slope[segptr++] = objective1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } newSolution[numberColumns2] = oldSolution[iColumn]; start2[++numberColumns2] = numberElements; breakpt[segptr] = columnUpper1[iColumn]; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; } } // print new number of columns, elements printf("New number of columns = %d\n", numberColumns2); printf("New number of elements = %d\n", numberElements); printf("Objective offset is %g\n", objectiveOffset); ClpSimplex model; // load up model.loadProblem(numberColumns2, numberRows, start2, row2, element2, columnLower2, columnUpper2, objective2, rowLower2, rowUpper2); model.scaling(0); model.setDblParam(ClpObjOffset, -objectiveOffset); // Create nonlinear objective int returnCode = model.createPiecewiseLinearCosts(segstart, breakpt, slope); if( returnCode != 0 ) { printf("Unexpected return code %d from model.createPiecewiseLinearCosts()\n", returnCode); return returnCode; } // delete delete [] segstart; delete [] breakpt; delete [] slope; delete [] start2; delete [] row2 ; delete [] element2; delete [] objective2; delete [] columnLower2; delete [] columnUpper2; delete [] rowLower2; delete [] rowUpper2; // copy in solution - (should be optimal) model.allSlackBasis(); memcpy(model.primalColumnSolution(), newSolution, numberColumns2 * sizeof(double)); //memcpy(model.columnLower(),newSolution,numberColumns2*sizeof(double)); //memcpy(model.columnUpper(),newSolution,numberColumns2*sizeof(double)); delete [] newSolution; //model.setLogLevel(63); const double * solution = model.primalColumnSolution(); double * saveSol = new double[numberColumns2]; memcpy(saveSol, solution, numberColumns2 * sizeof(double)); for (iColumn = 0; iColumn < numberColumns2; iColumn++) printf("%g ", solution[iColumn]); printf("\n"); // solve model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.allSlackBasis(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.setLogLevel(63); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); return 0; } Clp-1.15.10/examples/driverC.c0000644000076600007660000001052411510657150014436 0ustar coincoin/* $Id: driverC.c 1662 2011-01-04 17:52:40Z lou $ */ /* 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). */ /* This example shows the use of the "C" interface */ #include "Clp_C_Interface.h" #include #include #include #include /* Call back function - just says whenever it gets Clp0005 or Coin0002 */ static void callBack(Clp_Simplex * model, int messageNumber, int nDouble, const double * vDouble, int nInt, const int * vInt, int nString, char ** vString) { 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]); } } int main(int argc, const char *argv[]) { /* Get default model */ Clp_Simplex * model = Clp_newModel(); int status; /* register callback */ Clp_registerCallBack(model, callBack); /* Keep names when reading an mps file */ if (argc < 2) { #if defined(SAMPLEDIR) status = Clp_readMps(model, SAMPLEDIR "/p0033.mps", 1, 0); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = Clp_readMps(model, argv[1], 1, 0); if (status) { fprintf(stderr, "Bad readMps %s\n", argv[1]); fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } if (argc < 3 || !strstr(argv[2], "primal")) { /* Use the dual algorithm unless user said "primal" */ Clp_initialDualSolve(model); } else { Clp_initialPrimalSolve(model); } { char modelName[80]; Clp_problemName(model, 80, modelName); printf("Model %s has %d rows and %d columns\n", modelName, Clp_numberRows(model), Clp_numberColumns(model)); } /* remove this to print solution */ /*exit(0); */ { /* 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 columns */ /* Columns */ int numberColumns = Clp_numberColumns(model); int iColumn; /* Alternatively getColSolution(model) */ double * columnPrimal = Clp_primalColumnSolution(model); /* Alternatively getReducedCost(model) */ double * columnDual = Clp_dualColumnSolution(model); /* Alternatively getColLower(model) */ double * columnLower = Clp_columnLower(model); /* Alternatively getColUpper(model) */ double * columnUpper = Clp_columnUpper(model); /* Alternatively getObjCoefficients(model) */ double * columnObjective = Clp_objective(model); printf("--------------------------------------\n"); /* If we have not kept names (parameter to readMps) this will be 0 */ assert(Clp_lengthNames(model)); printf(" Primal Dual Lower Upper Cost\n"); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; value = columnPrimal[iColumn]; if (value > 1.0e-8 || value < -1.0e-8) { char name[20]; Clp_columnName(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"); } return 0; } Clp-1.15.10/examples/dualCuts.cpp0000644000076600007660000003055011510657150015165 0ustar coincoin/* $Id: dualCuts.cpp 1662 2011-01-04 17:52:40Z lou $ */ /* Copyright (C) 2003, International Business Machines Corporation and others. All Rights Reserved. This sample program is designed to illustrate programming techniques using CoinLP, has not been thoroughly tested and comes without any warranty whatsoever. You may copy, modify and distribute this sample program without any restrictions whatsoever and without any payment to anyone. */ #include "ClpSimplex.hpp" #include "ClpPresolve.hpp" #include "ClpFactorization.hpp" #include "CoinSort.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinMpsIO.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { status = model.readMps("small.mps", true); } else { status = model.readMps(argv[1], false); } if (status) exit(10); /* This driver implements a method of treating a problem as all cuts. So it adds in all E rows, solves and then adds in violated rows. */ double time1 = CoinCpuTime(); ClpSimplex * model2; ClpPresolve pinfo; int numberPasses = 5; // can change this /* Use a tolerance of 1.0e-8 for feasibility, treat problem as not being integer, do "numberpasses" passes and throw away names in presolved model */ model2 = pinfo.presolvedModel(model, 1.0e-8, false, numberPasses, false); if (!model2) { fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-8); fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-8); // model was infeasible - maybe try again with looser tolerances model2 = pinfo.presolvedModel(model, 1.0e-7, false, numberPasses, false); if (!model2) { fprintf(stderr, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-7); fprintf(stdout, "ClpPresolve says %s is infeasible with tolerance of %g\n", argv[1], 1.0e-7); exit(2); } } // change factorization frequency from 200 model2->setFactorizationFrequency(100 + model2->numberRows() / 50); int numberColumns = model2->numberColumns(); int originalNumberRows = model2->numberRows(); // We will need arrays to choose rows to add double * weight = new double [originalNumberRows]; int * sort = new int [originalNumberRows]; int numberSort = 0; char * take = new char [originalNumberRows]; const double * rowLower = model2->rowLower(); const double * rowUpper = model2->rowUpper(); int iRow, iColumn; // Set up initial list numberSort = 0; for (iRow = 0; iRow < originalNumberRows; iRow++) { weight[iRow] = 1.123e50; if (rowLower[iRow] == rowUpper[iRow]) { sort[numberSort++] = iRow; weight[iRow] = 0.0; } } numberSort /= 2; // Just add this number of rows each time in small problem int smallNumberRows = 2 * numberColumns; smallNumberRows = CoinMin(smallNumberRows, originalNumberRows / 20); // and pad out with random rows double ratio = ((double)(smallNumberRows - numberSort)) / ((double) originalNumberRows); for (iRow = 0; iRow < originalNumberRows; iRow++) { if (weight[iRow] == 1.123e50 && CoinDrand48() < ratio) sort[numberSort++] = iRow; } /* This is optional. The best thing to do is to miss out random rows and do a set which makes dual feasible. If that is not possible then make sure variables have bounds. One way that normally works is to automatically tighten bounds. */ #if 0 // However for some we need to do anyway double * columnLower = model2->columnLower(); double * columnUpper = model2->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnLower[iColumn] = CoinMax(-1.0e6, columnLower[iColumn]); columnUpper[iColumn] = CoinMin(1.0e6, columnUpper[iColumn]); } #endif model2->tightenPrimalBounds(-1.0e4, true); printf("%d rows in initial problem\n", numberSort); double * fullSolution = model2->primalRowSolution(); // Just do this number of passes int maxPass = 50; // And take out slack rows until this pass int takeOutPass = 30; int iPass; const int * start = model2->clpMatrix()->getVectorStarts(); const int * length = model2->clpMatrix()->getVectorLengths(); const int * row = model2->clpMatrix()->getIndices(); int * whichColumns = new int [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) whichColumns[iColumn] = iColumn; int numberSmallColumns = numberColumns; for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); // Cleaner this way std::sort(sort, sort + numberSort); // Create small problem ClpSimplex small(model2, numberSort, sort, numberSmallColumns, whichColumns); small.setFactorizationFrequency(100 + numberSort / 200); //small.setPerturbation(50); //small.setLogLevel(63); // A variation is to just do N iterations //if (iPass) //small.setMaximumIterations(100); // Solve small.factorization()->messageLevel(8); if (iPass) { small.dual(); } else { small.writeMps("continf.mps"); ClpSolve solveOptions; solveOptions.setSolveType(ClpSolve::useDual); //solveOptions.setSolveType(ClpSolve::usePrimalorSprint); //solveOptions.setSpecialOption(1,2,200); // idiot small.initialSolve(solveOptions); } bool dualInfeasible = (small.status() == 2); // move solution back double * solution = model2->primalColumnSolution(); const double * smallSolution = small.primalColumnSolution(); for (int j = 0; j < numberSmallColumns; j++) { iColumn = whichColumns[j]; solution[iColumn] = smallSolution[j]; model2->setColumnStatus(iColumn, small.getColumnStatus(j)); } for (iRow = 0; iRow < numberSort; iRow++) { int kRow = sort[iRow]; model2->setRowStatus(kRow, small.getRowStatus(iRow)); } // compute full solution memset(fullSolution, 0, originalNumberRows * sizeof(double)); model2->times(1.0, model2->primalColumnSolution(), fullSolution); if (iPass != maxPass - 1) { // Mark row as not looked at for (iRow = 0; iRow < originalNumberRows; iRow++) weight[iRow] = 1.123e50; // Look at rows already in small problem int iSort; int numberDropped = 0; int numberKept = 0; int numberBinding = 0; int numberInfeasibilities = 0; double sumInfeasibilities = 0.0; for (iSort = 0; iSort < numberSort; iSort++) { iRow = sort[iSort]; //printf("%d %g %g\n",iRow,fullSolution[iRow],small.primalRowSolution()[iSort]); if (model2->getRowStatus(iRow) == ClpSimplex::basic) { // Basic - we can get rid of if early on if (iPass < takeOutPass && !dualInfeasible) { // may have hit max iterations so check double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow], rowLower[iRow] - fullSolution[iRow]); weight[iRow] = -infeasibility; if (infeasibility > 1.0e-8) { numberInfeasibilities++; sumInfeasibilities += infeasibility; } else { weight[iRow] = 1.0; numberDropped++; } } else { // keep weight[iRow] = -1.0e40; numberKept++; } } else { // keep weight[iRow] = -1.0e50; numberKept++; numberBinding++; } } // Now rest for (iRow = 0; iRow < originalNumberRows; iRow++) { sort[iRow] = iRow; if (weight[iRow] == 1.123e50) { // not looked at yet double infeasibility = CoinMax(fullSolution[iRow] - rowUpper[iRow], rowLower[iRow] - fullSolution[iRow]); weight[iRow] = -infeasibility; if (infeasibility > 1.0e-8) { numberInfeasibilities++; sumInfeasibilities += infeasibility; } } } // sort CoinSort_2(weight, weight + originalNumberRows, sort); numberSort = CoinMin(originalNumberRows, smallNumberRows + numberKept); memset(take, 0, originalNumberRows); for (iRow = 0; iRow < numberSort; iRow++) take[sort[iRow]] = 1; numberSmallColumns = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int n = 0; for (int j = start[iColumn]; j < start[iColumn] + length[iColumn]; j++) { int iRow = row[j]; if (take[iRow]) n++; } if (n) whichColumns[numberSmallColumns++] = iColumn; } printf("%d rows binding, %d rows kept, %d rows dropped - new size %d rows, %d columns\n", numberBinding, numberKept, numberDropped, numberSort, numberSmallColumns); printf("%d rows are infeasible - sum is %g\n", numberInfeasibilities, sumInfeasibilities); if (!numberInfeasibilities) { printf("Exiting as looks optimal\n"); break; } numberInfeasibilities = 0; sumInfeasibilities = 0.0; for (iSort = 0; iSort < numberSort; iSort++) { if (weight[iSort] > -1.0e30 && weight[iSort] < -1.0e-8) { numberInfeasibilities++; sumInfeasibilities += -weight[iSort]; } } printf("in small model %d rows are infeasible - sum is %g\n", numberInfeasibilities, sumInfeasibilities); } } delete [] weight; delete [] sort; delete [] whichColumns; delete [] take; // If problem is big you may wish to skip this model2->dual(); int numberBinding = 0; for (iRow = 0; iRow < originalNumberRows; iRow++) { if (model2->getRowStatus(iRow) != ClpSimplex::basic) numberBinding++; } printf("%d binding rows at end\n", numberBinding); pinfo.postsolve(true); int numberIterations = model2->numberIterations();; delete model2; /* After this postsolve model should be optimal. We can use checkSolution and test feasibility */ model.checkSolution(); if (model.numberDualInfeasibilities() || model.numberPrimalInfeasibilities()) printf("%g dual %g(%d) Primal %g(%d)\n", model.objectiveValue(), model.sumDualInfeasibilities(), model.numberDualInfeasibilities(), model.sumPrimalInfeasibilities(), model.numberPrimalInfeasibilities()); // But resolve for safety model.primal(1); numberIterations += model.numberIterations();; printf("Solve took %g seconds\n", CoinCpuTime() - time1); return 0; } Clp-1.15.10/examples/rowColumn.cpp0000644000076600007660000001015611402524254015364 0ustar coincoin/* $Id: rowColumn.cpp 1559 2010-06-05 19:42:36Z stefan $ */ /* Copyright (C) 2004, International Business Machines Corporation and others. All Rights Reserved. This sample program is designed to illustrate programming techniques using CoinLP, has not been thoroughly tested and comes without any warranty whatsoever. You may copy, modify and distribute this sample program without any restrictions whatsoever and without any payment to anyone. */ #include "ClpSimplex.hpp" #include #include int main(int argc, const char *argv[]) { ClpSimplex modelByRow, modelByColumn; // This very simple example shows how to create a model by row and by column int numberRows = 3; int numberColumns = 5; // Rim of problem is same in both cases double objective [] = {1000.0, 400.0, 500.0, 10000.0, 10000.0}; double columnLower[] = {0.0, 0.0, 0.0, 0.0, 0.0}; double columnUpper[] = {COIN_DBL_MAX, COIN_DBL_MAX, COIN_DBL_MAX, 20.0, 20.0}; double rowLower[] = {20.0, -COIN_DBL_MAX, 8.0}; double rowUpper[] = {COIN_DBL_MAX, 30.0, 8.0}; // Matrix by row int rowStart[] = {0, 5, 10, 13}; int column[] = {0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2 }; double elementByRow[] = {8.0, 5.0, 4.0, 4.0, -4.0, 8.0, 4.0, 5.0, 5.0, -5.0, 1.0, -1.0, -1.0 }; // Matrix by column int columnStart[] = {0, 3, 6, 9, 11, 13}; int row[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 0, 1 }; double elementByColumn[] = {8.0, 8.0, 1.0, 5.0, 4.0, -1.0, 4.0, 5.0, -1.0, 4.0, 5.0, -4.0, -5.0 }; int numberElements; // Do column version first as it can be done two ways // a) As one step using matrix as stored modelByColumn.loadProblem(numberColumns, numberRows, columnStart, row, elementByColumn, columnLower, columnUpper, objective, rowLower, rowUpper); // Solve modelByColumn.dual(); // check value of objective assert(fabs(modelByColumn.objectiveValue() - 76000.0) < 1.0e-7); // b) As two steps - first creating a CoinPackedMatrix // NULL for column lengths indicate they are stored without gaps // Look at CoinPackedMatrix.hpp for other ways to create a matrix numberElements = columnStart[numberColumns]; CoinPackedMatrix byColumn(true, numberRows, numberColumns, numberElements, elementByColumn, row, columnStart, NULL); // now load matrix and rim modelByColumn.loadProblem(byColumn, columnLower, columnUpper, objective, rowLower, rowUpper); // Solve modelByColumn.dual(); // check value of objective assert(fabs(modelByColumn.objectiveValue() - 76000.0) < 1.0e-7); // Now do by row // The false says row ordered so numberRows and numberColumns swapped - see CoinPackedMatrix.hpp assert(numberElements == rowStart[numberRows]); // check same number of elements in each copy CoinPackedMatrix byRow(false, numberColumns, numberRows, numberElements, elementByRow, column, rowStart, NULL); // now load matrix and rim modelByRow.loadProblem(byRow, columnLower, columnUpper, objective, rowLower, rowUpper); // Solve modelByRow.dual(); // check value of objective assert(fabs(modelByRow.objectiveValue() - 76000.0) < 1.0e-7); // write solution const double * solution = modelByRow.primalColumnSolution(); for (int i = 0; i < numberColumns; i++) { if (solution[i]) printf("Column %d has value %g\n", i, solution[i]); } modelByRow.writeMps("Tiny.mps"); return 0; } Clp-1.15.10/examples/minimum.cpp0000644000076600007660000000142012131314313015035 0ustar coincoin/* $Id: minimum.cpp 1941 2013-04-10 16:52:27Z 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 "ClpSimplex.hpp" int main(int argc, const char *argv[]) { ClpSimplex model; int status; if (argc < 2) { #if defined(SAMPLEDIR) /* SAMPLEDIR should "path/to/Data/Sample" Include the quotes and final path separator. */ status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1]); if (!status) { model.primal(); } return 0; } Clp-1.15.10/examples/addColumns.cpp0000644000076600007660000002626711510657150015504 0ustar coincoin/* $Id: addColumns.cpp 1662 2011-01-04 17:52:40Z 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). // This is a simple example to create a model by column #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinBuild.hpp" #include "CoinModel.hpp" #include #include int main(int argc, const char *argv[]) { { // Empty model ClpSimplex model; // Bounds on rows - as dense vector double lower[] = {2.0, 1.0}; double upper[] = {COIN_DBL_MAX, 1.0}; // Create space for 2 rows model.resize(2, 0); // Fill in int i; // Now row bounds for (i = 0; i < 2; i++) { model.setRowLower(i, lower[i]); model.setRowUpper(i, upper[i]); } // Now add column 1 int column1Index[] = {0, 1}; double column1Value[] = {1.0, 1.0}; model.addColumn(2, column1Index, column1Value, 0.0, 2, 1.0); // Now add column 2 int column2Index[] = {1}; double column2Value[] = { -5.0}; model.addColumn(1, column2Index, column2Value, 0.0, COIN_DBL_MAX, 0.0); // Now add column 3 int column3Index[] = {0, 1}; double column3Value[] = {1.0, 1.0}; model.addColumn(2, column3Index, column3Value, 0.0, 4.0, 4.0); // solve model.dual(); /* Adding one column at a time has a significant overhead so let's try a more complicated but faster way First time adding in 10000 columns one by one */ model.allSlackBasis(); ClpSimplex modelSave = model; double time1 = CoinCpuTime(); int k; for (k = 0; k < 10000; k++) { int column2Index[] = {0, 1}; double column2Value[] = {1.0, -5.0}; model.addColumn(2, column2Index, column2Value, 0.0, 1.0, 10000.0); } printf("Time for 10000 addColumn is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; // Now use build CoinBuild buildObject; time1 = CoinCpuTime(); for (k = 0; k < 100000; k++) { int column2Index[] = {0, 1}; double column2Value[] = {1.0, -5.0}; buildObject.addColumn(2, column2Index, column2Value, 0.0, 1.0, 10000.0); } model.addColumns(buildObject); printf("Time for 100000 addColumn using CoinBuild is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; // Now use build +-1 int del[] = {0, 1, 2}; model.deleteColumns(3, del); CoinBuild buildObject2; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int column2Index[] = {0, 1}; double column2Value[] = {1.0, 1.0, -1.0}; int bias = k & 1; buildObject2.addColumn(2, column2Index, column2Value + bias, 0.0, 1.0, 10000.0); } model.addColumns(buildObject2, true); printf("Time for 10000 addColumn using CoinBuild+-1 is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; // Now use build +-1 model.deleteColumns(3, del); CoinModel modelObject2; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int column2Index[] = {0, 1}; double column2Value[] = {1.0, 1.0, -1.0}; int bias = k & 1; modelObject2.addColumn(2, column2Index, column2Value + bias, 0.0, 1.0, 10000.0); } model.addColumns(modelObject2, true); printf("Time for 10000 addColumn using CoinModel+-1 is %g\n", CoinCpuTime() - time1); //model.writeMps("xx.mps"); model.dual(); model = modelSave; // Now use model CoinModel modelObject; time1 = CoinCpuTime(); for (k = 0; k < 100000; k++) { int column2Index[] = {0, 1}; double column2Value[] = {1.0, -5.0}; modelObject.addColumn(2, column2Index, column2Value, 0.0, 1.0, 10000.0); } model.addColumns(modelObject); printf("Time for 100000 addColumn using CoinModel is %g\n", CoinCpuTime() - time1); model.dual(); // Print column solution Just first 3 columns int numberColumns = model.numberColumns(); numberColumns = CoinMin(3, numberColumns); // Alternatively getColSolution() double * columnPrimal = model.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model.columnLower(); // Alternatively getColUpper() double * columnUpper = model.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model.objective(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; std::cout << std::setw(6) << iColumn << " "; value = columnPrimal[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; } { // Now copy a model ClpSimplex model; int status; if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1]); if (status) { printf("errors on input\n"); exit(77); } model.initialSolve(); int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); // Start off model2 ClpSimplex model2; model2.addRows(numberRows, rowLower, rowUpper, NULL); // Build object CoinBuild buildObject; // Add columns const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); const double * objective = model.objective(); CoinPackedMatrix * matrix = model.matrix(); const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start, columnLower[iColumn], columnUpper[iColumn], objective[iColumn]); } // add in model2.addColumns(buildObject); model2.initialSolve(); } { // and again ClpSimplex model; int status; if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1]); if (status) { printf("errors on input\n"); exit(77); } model.initialSolve(); int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); // Build object CoinModel buildObject; for (int iRow = 0; iRow < numberRows; iRow++) buildObject.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]); // Add columns const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); const double * objective = model.objective(); CoinPackedMatrix * matrix = model.matrix(); const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; buildObject.addColumn(columnLength[iColumn], row + start, elementByColumn + start, columnLower[iColumn], columnUpper[iColumn], objective[iColumn]); } // add in ClpSimplex model2; model2.loadProblem(buildObject); model2.initialSolve(); } return 0; } Clp-1.15.10/examples/addRows.cpp0000644000076600007660000002731212131314313014775 0ustar coincoin/* $Id: addRows.cpp 1941 2013-04-10 16:52:27Z 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). // This is a simple example to create a model by row #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinBuild.hpp" #include "CoinModel.hpp" #include #include int main(int argc, const char *argv[]) { try { // Empty model ClpSimplex model; // Objective - just nonzeros int objIndex[] = {0, 2}; double objValue[] = {1.0, 4.0}; // Upper bounds - as dense vector double upper[] = {2.0, COIN_DBL_MAX, 4.0}; // Create space for 3 columns model.resize(0, 3); // Fill in int i; // Virtuous way // First objective for (i = 0; i < 2; i++) model.setObjectiveCoefficient(objIndex[i], objValue[i]); // Now bounds (lower will be zero by default but do again) for (i = 0; i < 3; i++) { model.setColumnLower(i, 0.0); model.setColumnUpper(i, upper[i]); } /* We could also have done in non-virtuous way e.g. double * objective = model.objective(); and then set directly */ // Faster to add rows all at once - but this is easier to show // Now add row 1 as >= 2.0 int row1Index[] = {0, 2}; double row1Value[] = {1.0, 1.0}; model.addRow(2, row1Index, row1Value, 2.0, COIN_DBL_MAX); // Now add row 2 as == 1.0 int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -5.0, 1.0}; model.addRow(3, row2Index, row2Value, 1.0, 1.0); // solve model.dual(); /* Adding one row at a time has a significant overhead so let's try a more complicated but faster way First time adding in 10000 rows one by one */ model.allSlackBasis(); ClpSimplex modelSave = model; double time1 = CoinCpuTime(); int k; for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -5.0, 1.0}; model.addRow(3, row2Index, row2Value, 1.0, 1.0); } printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; // Now use build CoinBuild buildObject; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -5.0, 1.0}; buildObject.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.addRows(buildObject); printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; int del[] = {0, 1, 2}; model.deleteRows(2, del); // Now use build +-1 CoinBuild buildObject2; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -1.0, 1.0}; buildObject2.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.addRows(buildObject2, true); printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1); model.dual(); model = modelSave; model.deleteRows(2, del); // Now use build +-1 CoinModel modelObject2; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -1.0, 1.0}; modelObject2.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.addRows(modelObject2, true); printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1); model.dual(); model = ClpSimplex(); // Now use build +-1 CoinModel modelObject3; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -1.0, 1.0}; modelObject3.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.loadProblem(modelObject3, true); printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1); model.writeMps("xx.mps"); model.dual(); model = modelSave; // Now use model CoinModel modelObject; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -5.0, 1.0}; modelObject.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.addRows(modelObject); printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1); model.dual(); model.writeMps("b.mps"); // Method using least memory - but most complicated time1 = CoinCpuTime(); // Assumes we know exact size of model and matrix // Empty model ClpSimplex model2; { // Create space for 3 columns and 10000 rows int numberRows = 10000; int numberColumns = 3; // This is fully dense - but would not normally be so int numberElements = numberRows * numberColumns; // Arrays will be set to default values model2.resize(numberRows, numberColumns); double * elements = new double [numberElements]; CoinBigIndex * starts = new CoinBigIndex [numberColumns+1]; int * rows = new int [numberElements];; int * lengths = new int[numberColumns]; // Now fill in - totally unsafe but .... // no need as defaults to 0.0 double * columnLower = model2.columnLower(); double * columnUpper = model2.columnUpper(); double * objective = model2.objective(); double * rowLower = model2.rowLower(); double * rowUpper = model2.rowUpper(); // Columns - objective was packed for (k = 0; k < 2; k++) { int iColumn = objIndex[k]; objective[iColumn] = objValue[k]; } for (k = 0; k < numberColumns; k++) columnUpper[k] = upper[k]; // Rows for (k = 0; k < numberRows; k++) { rowLower[k] = 1.0; rowUpper[k] = 1.0; } // Now elements double row2Value[] = {1.0, -5.0, 1.0}; CoinBigIndex put = 0; for (k = 0; k < numberColumns; k++) { starts[k] = put; lengths[k] = numberRows; double value = row2Value[k]; for (int i = 0; i < numberRows; i++) { rows[put] = i; elements[put] = value; put++; } } starts[numberColumns] = put; // assign to matrix CoinPackedMatrix * matrix = new CoinPackedMatrix(true, 0.0, 0.0); matrix->assignMatrix(true, numberRows, numberColumns, numberElements, elements, rows, starts, lengths); ClpPackedMatrix * clpMatrix = new ClpPackedMatrix(matrix); model2.replaceMatrix(clpMatrix, true); printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1); // If matrix is really big could switch off creation of row copy // model2.setSpecialOptions(256); } model2.dual(); model2.writeMps("a.mps"); // Print column solution int numberColumns = model.numberColumns(); // Alternatively getColSolution() double * columnPrimal = model.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model.columnLower(); // Alternatively getColUpper() double * columnUpper = model.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model.objective(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; std::cout << std::setw(6) << iColumn << " "; value = columnPrimal[iColumn]; if (fabs(value) < 1.0e5) std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } std::cout << "--------------------------------------" << std::endl; // Test CoinAssert std::cout << "If Clp compiled without NDEBUG below should give assert, if with NDEBUG or COIN_ASSERT CoinError" << std::endl; model = modelSave; model.deleteRows(2, del); // Deliberate error model.deleteColumns(1, del + 2); // Now use build +-1 CoinBuild buildObject3; time1 = CoinCpuTime(); for (k = 0; k < 10000; k++) { int row2Index[] = {0, 1, 2}; double row2Value[] = {1.0, -1.0, 1.0}; buildObject3.addRow(3, row2Index, row2Value, 1.0, 1.0); } model.addRows(buildObject3, true); } catch (CoinError e) { e.print(); if (e.lineNumber() >= 0) std::cout << "This was from a CoinAssert" << std::endl; } return 0; } Clp-1.15.10/examples/modify.cpp0000644000076600007660000000541011510657150014665 0ustar coincoin/* $Id: modify.cpp 1662 2011-01-04 17:52:40Z 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). /* This example shows the creation of a model from arrays, solution and then changes to objective and adding a row */ #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" int main(int argc, const char *argv[]) { ClpSimplex model; // 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}; // load problem model.loadProblem(matrix, colLower, colUpper, objective, rowLower, rowUpper); // mark integer (really for Cbc/examples/modify.cpp model.setInteger(2); model.setInteger(3); // Solve model.initialSolve(); // Solution const double * solution = model.primalColumnSolution(); int i; for (i = 0; i < numberColumns; i++) if (solution[i]) printf("Column %d has value %g\n", i, solution[i]); // Change objective double * objective2 = model.objective(); objective2[0] = -100.0; // Solve - primal as primal feasible model.primal(1); // Solution (array won't have changed) for (i = 0; i < numberColumns; i++) if (solution[i]) printf("Column %d has value %g\n", i, solution[i]); // Add constraint int column[8] = {0, 1, 2, 3, 4, 5, 6, 7}; double element2[8] = {1, 1, 1, 1, 1, 1, 1, 1}; model.addRow(8, column, element2, 7.8, COIN_DBL_MAX); // Solve - dual as dual feasible model.dual(); /* Solution This time we have changed arrays of solver so - array won't have changed as column array and we added a row - but be on safe side */ solution = model.primalColumnSolution(); for (i = 0; i < numberColumns; i++) if (solution[i]) printf("Column %d has value %g\n", i, solution[i]); return 0; } Clp-1.15.10/examples/testQP.cpp0000644000076600007660000001724111510657150014623 0ustar coincoin/* $Id: testQP.cpp 1662 2011-01-04 17:52:40Z 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 "CoinMpsIO.hpp" #include "ClpInterior.hpp" #include "ClpSimplex.hpp" #include "ClpCholeskyBase.hpp" #include "ClpQuadraticObjective.hpp" #include int main(int argc, const char *argv[]) { /* Read quadratic model in two stages to test loadQuadraticObjective. And is also possible to just read into ClpSimplex/Interior which sets it all up in one go. But this is only if it is in QUADOBJ format. If no arguments does share2qp using ClpInterior (also creates quad.mps which is in QUADOBJ format) If one argument uses simplex e.g. testit quad.mps If > one uses barrier via ClpSimplex input and then ClpInterior borrow */ if (argc < 2) { CoinMpsIO m; #if defined(SAMPLEDIR) int status = m.readMps(SAMPLEDIR "/share2qp", "mps"); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif if (status) { printf("errors on input\n"); exit(77); } ClpInterior model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); // get quadratic part int * start = NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL, start, column, element, 2); int j; for (j = 0; j < 79; j++) { if (start[j] < start[j+1]) { int i; printf("Column %d ", j); for (i = start[j]; i < start[j+1]; i++) { printf("( %d, %g) ", column[i], element[i]); } printf("\n"); } } model.loadQuadraticObjective(model.numberColumns(), start, column, element); // share2qp is in old style qp format - convert to new so other options can use model.writeMps("quad.mps"); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); model.setCholesky(cholesky); model.primalDual(); double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); int i; int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); for (i = 0; i < numberColumns; i++) { if (fabs(primal[i]) > 1.0e-8) printf("%d primal %g\n", i, primal[i]); } for (i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } } else { // Could read into ClpInterior ClpSimplex model; if (model.readMps(argv[1])) { printf("errors on input\n"); exit(77); } model.writeMps("quad"); if (argc < 3) { // simplex - just primal as dual does not work // also I need to fix scaling of duals on output // (Was okay in first place - can't mix and match scaling techniques) // model.scaling(0); model.primal(); } else { // barrier ClpInterior barrier; barrier.borrowModel(model); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); barrier.primalDual(); barrier.returnModel(model); } // Just check if share2qp (quad.mps here) // this is because I am not checking if variables at ub if (model.numberColumns() == 79) { double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); // Check duals by hand const ClpQuadraticObjective * quadraticObj = (dynamic_cast(model.objectiveAsObject())); assert(quadraticObj); CoinPackedMatrix * quad = quadraticObj->quadraticObjective(); const int * columnQuadratic = quad->getIndices(); const CoinBigIndex * columnQuadraticStart = quad->getVectorStarts(); const int * columnQuadraticLength = quad->getVectorLengths(); const double * quadraticElement = quad->getElements(); int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); double * gradient = new double [numberColumns]; // move linear objective memcpy(gradient, quadraticObj->linearObjective(), numberColumns * sizeof(double)); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double valueI = primal[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = primal[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient[iColumn] += gradientI; gradient[jColumn] += gradientJ; } else { double gradientI = valueI * elementValue; gradient[iColumn] += gradientI; } } if (fabs(primal[iColumn]) > 1.0e-8) printf("%d primal %g\n", iColumn, primal[iColumn]); } for (int i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } // Now use duals to get reduced costs // Can't use this as will try and use scaling // model.transposeTimes(-1.0,dual,gradient); // So ... CoinPackedMatrix * matrix = model.matrix(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = gradient[iColumn]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int jRow = row[j]; dj -= element[j] * dual[jRow]; } if (model.getColumnStatus(iColumn) == ClpSimplex::basic) { assert(fabs(dj) < 1.0e-5); } else { assert(dj > -1.0e-5); } } delete [] gradient; } } return 0; } Clp-1.15.10/examples/decomp3.cpp0000644000076600007660000000666111510657150014741 0ustar coincoin/* $Id: decomp3.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include "ClpSimplex.hpp" #include "ClpPresolve.hpp" #include "CoinStructuredModel.hpp" #include "CoinTime.hpp" #include int main(int argc, const char *argv[]) { /* Create a structured model by reading mps file and trying Dantzig-Wolfe or Benders decomposition */ // Get maximum number of blocks int maxBlocks = 50; if (argc > 2) maxBlocks = atoi(argv[2]); int decompose = 1; if (maxBlocks < 0) { maxBlocks = -maxBlocks; decompose = 2; } if (maxBlocks < 2) { printf("Second parameters is maximum number of blocks >=2)\n"); exit(5); } else { printf("Allowing at most %d blocks\n", maxBlocks); } //#define PRESOLVE #ifndef PRESOLVE #if defined(NETLIBDIR) CoinStructuredModel model((argc < 2) ? NETLIBDIR "/czprob.mps" : argv[1], decompose, maxBlocks); #else if (argc<2) { fprintf(stderr, "Do not know where to find netlib MPS files.\n"); return 1; } CoinStructuredModel model(argv[1], 1); #endif if (!model.numberRows()) exit(10); // Get default solver - could change stuff ClpSimplex solver; // change factorization frequency from 200 solver.setFactorizationFrequency(100 + model.numberRows() / 50); /* This driver does a simple Dantzig Wolfe decomposition */ double time1 = CoinCpuTime() ; solver.solve(&model); std::cout << "model took " << CoinCpuTime() - time1 << " seconds" << std::endl; // Double check solver.primal(1); #else ClpSimplex model; #if defined(NETLIBDIR) int status = model.readMps((argc < 2) ? NETLIBDIR "/czprob.mps" : argv[1]); #else if (argc<2) { fprintf(stderr, "Do not know where to find netlib MPS files.\n"); return 1; } int status = model.readMps(argv[1]); #endif if (status) { fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } ClpSimplex * model2 = &model; CoinStructuredModel modelB; modelB.decompose(*model2->matrix(), model2->rowLower(), model2->rowUpper(), model2->columnLower(), model2->columnUpper(), model2->objective(), 1, maxBlocks, model2->objectiveOffset()); // change factorization frequency from 200 model2->setFactorizationFrequency(100 + modelB.numberRows() / 50); /* This driver does a simple Dantzig Wolfe decomposition */ double time1 = CoinCpuTime() ; model2->solve(&modelB); std::cout << "model took " << CoinCpuTime() - time1 << " seconds" << std::endl; // But resolve for safety model.primal(1); #endif return 0; ClpSimplex solver2; #if defined(NETLIBDIR) solver2.readMps((argc < 2) ? NETLIBDIR "/czprob.mps" : argv[1]); #else if (argc<2) { fprintf(stderr, "Do not know where to find netlib MPS files.\n"); return 1; } solver2.readMps(argv[1]); #endif time1 = CoinCpuTime() ; solver2.dual(); std::cout << "second try took " << CoinCpuTime() - time1 << " seconds" << std::endl; return 0; } Clp-1.15.10/examples/decompose.cpp0000644000076600007660000005453611510657150015371 0ustar coincoin/* $Id: decompose.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include "ClpSimplex.hpp" #include "CoinMpsIO.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { #if defined(NETLIBDIR) status = model.readMps(NETLIBDIR "/czprob.mps", true); #else fprintf(stderr, "Do not know where to find netlib MPS files.\n"); return 1; #endif } else { status = model.readMps(argv[1], true); } if (status) exit(10); /* This driver does a simple Dantzig Wolfe decomposition */ // Get master rows in some mysterious way int numberRows = model.numberRows(); int * rowBlock = new int[numberRows]; int iRow; for (iRow = 0; iRow < numberRows; iRow++) rowBlock[iRow] = -2; // these are master rows if (numberRows == 105127) { // ken-18 for (iRow = 104976; iRow < numberRows; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 2426) { // ken-7 for (iRow = 2401; iRow < numberRows; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 810) { for (iRow = 81; iRow < 84; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 5418) { for (iRow = 564; iRow < 603; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 10280) { // osa-60 for (iRow = 10198; iRow < 10280; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 1503) { // degen3 for (iRow = 0; iRow < 561; iRow++) rowBlock[iRow] = -1; } else if (numberRows == 929) { // czprob for (iRow = 0; iRow < 39; iRow++) rowBlock[iRow] = -1; } CoinPackedMatrix * matrix = model.matrix(); // get row copy CoinPackedMatrix rowCopy = *matrix; rowCopy.reverseOrdering(); const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); //const double * elementByColumn = matrix->getElements(); const int * column = rowCopy.getIndices(); const int * rowLength = rowCopy.getVectorLengths(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); //const double * elementByRow = rowCopy.getElements(); int numberBlocks = 0; int * stack = new int [numberRows]; // to say if column looked at int numberColumns = model.numberColumns(); int * columnBlock = new int[numberColumns]; int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) columnBlock[iColumn] = -2; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int kstart = columnStart[iColumn]; int kend = columnStart[iColumn] + columnLength[iColumn]; if (columnBlock[iColumn] == -2) { // column not allocated int j; int nstack = 0; for (j = kstart; j < kend; j++) { int iRow = row[j]; if (rowBlock[iRow] != -1) { assert(rowBlock[iRow] == -2); rowBlock[iRow] = numberBlocks; // mark stack[nstack++] = iRow; } } if (nstack) { // new block - put all connected in numberBlocks++; columnBlock[iColumn] = numberBlocks - 1; while (nstack) { int iRow = stack[--nstack]; int k; for (k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) { int iColumn = column[k]; int kkstart = columnStart[iColumn]; int kkend = kkstart + columnLength[iColumn]; if (columnBlock[iColumn] == -2) { columnBlock[iColumn] = numberBlocks - 1; // mark // column not allocated int jj; for (jj = kkstart; jj < kkend; jj++) { int jRow = row[jj]; if (rowBlock[jRow] == -2) { rowBlock[jRow] = numberBlocks - 1; stack[nstack++] = jRow; } } } else { assert(columnBlock[iColumn] == numberBlocks - 1); } } } } else { // Only in master columnBlock[iColumn] = -1; } } } printf("%d blocks found\n", numberBlocks); if (numberBlocks > 50) { int iBlock; for (iRow = 0; iRow < numberRows; iRow++) { iBlock = rowBlock[iRow]; if (iBlock >= 0) rowBlock[iRow] = iBlock % 50; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { iBlock = columnBlock[iColumn]; if (iBlock >= 0) columnBlock[iColumn] = iBlock % 50; } numberBlocks = 50; } delete [] stack; // make up problems CoinPackedMatrix * top = new CoinPackedMatrix [numberBlocks]; ClpSimplex * sub = new ClpSimplex [numberBlocks]; ClpSimplex master; // Create all sub problems // Could do much faster - but do that later int * whichRow = new int [numberRows]; int * whichColumn = new int [numberColumns]; // get top matrix CoinPackedMatrix topMatrix = *model.matrix(); int numberRow2, numberColumn2; numberRow2 = 0; for (iRow = 0; iRow < numberRows; iRow++) if (rowBlock[iRow] >= 0) whichRow[numberRow2++] = iRow; topMatrix.deleteRows(numberRow2, whichRow); int iBlock; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { numberRow2 = 0; numberColumn2 = 0; for (iRow = 0; iRow < numberRows; iRow++) if (iBlock == rowBlock[iRow]) whichRow[numberRow2++] = iRow; for (iColumn = 0; iColumn < numberColumns; iColumn++) if (iBlock == columnBlock[iColumn]) whichColumn[numberColumn2++] = iColumn; sub[iBlock] = ClpSimplex(&model, numberRow2, whichRow, numberColumn2, whichColumn); #if 0 // temp double * upper = sub[iBlock].columnUpper(); for (iColumn = 0; iColumn < numberColumn2; iColumn++) upper[iColumn] = 100.0; #endif // and top matrix CoinPackedMatrix matrix = topMatrix; // and delete bits numberColumn2 = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) if (iBlock != columnBlock[iColumn]) whichColumn[numberColumn2++] = iColumn; matrix.deleteCols(numberColumn2, whichColumn); top[iBlock] = matrix; } // and master numberRow2 = 0; numberColumn2 = 0; for (iRow = 0; iRow < numberRows; iRow++) if (rowBlock[iRow] < 0) whichRow[numberRow2++] = iRow; for (iColumn = 0; iColumn < numberColumns; iColumn++) if (columnBlock[iColumn] == -1) whichColumn[numberColumn2++] = iColumn; ClpModel masterModel(&model, numberRow2, whichRow, numberColumn2, whichColumn); master = ClpSimplex(masterModel); delete [] whichRow; delete [] whichColumn; // Overkill in terms of space int numberMasterRows = master.numberRows(); int * columnAdd = new int[numberBlocks+1]; int * rowAdd = new int[numberBlocks*(numberMasterRows+1)]; double * elementAdd = new double[numberBlocks*(numberMasterRows+1)]; double * objective = new double[numberBlocks]; int maxPass = 500; int iPass; double lastObjective = 1.0e31; // Create convexity rows for proposals int numberMasterColumns = master.numberColumns(); master.resize(numberMasterRows + numberBlocks, numberMasterColumns); // Arrays to say which block and when created int maximumColumns = 2 * numberMasterRows + 10 * numberBlocks; int * whichBlock = new int[maximumColumns]; int * when = new int[maximumColumns]; int numberColumnsGenerated = numberBlocks; // fill in rhs and add in artificials { double * rowLower = master.rowLower(); double * rowUpper = master.rowUpper(); int iBlock; columnAdd[0] = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int iRow = iBlock + numberMasterRows;; rowLower[iRow] = 1.0; rowUpper[iRow] = 1.0; rowAdd[iBlock] = iRow; elementAdd[iBlock] = 1.0; objective[iBlock] = 1.0e9; columnAdd[iBlock+1] = iBlock + 1; when[iBlock] = -1; whichBlock[iBlock] = iBlock; } master.addColumns(numberBlocks, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); } // and resize matrix to double check clp will be happy //master.matrix()->setDimensions(numberMasterRows+numberBlocks, // numberMasterColumns+numberBlocks); for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); // Solve master - may be infeasible master.scaling(false); if (0) { master.writeMps("yy.mps"); } master.primal(); int problemStatus = master.status(); // do here as can change (delcols) if (master.numberIterations() == 0 && iPass) break; // finished if (master.objectiveValue() > lastObjective - 1.0e-7 && iPass > 555) break; // finished lastObjective = master.objectiveValue(); // mark basic ones and delete if necessary int iColumn; numberColumnsGenerated = master.numberColumns() - numberMasterColumns; for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) { if (master.getStatus(iColumn + numberMasterColumns) == ClpSimplex::basic) when[iColumn] = iPass; } if (numberColumnsGenerated + numberBlocks > maximumColumns) { // delete int numberKeep = 0; int numberDelete = 0; int * whichDelete = new int[numberColumns]; for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) { if (when[iColumn] > iPass - 7) { // keep when[numberKeep] = when[iColumn]; whichBlock[numberKeep++] = whichBlock[iColumn]; } else { // delete whichDelete[numberDelete++] = iColumn + numberMasterColumns; } } numberColumnsGenerated -= numberDelete; master.deleteColumns(numberDelete, whichDelete); delete [] whichDelete; } const double * dual = NULL; bool deleteDual = false; if (problemStatus == 0) { dual = master.dualRowSolution(); } else if (problemStatus == 1) { // could do composite objective dual = master.infeasibilityRay(); deleteDual = true; printf("The sum of infeasibilities is %g\n", master.sumPrimalInfeasibilities()); } else if (!master.numberColumns()) { assert(!iPass); dual = master.dualRowSolution(); memset(master.dualRowSolution(), 0, (numberMasterRows + numberBlocks) *sizeof(double)); } else { abort(); } // Create objective for sub problems and solve columnAdd[0] = 0; int numberProposals = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int numberColumns2 = sub[iBlock].numberColumns(); double * saveObj = new double [numberColumns2]; double * objective2 = sub[iBlock].objective(); memcpy(saveObj, objective2, numberColumns2 * sizeof(double)); // new objective top[iBlock].transposeTimes(dual, objective2); int i; if (problemStatus == 0) { for (i = 0; i < numberColumns2; i++) objective2[i] = saveObj[i] - objective2[i]; } else { for (i = 0; i < numberColumns2; i++) objective2[i] = -objective2[i]; } sub[iBlock].primal(); memcpy(objective2, saveObj, numberColumns2 * sizeof(double)); // get proposal if (sub[iBlock].numberIterations() || !iPass) { double objValue = 0.0; int start = columnAdd[numberProposals]; // proposal if (sub[iBlock].isProvenOptimal()) { const double * solution = sub[iBlock].primalColumnSolution(); top[iBlock].times(solution, elementAdd + start); for (i = 0; i < numberColumns2; i++) objValue += solution[i] * saveObj[i]; // See if good dj and pack down int number = start; double dj = objValue; if (problemStatus) dj = 0.0; double smallest = 1.0e100; double largest = 0.0; for (i = 0; i < numberMasterRows; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { dj -= dual[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); rowAdd[number] = i; elementAdd[number++] = value; } } // and convexity dj -= dual[numberMasterRows+iBlock]; rowAdd[number] = numberMasterRows + iBlock; elementAdd[number++] = 1.0; // if elements large then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem %d smallest - %g, largest %g - dj %g\n", iBlock, smallest, largest, dj); if (dj < -1.0e-6 || !iPass) { // take objective[numberProposals] = objValue; columnAdd[++numberProposals] = number; when[numberColumnsGenerated] = iPass; whichBlock[numberColumnsGenerated++] = iBlock; } } else if (sub[iBlock].isProvenDualInfeasible()) { // use ray const double * solution = sub[iBlock].unboundedRay(); top[iBlock].times(solution, elementAdd + start); for (i = 0; i < numberColumns2; i++) objValue += solution[i] * saveObj[i]; // See if good dj and pack down int number = start; double dj = objValue; double smallest = 1.0e100; double largest = 0.0; for (i = 0; i < numberMasterRows; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { dj -= dual[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); rowAdd[number] = i; elementAdd[number++] = value; } } // if elements large or small then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem ray %d smallest - %g, largest %g - dj %g\n", iBlock, smallest, largest, dj); if (dj < -1.0e-6) { // take objective[numberProposals] = objValue; columnAdd[++numberProposals] = number; when[numberColumnsGenerated] = iPass; whichBlock[numberColumnsGenerated++] = iBlock; } } else { abort(); } } delete [] saveObj; } if (deleteDual) delete [] dual; if (numberProposals) master.addColumns(numberProposals, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); } // now put back a good solution double * lower = new double[numberMasterRows+numberBlocks]; double * upper = new double[numberMasterRows+numberBlocks]; numberColumnsGenerated += numberMasterColumns; double * sol = new double[numberColumnsGenerated]; const double * solution = master.primalColumnSolution(); const double * masterLower = master.rowLower(); const double * masterUpper = master.rowUpper(); double * fullSolution = model.primalColumnSolution(); const double * fullLower = model.columnLower(); const double * fullUpper = model.columnUpper(); const double * rowSolution = master.primalRowSolution(); double * fullRowSolution = model.primalRowSolution(); int kRow = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowBlock[iRow] == -1) { model.setRowStatus(iRow, master.getRowStatus(kRow)); fullRowSolution[iRow] = rowSolution[kRow++]; } } int kColumn = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnBlock[iColumn] == -1) { model.setStatus(iColumn, master.getStatus(kColumn)); fullSolution[iColumn] = solution[kColumn++]; } } for (iBlock = 0; iBlock < numberBlocks; iBlock++) { // convert top bit to by rows top[iBlock].reverseOrdering(); // zero solution memset(sol, 0, numberColumnsGenerated * sizeof(double)); int i; for (i = numberMasterColumns; i < numberColumnsGenerated; i++) if (whichBlock[i-numberMasterColumns] == iBlock) sol[i] = solution[i]; memset(lower, 0, (numberMasterRows + numberBlocks) *sizeof(double)); master.times(1.0, sol, lower); for (iRow = 0; iRow < numberMasterRows; iRow++) { double value = lower[iRow]; if (masterUpper[iRow] < 1.0e20) upper[iRow] = value; else upper[iRow] = COIN_DBL_MAX; if (masterLower[iRow] > -1.0e20) lower[iRow] = value; else lower[iRow] = -COIN_DBL_MAX; } sub[iBlock].addRows(numberMasterRows, lower, upper, top[iBlock].getVectorStarts(), top[iBlock].getVectorLengths(), top[iBlock].getIndices(), top[iBlock].getElements()); sub[iBlock].primal(); const double * subSolution = sub[iBlock].primalColumnSolution(); const double * subRowSolution = sub[iBlock].primalRowSolution(); // move solution kColumn = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnBlock[iColumn] == iBlock) { model.setStatus(iColumn, sub[iBlock].getStatus(kColumn)); fullSolution[iColumn] = subSolution[kColumn++]; } } assert(kColumn == sub[iBlock].numberColumns()); kRow = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowBlock[iRow] == iBlock) { model.setRowStatus(iRow, sub[iBlock].getRowStatus(kRow)); fullRowSolution[iRow] = subRowSolution[kRow++]; } } assert(kRow == sub[iBlock].numberRows() - numberMasterRows); } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (fullSolution[iColumn] < fullUpper[iColumn] - 1.0e-8 && fullSolution[iColumn] > fullLower[iColumn] + 1.0e-8) { assert(model.getStatus(iColumn) == ClpSimplex::basic); } else if (fullSolution[iColumn] >= fullUpper[iColumn] - 1.0e-8) { // may help to make rest non basic model.setStatus(iColumn, ClpSimplex::atUpperBound); } else if (fullSolution[iColumn] <= fullLower[iColumn] + 1.0e-8) { // may help to make rest non basic model.setStatus(iColumn, ClpSimplex::atLowerBound); } } for (iRow = 0; iRow < numberRows; iRow++) model.setRowStatus(iRow, ClpSimplex::superBasic); model.primal(1); delete [] sol; delete [] lower; delete [] upper; delete [] whichBlock; delete [] when; delete [] columnAdd; delete [] rowAdd; delete [] elementAdd; delete [] objective; delete [] top; delete [] sub; delete [] rowBlock; delete [] columnBlock; return 0; } Clp-1.15.10/examples/driver.cpp0000644000076600007660000001763511510657150014705 0ustar coincoin/* $Id: driver.cpp 1662 2011-01-04 17:52:40Z lou $ */ // Copyright (C) 2002,2003 International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "ClpSimplex.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names when reading an mps file if (argc < 2) { #if defined(SAMPLEDIR) status = model.readMps(SAMPLEDIR "/p0033.mps", true); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else status = model.readMps(argv[1], true); if (status) { fprintf(stderr, "Bad readMps %s\n", argv[1]); fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } #ifdef STYLE1 if (argc < 3 || !strstr(argv[2], "primal")) { // Use the dual algorithm unless user said "primal" model.initialDualSolve(); } else { model.initialPrimalSolve(); } #else ClpSolve solvectl; if (argc < 3 || (!strstr(argv[2], "primal") && !strstr(argv[2], "barrier"))) { // Use the dual algorithm unless user said "primal" or "barrier" std::cout << std::endl << " Solve using Dual: " << std::endl; solvectl.setSolveType(ClpSolve::useDual); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } else if (strstr(argv[2], "barrier")) { // Use the barrier algorithm if user said "barrier" std::cout << std::endl << " Solve using Barrier: " << std::endl; solvectl.setSolveType(ClpSolve::useBarrier); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } else { std::cout << std::endl << " Solve using Primal: " << std::endl; solvectl.setSolveType(ClpSolve::usePrimal); solvectl.setPresolveType(ClpSolve::presolveOn); model.initialSolve(solvectl); } #endif std::string modelName; model.getStrParam(ClpProbName, modelName); std::cout << "Model " << modelName << " has " << model.numberRows() << " rows and " << model.numberColumns() << " columns" << std::endl; // remove this to print solution exit(0); /* 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 columns */ #if 0 int numberRows = model.numberRows(); // Alternatively getRowActivity() double * rowPrimal = model.primalRowSolution(); // Alternatively getRowPrice() double * rowDual = model.dualRowSolution(); // Alternatively getRowLower() double * rowLower = model.rowLower(); // Alternatively getRowUpper() double * rowUpper = model.rowUpper(); // Alternatively getRowObjCoefficients() double * rowObjective = model.rowObjective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Row names const std::vector * rowNames = model.rowNames(); int iRow; std::cout << " Primal Dual Lower Upper (Cost)" << std::endl; for (iRow = 0; iRow < numberRows; iRow++) { double value; std::cout << std::setw(6) << iRow << " " << std::setw(8) << (*rowNames)[iRow]; value = rowPrimal[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowDual[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowLower[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = rowUpper[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; if (rowObjective) { value = rowObjective[iRow]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; } std::cout << std::endl; } #endif std::cout << "--------------------------------------" << std::endl; // Columns int numberColumns = model.numberColumns(); // Alternatively getColSolution() double * columnPrimal = model.primalColumnSolution(); // Alternatively getReducedCost() double * columnDual = model.dualColumnSolution(); // Alternatively getColLower() double * columnLower = model.columnLower(); // Alternatively getColUpper() double * columnUpper = model.columnUpper(); // Alternatively getObjCoefficients() double * columnObjective = model.objective(); // If we have not kept names (parameter to readMps) this will be 0 assert(model.lengthNames()); // Column names const std::vector * columnNames = model.columnNames(); int iColumn; std::cout << " Primal Dual Lower Upper Cost" << std::endl; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value; value = columnPrimal[iColumn]; if (fabs(value) > 1.0e-8) { std::cout << std::setw(6) << iColumn << " " << std::setw(8) << (*columnNames)[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnDual[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnLower[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnUpper[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; value = columnObjective[iColumn]; if (fabs(value) < 1.0e5) std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value; else std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value; std::cout << std::endl; } } std::cout << "--------------------------------------" << std::endl; return 0; } Clp-1.15.10/examples/myPdco.hpp0000644000076600007660000000356711510657150014651 0ustar coincoin/* $Id: myPdco.hpp 1662 2011-01-04 17:52:40Z lou $ */ // 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 myPdco_H #define myPdco_H #include "CoinPragma.hpp" #include "ClpPdcoBase.hpp" /** This implements a simple network matrix as derived from ClpMatrixBase. If you want more sophisticated version then you could inherit from this. Also you might want to allow networks with gain */ class myPdco : public ClpPdcoBase { public: /**@name Useful methods */ //@{ virtual void matVecMult(ClpInterior * model, int mode, double * x, double * y) const; virtual void getGrad(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &grad) const; virtual void getHessian(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &H) const; virtual double getObj(ClpInterior * model, CoinDenseVector &x) const; virtual void matPrecon(ClpInterior * model, double delta, double * x, double * y) const ; //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ myPdco(); /** Constructor from Stuff */ myPdco(double d1, double d2, int numnodes, int numlinks); /// Also reads a model myPdco(ClpInterior & model, FILE * fpData, FILE * fpParam); /** Destructor */ virtual ~myPdco(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ myPdco(const myPdco&); myPdco& operator=(const myPdco&); /// Clone virtual ClpPdcoBase * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ int * rowIndex_; int numlinks_; int numnodes_; //@} }; #endif Clp-1.15.10/examples/testGub.cpp0000644000076600007660000005026012131314313015005 0ustar coincoin/* $Id: testGub.cpp 1941 2013-04-10 16:52:27Z 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). #include "ClpSimplex.hpp" #include "ClpDynamicExampleMatrix.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "CoinSort.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinMpsIO.hpp" int main(int argc, const char *argv[]) { ClpSimplex model; int status; int maxFactor = 100; if (argc < 2) { #if defined(NETLIBDIR) status = model.readMps(NETLIBDIR "/czprob.mps"); if (status) { printf("Unable to read matrix - trying gzipped version\n"); status = model.readMps(NETLIBDIR "/czprob.mps.gz"); } #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } else { status = model.readMps(argv[1]); } if (status) { printf("errors on input\n"); exit(77); } if (argc > 2) { maxFactor = atoi(argv[2]); printf("max factor %d\n", maxFactor); } if (argc > 3) { printf("Using ClpDynamicMatrix\n"); } else { printf("Using ClpDynamicExampleMatrix\n"); } // find gub int numberRows = model.numberRows(); int * gubStart = new int[numberRows+1]; int * gubEnd = new int[numberRows]; int * which = new int[numberRows]; int * whichGub = new int[numberRows]; int numberColumns = model.numberColumns(); int * mark = new int[numberColumns]; int iRow, iColumn; // delete variables fixed to zero const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberDelete = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 0.0) mark[numberDelete++] = iColumn; } if (numberDelete) { model.deleteColumns(numberDelete, mark); numberColumns -= numberDelete; columnLower = model.columnLower(); columnUpper = model.columnUpper(); } double * lower = new double[numberRows]; double * upper = new double[numberRows]; const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) mark[iColumn] = -1; CoinPackedMatrix * matrix = model.matrix(); // 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(); int putGub = numberRows; int putNonGub = numberRows; int * rowIsGub = new int [numberRows]; for (iRow = numberRows - 1; iRow >= 0; iRow--) { bool gubRow = true; int first = numberColumns + 1; int last = -1; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { if (element[j] != 1.0) { gubRow = false; break; } else { int iColumn = column[j]; if (mark[iColumn] >= 0) { gubRow = false; break; } else { last = CoinMax(last, iColumn); first = CoinMin(first, iColumn); } } } if (last - first + 1 != rowLength[iRow] || !gubRow) { which[--putNonGub] = iRow; rowIsGub[iRow] = 0; } else { for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; mark[iColumn] = iRow; } rowIsGub[iRow] = -1; putGub--; gubStart[putGub] = first; gubEnd[putGub] = last + 1; lower[putGub] = rowLower[iRow]; upper[putGub] = rowUpper[iRow]; whichGub[putGub] = iRow; } } int numberNonGub = numberRows - putNonGub; int numberGub = numberRows - putGub; if (numberGub > 0) { printf("** %d gub rows\n", numberGub); int numberNormal = 0; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int numberElements = 0; bool doLower = false; bool doUpper = false; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (mark[iColumn] < 0) { mark[numberNormal++] = iColumn; } else { numberElements += columnLength[iColumn]; if (columnLower[iColumn] != 0.0) doLower = true; if (columnUpper[iColumn] < 1.0e20) doUpper = true; } } if (!numberNormal) { printf("Putting back one gub row to make non-empty\n"); for (iColumn = gubStart[putGub]; iColumn < gubEnd[putGub]; iColumn++) mark[numberNormal++] = iColumn; putGub++; numberGub--; } ClpSimplex model2(&model, numberNonGub, which + putNonGub, numberNormal, mark); // and copy for restart test ClpSimplex model3 = model2; int numberGubColumns = numberColumns - numberNormal; // sort gubs so monotonic int * which = new int[numberGub]; int i; for (i = 0; i < numberGub; i++) which[i] = i; CoinSort_2(gubStart + putGub, gubStart + putGub + numberGub, which); // move to bottom if we want to use later memmove(gubStart, gubStart + putGub, numberGub * sizeof(int)); int * temp1 = new int [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp1[i] = gubEnd[putGub+k]; } memcpy(gubEnd, temp1, numberGub * sizeof(int)); delete [] temp1; double * temp2 = new double [numberGub]; for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = lower[putGub+k]; } memcpy(lower, temp2, numberGub * sizeof(double)); for (i = 0; i < numberGub; i++) { int k = which[i]; temp2[i] = upper[putGub+k]; } memcpy(upper, temp2, numberGub * sizeof(double)); delete [] temp2; delete [] which; numberElements -= numberGubColumns; int * start2 = new int[numberGubColumns+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; double * cost2 = new double [numberGubColumns]; double * lowerColumn2 = NULL; if (doLower) { lowerColumn2 = new double [numberGubColumns]; CoinFillN(lowerColumn2, numberGubColumns, 0.0); } double * upperColumn2 = NULL; if (doUpper) { upperColumn2 = new double [numberGubColumns]; CoinFillN(upperColumn2, numberGubColumns, COIN_DBL_MAX); } numberElements = 0; int numberNonGubRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (!rowIsGub[iRow]) rowIsGub[iRow] = numberNonGubRows++; } numberColumns = 0; int iStart = gubStart[0]; gubStart[0] = 0; start2[0] = 0; const double * cost = model.objective(); for (int iSet = 0; iSet < numberGub; iSet++) { int iEnd = gubEnd[iSet]; for (int k = iStart; k < iEnd; k++) { cost2[numberColumns] = cost[k]; if (columnLower[k]) lowerColumn2[numberColumns] = columnLower[k]; if (columnUpper[k] < 1.0e20) upperColumn2[numberColumns] = columnUpper[k]; for (int j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int iRow = rowIsGub[row[j]]; if (iRow >= 0) { row2[numberElements] = iRow; element2[numberElements++] = elementByColumn[j]; } } start2[++numberColumns] = numberElements; } if (iSet < numberGub - 1) iStart = gubStart[iSet+1]; gubStart[iSet+1] = numberColumns; } printf("** Before adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); if (argc > 3) { ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model2, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); model2.replaceMatrix(newMatrix,true); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } printf("** While after adding matrix there are %d rows and %d columns\n", model2.numberRows(), model2.numberColumns()); model2.setSpecialOptions(4); // exactly to bound // For now scaling off model2.scaling(0); ClpPrimalColumnSteepest steepest(5); model2.setPrimalColumnPivotAlgorithm(steepest); //model2.messageHandler()->setLogLevel(63); model2.setFactorizationFrequency(maxFactor); model2.setMaximumIterations(4000000); double time1 = CoinCpuTime(); model2.primal(); // can't use values pass model2.primal(0); // test proper restart if (argc > 3) { ClpDynamicMatrix * oldMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert(oldMatrix); ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus()); model3.replaceMatrix(newMatrix,true); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns()) *sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } else { ClpDynamicExampleMatrix * oldMatrix = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); assert(oldMatrix); ClpDynamicExampleMatrix * newMatrix = new ClpDynamicExampleMatrix(&model3, numberGub, numberColumns, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2, oldMatrix->gubRowStatus(), oldMatrix->dynamicStatus(), oldMatrix->numberGubColumns(), oldMatrix->idGen()); model3.replaceMatrix(newMatrix,true); // and ordinary status (but only NON gub rows) memcpy(model3.statusArray(), model2.statusArray(), (newMatrix->numberStaticRows() + model3.numberColumns()) *sizeof(unsigned char)); newMatrix->switchOffCheck(); newMatrix->setRefreshFrequency(1000); } model3.setSpecialOptions(4); // exactly to bound // For now scaling off model3.scaling(0); model3.setPrimalColumnPivotAlgorithm(steepest); model3.messageHandler()->setLogLevel(63); model3.setFactorizationFrequency(maxFactor); model3.setMaximumIterations(4000000); delete [] rowIsGub; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lowerColumn2; delete [] upperColumn2; model3.primal(); // this code expects non gub first in original matrix // and only works at present for ClpDynamicMatrix ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(model2.clpMatrix()); assert(gubMatrix); ClpDynamicExampleMatrix * gubMatrix2 = dynamic_cast< ClpDynamicExampleMatrix*>(model2.clpMatrix()); if (!gubMatrix2) { const double * solution = model2.primalColumnSolution(); const double * cost = model.objective(); int numberGubColumns = gubMatrix->numberGubColumns(); int firstOdd = gubMatrix->firstDynamic(); int lastOdd = gubMatrix->firstAvailable(); int numberTotalColumns = firstOdd + numberGubColumns; int originalNumberRows = model.numberRows(); int numberStaticRows = gubMatrix->numberStaticRows(); char * status = new char [numberTotalColumns]; double * gubSolution = new double [numberTotalColumns]; int numberSets = gubMatrix->numberSets(); const int * id = gubMatrix->id(); int i; const double * columnLower = gubMatrix->columnLower(); const double * columnUpper = gubMatrix->columnUpper(); for (i = 0; i < numberGubColumns; i++) { if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) { gubSolution[i+firstOdd] = columnUpper[i]; status[i+firstOdd] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) { gubSolution[i+firstOdd] = columnLower[i]; status[i+firstOdd] = 1; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) { int iSet = gubMatrix->whichSet(i); gubSolution[i+firstOdd] = gubMatrix->keyValue(iSet); status[i+firstOdd] = 0; } else { gubSolution[i+firstOdd] = 0.0; status[i+firstOdd] = 1; } } for (i = 0; i < firstOdd; i++) { ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[i] = 2; else if (thisStatus == ClpSimplex::isFixed) status[i] = 3; else abort(); gubSolution[i] = solution[i]; } for (i = firstOdd; i < lastOdd; i++) { int iBig = id[i-firstOdd] + firstOdd; ClpSimplex::Status thisStatus = model2.getStatus(i); if (thisStatus == ClpSimplex::basic) status[iBig] = 0; else if (thisStatus == ClpSimplex::atLowerBound) status[iBig] = 1; else if (thisStatus == ClpSimplex::atUpperBound) status[iBig] = 2; else if (thisStatus == ClpSimplex::isFixed) status[iBig] = 3; else abort(); gubSolution[iBig] = solution[i]; } char * rowStatus = new char[originalNumberRows]; for (i = 0; i < numberStaticRows; i++) { ClpSimplex::Status thisStatus = model2.getRowStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[i] = 3; else abort(); } double objValue = 0.0; for (i = 0; i < numberTotalColumns; i++) objValue += cost[i] * gubSolution[i]; printf("objective value is %g\n", objValue); for (i = 0; i < numberSets; i++) { ClpSimplex::Status thisStatus = gubMatrix->getStatus(i); if (thisStatus == ClpSimplex::basic) rowStatus[numberStaticRows+i] = 0; else if (thisStatus == ClpSimplex::atLowerBound) rowStatus[numberStaticRows+i] = 1; else if (thisStatus == ClpSimplex::atUpperBound) rowStatus[numberStaticRows+i] = 2; else if (thisStatus == ClpSimplex::isFixed) rowStatus[numberStaticRows+i] = 3; else abort(); } // Coding below may not work if gub rows not at end FILE * fp = fopen("xx.sol", "w"); fwrite(gubSolution, sizeof(double), numberTotalColumns, fp); fwrite(status, sizeof(char), numberTotalColumns, fp); #ifndef NDEBUG const double * rowsol = model2.primalRowSolution(); #endif double * rowsol2 = new double[originalNumberRows]; memset(rowsol2, 0, originalNumberRows * sizeof(double)); model.times(1.0, gubSolution, rowsol2); for (i = 0; i < numberStaticRows; i++) assert(fabs(rowsol[i] - rowsol2[i]) < 1.0e-3); for (; i < originalNumberRows; i++) assert(rowsol2[i] > lower[i-numberStaticRows] - 1.0e-3 && rowsol2[i] < upper[i-numberStaticRows] + 1.0e-3); //for (;i -1.0e20) { if (fabs(columnLower[iColumn]) < fabs(columnUpper[iColumn])) { double value = columnUpper[iColumn]; model.setColumnUpper(iColumn, COIN_DBL_MAX); build.addRow(1, &iColumn, &one, -COIN_DBL_MAX, value); } else { double value = columnLower[iColumn]; model.setColumnLower(iColumn, -COIN_DBL_MAX); build.addRow(1, &iColumn, &one, value, COIN_DBL_MAX); } } } if (build.numberRows()) model.addRows(build); } int numberColumns = model.numberColumns(); const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); int numberRows = model.numberRows(); double * rowLower = CoinCopyOfArray(model.rowLower(), numberRows); double * rowUpper = CoinCopyOfArray(model.rowUpper(), numberRows); const double * objective = model.objective(); CoinPackedMatrix * matrix = model.matrix(); // get transpose CoinPackedMatrix rowCopy = *matrix; int iRow, iColumn; int numberExtraRows = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] <= -1.0e20) { } else if (rowUpper[iRow] >= 1.0e20) { } else { if (rowUpper[iRow] != rowLower[iRow]) numberExtraRows++; } } const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); double objOffset = 0.0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double offset = 0.0; if (columnUpper[iColumn] >= 1.0e20) { if (columnLower[iColumn] > -1.0e20) offset = columnLower[iColumn]; } else if (columnLower[iColumn] <= -1.0e20) { offset = columnUpper[iColumn]; } else { // taken care of before abort(); } if (offset) { objOffset += offset * objective[iColumn]; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowLower[iRow] > -1.0e20) rowLower[iRow] -= offset * elementByColumn[j]; if (rowUpper[iRow] < 1.0e20) rowUpper[iRow] -= offset * elementByColumn[j]; } } } int * which = new int[numberRows+numberExtraRows]; rowCopy.reverseOrdering(); rowCopy.transpose(); double * fromRowsLower = new double[numberRows+numberExtraRows]; double * fromRowsUpper = new double[numberRows+numberExtraRows]; double * newObjective = new double[numberRows+numberExtraRows]; double * fromColumnsLower = new double[numberColumns]; double * fromColumnsUpper = new double[numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { // Offset is already in if (columnUpper[iColumn] >= 1.0e20) { if (columnLower[iColumn] > -1.0e20) { fromColumnsLower[iColumn] = -COIN_DBL_MAX; fromColumnsUpper[iColumn] = objective[iColumn]; } else { // free fromColumnsLower[iColumn] = objective[iColumn]; fromColumnsUpper[iColumn] = objective[iColumn]; } } else if (columnLower[iColumn] <= -1.0e20) { fromColumnsLower[iColumn] = objective[iColumn]; fromColumnsUpper[iColumn] = COIN_DBL_MAX; } else { abort(); } } int kRow = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] <= -1.0e20) { assert(rowUpper[iRow] < 1.0e20); newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; } else if (rowUpper[iRow] >= 1.0e20) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = 0.0; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { if (rowUpper[iRow] == rowLower[iRow]) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX;; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { // range newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = 0.0; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } } } if (numberExtraRows) { CoinPackedMatrix newCopy; newCopy.submatrixOfWithDuplicates(rowCopy, kRow, which); rowCopy = newCopy; } ClpSimplex modelDual; modelDual.loadProblem(rowCopy, fromRowsLower, fromRowsUpper, newObjective, fromColumnsLower, fromColumnsUpper); modelDual.setObjectiveOffset(objOffset); delete [] fromRowsLower; delete [] fromRowsUpper; delete [] fromColumnsLower; delete [] fromColumnsUpper; delete [] newObjective; delete [] which; delete [] rowLower; delete [] rowUpper; modelDual.writeMps("dual.mps"); return 0; } Clp-1.15.10/examples/testBasis.cpp0000644000076600007660000000651011510657150015341 0ustar coincoin/* $Id: testBasis.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { status = model.readMps("small.mps", true); } else { status = model.readMps(argv[1], true); } if (status) exit(10); /* This driver turns a problem into all equalities, solves it and then creates optimal basis. */ // copy of original ClpSimplex model2(model); // And another ClpSimplex model3(model); int originalNumberColumns = model.numberColumns(); int numberRows = model.numberRows(); int * addStarts = new int [numberRows+1]; int * addRow = new int[numberRows]; double * addElement = new double[numberRows]; double * newUpper = new double[numberRows]; double * newLower = new double[numberRows]; double * lower = model2.rowLower(); double * upper = model2.rowUpper(); int iRow; // Simplest is to change all rhs to zero // One should skip E rows but this is simpler coding for (iRow = 0; iRow < numberRows; iRow++) { newUpper[iRow] = upper[iRow]; upper[iRow] = 0.0; newLower[iRow] = lower[iRow]; lower[iRow] = 0.0; addRow[iRow] = iRow; addElement[iRow] = -1.0; addStarts[iRow] = iRow; } addStarts[numberRows] = numberRows; model2.addColumns(numberRows, newLower, newUpper, NULL, addStarts, addRow, addElement); delete [] addStarts; delete [] addRow; delete [] addElement; delete [] newLower; delete [] newUpper; // Modify costs double * randomArray = new double[numberRows]; for (iRow = 0; iRow < numberRows; iRow++) randomArray[iRow] = CoinDrand48(); model2.transposeTimes(1.0, randomArray, model2.objective()); delete [] randomArray; // solve model2.primal(); // first check okay if solution values back memcpy(model.primalColumnSolution(), model2.primalColumnSolution(), originalNumberColumns * sizeof(double)); memcpy(model.primalRowSolution(), model2.primalRowSolution(), numberRows * sizeof(double)); int iColumn; for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) model.setColumnStatus(iColumn, model2.getColumnStatus(iColumn)); for (iRow = 0; iRow < numberRows; iRow++) { if (model2.getRowStatus(iRow) == ClpSimplex::basic) { model.setRowStatus(iRow, ClpSimplex::basic); } else { model.setRowStatus(iRow, model2.getColumnStatus(iRow + originalNumberColumns)); } } model.primal(0); // and now without solution values for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) model3.setColumnStatus(iColumn, model2.getColumnStatus(iColumn)); for (iRow = 0; iRow < numberRows; iRow++) model3.setRowStatus(iRow, model2.getColumnStatus(iRow + originalNumberColumns)); model3.primal(0); return 0; } Clp-1.15.10/examples/hello.mps0000644000076600007660000003024210057415246014522 0ustar coincoinNAME Hello ROWS N OBJROW L R0000000 L R0000001 L R0000002 L R0000003 L R0000004 L R0000005 L R0000006 L R0000007 L R0000008 L R0000009 L R0000010 L R0000011 L R0000012 L R0000013 L R0000014 L R0000015 L R0000016 L R0000017 L R0000018 L R0000019 L R0000020 COLUMNS C0000000 OBJROW 1. R0000000 1. C0000000 R0000001 1. R0000002 1. C0000000 R0000003 1. R0000004 1. C0000000 R0000005 1. R0000006 1. C0000000 R0000007 1. R0000008 1. C0000000 R0000011 1. R0000012 1. C0000000 R0000013 1. R0000014 1. C0000000 R0000015 1. R0000016 1. C0000000 R0000017 1. C0000001 OBJROW 1. R0000004 1. C0000001 R0000018 1. C0000002 OBJROW 1. R0000004 1. C0000002 R0000019 1. C0000003 OBJROW 1. R0000004 1. C0000003 R0000018 1. C0000004 OBJROW 1. R0000004 1. C0000004 R0000017 1. C0000005 OBJROW 1. R0000004 1. C0000005 R0000018 1. C0000006 OBJROW 1. R0000004 1. C0000006 R0000019 1. C0000007 OBJROW 1. R0000004 1. C0000007 R0000018 1. C0000008 OBJROW 1. R0000000 1. C0000008 R0000001 1. R0000002 1. C0000008 R0000003 1. R0000004 1. C0000008 R0000005 1. R0000006 1. C0000008 R0000007 1. R0000008 1. C0000008 R0000011 1. R0000012 1. C0000008 R0000013 1. R0000014 1. C0000008 R0000015 1. R0000016 1. C0000008 R0000017 1. C0000009 OBJROW 1. C0000010 OBJROW 1. C0000011 OBJROW 1. R0000000 1. C0000011 R0000001 1. R0000002 1. C0000011 R0000003 1. R0000004 1. C0000011 R0000005 1. R0000006 1. C0000011 R0000007 1. R0000008 1. C0000011 R0000013 1. R0000014 1. C0000011 R0000015 1. R0000016 1. C0000011 R0000017 1. C0000012 OBJROW 1. R0000000 1. C0000012 R0000004 1. R0000008 1. C0000012 R0000012 1. R0000018 1. C0000013 OBJROW 1. R0000000 1. C0000013 R0000004 1. R0000008 1. C0000013 R0000011 1. R0000019 1. C0000014 OBJROW 1. R0000000 1. C0000014 R0000004 1. R0000008 1. C0000014 R0000011 1. R0000019 1. C0000015 OBJROW 1. R0000000 1. C0000015 R0000004 1. R0000008 1. C0000015 R0000011 1. R0000019 1. C0000016 OBJROW 1. R0000000 1. C0000016 R0000004 1. R0000008 1. C0000016 R0000011 1. R0000019 1. C0000017 OBJROW 1. R0000000 1. C0000017 R0000008 1. R0000011 1. C0000017 R0000019 1. C0000018 OBJROW 1. R0000000 1. C0000018 R0000008 1. R0000012 1. C0000018 R0000018 1. C0000019 OBJROW 1. R0000000 1. C0000019 R0000008 1. R0000013 1. C0000019 R0000014 1. R0000015 1. C0000019 R0000016 1. R0000017 1. C0000020 OBJROW 1. C0000021 OBJROW 1. C0000022 OBJROW 1. R0000000 1. C0000022 R0000001 1. R0000002 1. C0000022 R0000003 1. R0000004 1. C0000022 R0000005 1. R0000006 1. C0000022 R0000007 1. R0000008 1. C0000022 R0000011 1. R0000012 1. C0000022 R0000013 1. R0000014 1. C0000022 R0000015 1. R0000016 1. C0000022 R0000017 1. R0000018 1. C0000022 R0000019 1. C0000023 OBJROW 1. R0000008 1. C0000023 R0000011 1. R0000015 1. C0000024 OBJROW 1. R0000008 1. C0000024 R0000011 1. R0000015 1. C0000025 OBJROW 1. R0000008 1. C0000025 R0000011 1. R0000015 1. C0000025 R0000016 1. C0000026 OBJROW 1. R0000008 1. C0000026 R0000011 1. R0000015 1. C0000026 R0000017 1. C0000027 OBJROW 1. R0000008 1. C0000027 R0000012 1. R0000014 1. C0000027 R0000018 1. C0000028 OBJROW 1. R0000008 1. C0000028 R0000013 1. R0000014 1. C0000028 R0000019 1. C0000029 OBJROW 1. R0000008 1. C0000030 OBJROW 1. R0000008 1. C0000031 OBJROW 1. C0000032 OBJROW 1. C0000033 OBJROW 1. R0000000 1. C0000033 R0000001 1. R0000002 1. C0000033 R0000003 1. R0000004 1. C0000033 R0000005 1. R0000006 1. C0000033 R0000007 1. R0000008 1. C0000033 R0000011 1. R0000012 1. C0000033 R0000013 1. R0000014 1. C0000033 R0000015 1. R0000016 1. C0000033 R0000017 1. R0000018 1. C0000033 R0000019 1. C0000034 OBJROW 1. R0000008 1. C0000034 R0000019 1. C0000035 OBJROW 1. R0000008 1. C0000035 R0000019 1. C0000036 OBJROW 1. R0000008 1. C0000036 R0000019 1. C0000037 OBJROW 1. R0000008 1. C0000037 R0000019 1. C0000038 OBJROW 1. R0000008 1. C0000038 R0000019 1. C0000039 OBJROW 1. R0000008 1. C0000039 R0000019 1. C0000040 OBJROW 1. R0000008 1. C0000040 R0000019 1. C0000041 OBJROW 1. R0000008 1. C0000041 R0000019 1. C0000042 OBJROW 1. C0000043 OBJROW 1. C0000044 OBJROW 1. R0000002 1. C0000044 R0000003 1. R0000004 1. C0000044 R0000005 1. R0000006 1. C0000044 R0000011 1. R0000012 1. C0000044 R0000013 1. R0000014 1. C0000044 R0000015 1. R0000016 1. C0000044 R0000017 1. R0000018 1. C0000044 R0000019 1. C0000045 OBJROW 1. R0000001 1. C0000045 R0000007 1. R0000011 1. C0000045 R0000019 1. C0000046 OBJROW 1. R0000000 1. C0000046 R0000008 1. R0000011 1. C0000046 R0000019 1. C0000047 OBJROW 1. R0000000 1. C0000047 R0000008 1. R0000011 1. C0000047 R0000019 1. C0000048 OBJROW 1. R0000000 1. C0000048 R0000008 1. R0000011 1. C0000048 R0000019 1. C0000049 OBJROW 1. R0000000 1. C0000049 R0000008 1. R0000012 1. C0000049 R0000018 1. C0000050 OBJROW 1. R0000000 1. C0000050 R0000008 1. R0000013 1. C0000050 R0000017 1. C0000051 OBJROW 1. R0000001 1. C0000051 R0000007 1. R0000014 1. C0000051 R0000015 1. R0000016 1. C0000052 OBJROW 1. R0000002 1. C0000052 R0000003 1. R0000004 1. C0000052 R0000005 1. R0000006 1. RHS RHS R0000000 1. R0000001 1. RHS R0000002 1. R0000003 1. RHS R0000004 1. R0000005 1. RHS R0000006 1. R0000007 1. RHS R0000008 1. R0000009 1. RHS R0000010 1. R0000011 1. RHS R0000012 1. R0000013 1. RHS R0000014 1. R0000015 1. RHS R0000016 1. R0000017 1. RHS R0000018 1. R0000019 1. RHS R0000020 1. RANGES RANGE R0000000 1. R0000001 1. RANGE R0000002 1. R0000003 1. RANGE R0000004 1. R0000005 1. RANGE R0000006 1. R0000007 1. RANGE R0000008 1. R0000009 1. RANGE R0000010 1. R0000011 1. RANGE R0000012 1. R0000013 1. RANGE R0000014 1. R0000015 1. RANGE R0000016 1. R0000017 1. RANGE R0000018 1. R0000019 1. RANGE R0000020 1. BOUNDS UP BOUND C0000000 1. UP BOUND C0000001 1. UP BOUND C0000002 1. UP BOUND C0000003 1. UP BOUND C0000004 1. UP BOUND C0000005 1. UP BOUND C0000006 1. UP BOUND C0000007 1. UP BOUND C0000008 1. UP BOUND C0000009 1. UP BOUND C0000010 1. UP BOUND C0000011 1. UP BOUND C0000012 1. UP BOUND C0000013 1. UP BOUND C0000014 1. UP BOUND C0000015 1. UP BOUND C0000016 1. UP BOUND C0000017 1. UP BOUND C0000018 1. UP BOUND C0000019 1. UP BOUND C0000020 1. UP BOUND C0000021 1. UP BOUND C0000022 1. UP BOUND C0000023 1. UP BOUND C0000024 1. UP BOUND C0000025 1. UP BOUND C0000026 1. UP BOUND C0000027 1. UP BOUND C0000028 1. UP BOUND C0000029 1. UP BOUND C0000030 1. UP BOUND C0000031 1. UP BOUND C0000032 1. UP BOUND C0000033 1. UP BOUND C0000034 1. UP BOUND C0000035 1. UP BOUND C0000036 1. UP BOUND C0000037 1. UP BOUND C0000038 1. UP BOUND C0000039 1. UP BOUND C0000040 1. UP BOUND C0000041 1. UP BOUND C0000042 1. UP BOUND C0000043 1. UP BOUND C0000044 1. UP BOUND C0000045 1. UP BOUND C0000046 1. UP BOUND C0000047 1. UP BOUND C0000048 1. UP BOUND C0000049 1. UP BOUND C0000050 1. UP BOUND C0000051 1. UP BOUND C0000052 1. ENDATA Clp-1.15.10/examples/decomp2.cpp0000644000076600007660000000221711510657150014731 0ustar coincoin/* $Id: decomp2.cpp 1662 2011-01-04 17:52:40Z lou $ */ // 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). #include "ClpSimplex.hpp" #include "CoinStructuredModel.hpp" #include int main(int argc, const char *argv[]) { /* Create a structured model by reading mps file and trying Dantzig-Wolfe decomposition (that's the 1 parameter) */ // At present D-W rows are hard coded - will move stuff from OSL #if defined(NETLIBDIR) CoinStructuredModel model((argc < 2) ? NETLIBDIR "/czprob.mps" : argv[1], 1); #else if (argc<2) { fprintf(stderr, "Do not know where to find netlib MPS files.\n"); return 1; } CoinStructuredModel model(argv[1], 1); #endif if (!model.numberRows()) exit(10); // Get default solver - could change stuff ClpSimplex solver; /* This driver does a simple Dantzig Wolfe decomposition */ solver.solve(&model); // Double check solver.primal(1); return 0; } Clp-1.15.10/examples/Makefile.in0000644000076600007660000001237612131314313014737 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 726 2006-04-17 04:16:00Z andreasw $ ########################################################################## # 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@ # CHANGEME: Additional libraries 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 # # COIN 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_NETLIB = @COIN_HAS_NETLIB_TRUE@TRUE # C++ Compiler command CXX = @CXX@ # C++ Compiler options CXXFLAGS = @CXXFLAGS@ # additional C++ Compiler options for linking CXXLINKFLAGS = @RPATH_FLAGS@ # C Compiler command CC = @CC@ # C Compiler options CFLAGS = @CFLAGS@ # 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 # Netlib data directory ifeq ($(COIN_HAS_NETLIB), TRUE) ifeq ($(COIN_HAS_PKGCONFIG), TRUE) CXXFLAGS += -DNETLIBDIR=\"`PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --variable=datadir coindatanetlib`\" CFLAGS += -DNETLIBDIR=\"`PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --variable=datadir coindatanetlib`\" else CXXFLAGS += -DNETLIBDIR=\"@NETLIB_DATA_INSTALLED@\" CFLAGS += -DNETLIBDIR=\"@NETLIB_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 clp` else INCL = @CLPLIB_CFLAGS_INSTALLED@ endif INCL += $(ADDINCFLAGS) # Linker flags ifeq ($(COIN_HAS_PKGCONFIG), TRUE) LIBS = `PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ @PKG_CONFIG@ --libs clp` else ifeq ($(COIN_CXX_IS_CL), TRUE) LIBS = -link -libpath:`$(CYGPATH_W) @abs_lib_dir@` libClp.lib @CLPLIB_LIBS_INSTALLED@ else LIBS = -L@abs_lib_dir@ -lClp @CLPLIB_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 = \ addBits.@OBJEXT@ addBits@EXEEXT@ \ addColumns.@OBJEXT@ addColumns@EXEEXT@ \ addRows.@OBJEXT@ addRows@EXEEXT@ \ decomp2.@OBJEXT@ decomp2@EXEEXT@ \ decomp3.@OBJEXT@ decomp3@EXEEXT@ \ decompose.@OBJEXT@ decompose@EXEEXT@ \ defaults.@OBJEXT@ defaults@EXEEXT@ \ driver2.@OBJEXT@ driver2@EXEEXT@ \ driver.@OBJEXT@ driver@EXEEXT@ \ driverC.@OBJEXT@ driverC@EXEEXT@ \ dualCuts.@OBJEXT@ dualCuts@EXEEXT@ \ ekk.@OBJEXT@ ekk@EXEEXT@ \ ekk_interface.@OBJEXT@ ekk_interface@EXEEXT@ \ hello.@OBJEXT@ hello@EXEEXT@ \ makeDual.@OBJEXT@ makeDual@EXEEXT@ \ minimum.@OBJEXT@ minimum@EXEEXT@ \ modify.@OBJEXT@ modify@EXEEXT@ \ network.@OBJEXT@ network@EXEEXT@ \ pdco.@OBJEXT@ pdco@EXEEXT@ \ piece.@OBJEXT@ piece@EXEEXT@ \ rowColumn.@OBJEXT@ rowColumn@EXEEXT@ \ sprint2.@OBJEXT@ sprint2@EXEEXT@ \ sprint.@OBJEXT@ sprint@EXEEXT@ \ testBarrier.@OBJEXT@ testBarrier@EXEEXT@ \ testBasis.@OBJEXT@ testBasis@EXEEXT@ \ testGub2.@OBJEXT@ testGub2@EXEEXT@ \ testGub.@OBJEXT@ testGub@EXEEXT@ \ testQP.@OBJEXT@ testQP@EXEEXT@ \ useVolume.@OBJEXT@ useVolume@EXEEXT@ all: $(EXE) .SUFFIXES: .cpp .c .o .obj $(EXE): $(OBJS) bla=;\ for file in $(OBJS); do bla="$$bla `$(CYGPATH_W) $$file`"; done; \ $(CXX) $(CXXLINKFLAGS) $(CXXFLAGS) -o $@ $$bla $(LIBS) $(ADDLIBS) clean: rm -rf $(CLEANFILES) .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` Clp-1.15.10/examples/ekk.cpp0000644000076600007660000001357111510657150014157 0ustar coincoin/* $Id: ekk.cpp 1662 2011-01-04 17:52:40Z 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). /* This can be used to compare OSL and Clp. The interface functions below (in ekk_interface.cpp) were written so that calls to osl in the middle of complex algorithms could easily be swapped for Clp code. This was to stress test Clp (and Osl :-)). With the addition of ekk_crash it may be used to see if we need a crash in Clp. With "both" set it can also be used to see which gives better behavior after postSolve. However they may be useful as sample code. Virtuous people would add return code checking. This main could just as easily be C code. */ #include "ekk_c_api.h" // These interface functions are needed // Note - This example wastes memory as it has several copies of matrix /* As ekk_primalSimplex + postsolve instructions: presolve - 0 , no presolve, 1 presolve but no primal after postsolve, 2 do primal if any infeasibilities, 3 always do primal. */ extern "C" int ekk_primalClp(EKKModel * model, int startup, int presolve); /* As ekk_dualSimplex + postsolve instructions: presolve - 0 , no presolve, 1 presolve but no primal after postsolve, 2 do primal if any infeasibilities, 3 always do primal. */ extern "C" int ekk_dualClp(EKKModel * model, int presolve); /* rather like ekk_preSolve (3) plus: keepIntegers - false to treat as if continuous pass - do this many passes (0==default(5)) returns 1 if infeasible */ extern "C" int ekk_preSolveClp(EKKModel * model, bool keepIntegers, int pass); #include "ClpSimplex.hpp" #include #include int main(int argc, const char *argv[]) { const char * name; // problem is actually scaled for osl, dynamically for clp (slows clp) // default is primal, no presolve, minimise and use clp bool primal = true, presolve = false; int useosl = 0; bool freeFormat = false; bool exportIt = false; EKKModel * model; EKKContext * context; if (argc > 1) { name = argv[1]; } else { #if defined(SAMPLEDIR) name = (SAMPLEDIR "/p0033.mps"; #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif } /* initialize OSL environment */ context = ekk_initializeContext(); model = ekk_newModel(context, ""); int i; printf("*** Options "); for (i = 2; i < argc; i++) { printf("%s ", argv[i]); } printf("\n"); // see if free format needed for (i = 2; i < argc; i++) { if (!strncmp(argv[i], "free", 4)) { freeFormat = true; } } // create model from MPS file if (!freeFormat) { ekk_importModel(model, name); } else { ekk_importModelFree(model, name); } // other options for (i = 2; i < argc; i++) { if (!strncmp(argv[i], "max", 3)) { if (!strncmp(argv[i], "max2", 4)) { // This is for testing - it just reverses signs and maximizes int i, n = ekk_getInumcols(model); double * objective = ekk_getObjective(model); for (i = 0; i < n; i++) { objective[i] = -objective[i]; } ekk_setObjective(model, objective); ekk_setMaximize(model); } else { // maximize ekk_setMaximize(model); } } if (!strncmp(argv[i], "dual", 4)) { primal = false; } if (!strncmp(argv[i], "presol", 6)) { presolve = true; } if (!strncmp(argv[i], "osl", 3)) { useosl = 1; } if (!strncmp(argv[i], "both", 4)) { useosl = 2; } if (!strncmp(argv[i], "export", 6)) { exportIt = true; } } if (useosl) { // OSL if (presolve) ekk_preSolve(model, 3, NULL); ekk_scale(model); if (primal) ekk_primalSimplex(model, 1); else ekk_dualSimplex(model); if (presolve) { ekk_postSolve(model, NULL); ekk_primalSimplex(model, 3); } if (useosl == 2) ekk_allSlackBasis(model); // otherwise it would be easy } if ((useosl & 2) == 0) { // CLP if (presolve) ekk_preSolveClp(model, true, 5); /* 3 is because it is ignored if no presolve, and we are forcing Clp to re-optimize */ if (primal) ekk_primalClp(model, 1, 3); else ekk_dualClp(model, 3); } if (exportIt) { ClpSimplex * clp = new ClpSimplex();; int numberRows = ekk_getInumrows(model); int numberColumns = ekk_getInumcols(model); clp->loadProblem(numberColumns, numberRows, ekk_blockColumn(model, 0), ekk_blockRow(model, 0), ekk_blockElement(model, 0), ekk_collower(model), ekk_colupper(model), ekk_objective(model), ekk_rowlower(model), ekk_rowupper(model)); // Do integer stuff int * which = ekk_listOfIntegers(model); int numberIntegers = ekk_getInumints(model); for (int i = 0; i < numberIntegers; i++) clp->setInteger(which[i]); ekk_free(which); clp->writeMps("try1.mps"); delete clp; } ekk_deleteModel(model); ekk_endContext(context); return 0; } Clp-1.15.10/examples/pdco.cpp0000644000076600007660000000427612131314313014323 0ustar coincoin/* $Id: pdco.cpp 1941 2013-04-10 16:52:27Z 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). // It also tests pdco // This reads a network problem created by netgen which can be // downloaded from www.netlib.org/lp/generators/netgen // This is a generator due to Darwin Klingman #include "ClpInterior.hpp" #include "myPdco.hpp" #include #include #include // easy way to allow compiling all sources for this example within one file, // so no need to do something special in Makefile #include "myPdco.cpp" int main(int argc, const char *argv[]) { // Get model in some way ClpInterior model; // Open graph and parameter files //FILE *fpin = fopen("./g.graph","r"); //FILE *fpp = fopen("./gparm","r"); FILE *fpin = fopen("./g.tiny", "r"); FILE *fpp = fopen("./gparm.tiny", "r"); assert(fpin); assert(fpp); myPdco stuff(model, fpin, fpp); Info info; Outfo outfo; Options options; /* * Set the input parameters for LSQR. */ options.gamma = stuff.getD1(); options.delta = stuff.getD2(); options.MaxIter = 40; options.FeaTol = 5.0e-4; options.OptTol = 5.0e-4; options.StepTol = 0.99; // options.x0min = 10.0/num_cols; options.x0min = 0.01; options.z0min = 0.01; options.mu0 = 1.0e-6; options.LSmethod = 3; // 1=Cholesky 2=QR 3=LSQR options.LSproblem = 1; // See below options.LSQRMaxIter = 999; options.LSQRatol1 = 1.0e-3; // Initial atol options.LSQRatol2 = 1.0e-6; // Smallest atol (unless atol1 is smaller) options.LSQRconlim = 1.0e12; info.atolmin = options.LSQRatol2; info.LSdamp = 0.0; // These are already set? model.xsize_ = 50.0 / (model.numberColumns()); model.xsize_ = CoinMin(1.0, model.xsize_); /* * Solve the test problem */ model.pdco(&stuff, options, info, outfo); /* * Examine the results. * Print the residual norms RNORM and ARNORM given by LSQR, and then compute */ return 0; } Clp-1.15.10/examples/addBits.cpp0000644000076600007660000001667112131314313014752 0ustar coincoin/* $Id: addBits.cpp 1941 2013-04-10 16:52:27Z 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). /* This is a simple example to create a model using CoinModel. For even simpler methods see addRows.cpp and addColumns.cpp This reads in one model and then creates another one: a) Row bounds b) Column bounds and objective c) Adds elements one by one by row. Solve It then repeats the exercise: a) Column bounds b) Objective - half the columns as is and half with multiplier of "1.0+multiplier" c) It then adds rows one by one but for half the rows sets their values with multiplier of "1.0+1.5*multiplier" where column affected It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1 (you can have as many different strings as you want) */ #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinModel.hpp" #include #include int main(int argc, const char *argv[]) { // Empty model ClpSimplex model; std::string mpsFileName; if (argc >= 2) mpsFileName = argv[1]; else { #if defined(NETLIBDIR) mpsFileName = NETLIBDIR "/25fv47.mps"; #else fprintf(stderr, "Do not know where to find netlib MPS files.\n"); exit(1); #endif } int status = model.readMps(mpsFileName.c_str(), true); if (status) { fprintf(stderr, "Bad readMps %s\n", mpsFileName.c_str()); fprintf(stdout, "Bad readMps %s\n", mpsFileName.c_str()); exit(1); } // Point to data int numberRows = model.numberRows(); const double * rowLower = model.rowLower(); const double * rowUpper = model.rowUpper(); int numberColumns = model.numberColumns(); const double * columnLower = model.columnLower(); const double * columnUpper = model.columnUpper(); const double * columnObjective = model.objective(); CoinPackedMatrix * matrix = model.matrix(); // 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(); //const int * row = matrix->getIndices(); //const int * columnLength = matrix->getVectorLengths(); //const CoinBigIndex * columnStart = matrix->getVectorStarts(); //const double * elementByColumn = matrix->getElements(); // solve model.dual(); // Now build new model CoinModel build; double time1 = CoinCpuTime(); // Row bounds int iRow; for (iRow = 0; iRow < numberRows; iRow++) { build.setRowBounds(iRow, rowLower[iRow], rowUpper[iRow]); // optional name build.setRowName(iRow, model.rowName(iRow).c_str()); } // Column bounds and objective int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { build.setColumnLower(iColumn, columnLower[iColumn]); build.setColumnUpper(iColumn, columnUpper[iColumn]); build.setObjective(iColumn, columnObjective[iColumn]); // optional name build.setColumnName(iColumn, model.columnName(iColumn).c_str()); } // Adds elements one by one by row (backwards by row) for (iRow = numberRows - 1; iRow >= 0; iRow--) { int start = rowStart[iRow]; for (int j = start; j < start + rowLength[iRow]; j++) build(iRow, column[j], element[j]); } double time2 = CoinCpuTime(); // Now create clpsimplex ClpSimplex model2; model2.loadProblem(build); double time3 = CoinCpuTime(); printf("Time for build using CoinModel is %g (%g for loadproblem)\n", time3 - time1, time3 - time2); model2.dual(); // Now do with strings attached // Save build to show how to go over rows CoinModel saveBuild = build; build = CoinModel(); time1 = CoinCpuTime(); // Column bounds for (iColumn = 0; iColumn < numberColumns; iColumn++) { build.setColumnLower(iColumn, columnLower[iColumn]); build.setColumnUpper(iColumn, columnUpper[iColumn]); } // Objective - half the columns as is and half with multiplier of "1.0+multiplier" // Pick up from saveBuild (for no reason at all) for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = saveBuild.objective(iColumn); if (iColumn * 2 < numberColumns) { build.setObjective(iColumn, columnObjective[iColumn]); } else { // create as string char temp[100]; sprintf(temp, "%g + abs(%g*multiplier)", value, value); build.setObjective(iColumn, temp); } } // It then adds rows one by one but for half the rows sets their values // with multiplier of "1.0+1.5*multiplier" for (iRow = 0; iRow < numberRows; iRow++) { if (iRow * 2 < numberRows) { // add row in simple way int start = rowStart[iRow]; build.addRow(rowLength[iRow], column + start, element + start, rowLower[iRow], rowUpper[iRow]); } else { // As we have to add one by one let's get from saveBuild CoinModelLink triple = saveBuild.firstInRow(iRow); while (triple.column() >= 0) { int iColumn = triple.column(); if (iColumn * 2 < numberColumns) { // just value as normal build(iRow, triple.column(), triple.value()); } else { // create as string char temp[100]; sprintf(temp, "%g + (1.5*%g*multiplier)", triple.value(), triple.value()); build(iRow, iColumn, temp); } triple = saveBuild.next(triple); } // but remember to do rhs build.setRowLower(iRow, rowLower[iRow]); build.setRowUpper(iRow, rowUpper[iRow]); } } time2 = CoinCpuTime(); // Now create ClpSimplex // If small switch on error printing if (numberColumns < 50) build.setLogLevel(1); // should fail as we never set multiplier int numberErrors = model2.loadProblem(build); if( numberErrors == 0 ) { printf("%d errors from model2.loadProblem(build), but we expected some", numberErrors); return 1; } time3 = CoinCpuTime() - time2; // subtract out unsuccessful times time1 += time3; time2 += time3; build.associateElement("multiplier", 0.0); numberErrors = model2.loadProblem(build); assert(!numberErrors); time3 = CoinCpuTime(); printf("Time for build using CoinModel is %g (%g for successful loadproblem)\n", time3 - time1, time3 - time2); build.writeMps("zero.mps"); // It then loops with multiplier going from 0.0 to 2.0 in increments of 0.1 for (double multiplier = 0.0; multiplier < 2.0; multiplier += 0.1) { build.associateElement("multiplier", multiplier); numberErrors = model2.loadProblem(build, true); assert(!numberErrors); model2.dual(); } return 0; } Clp-1.15.10/examples/sprint2.cpp0000644000076600007660000001510712131314313014772 0ustar coincoin/* $Id: sprint2.cpp 1941 2013-04-10 16:52:27Z 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). #include "ClpSimplex.hpp" #include "ClpPresolve.hpp" #include "CoinSort.hpp" #include int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { status = model.readMps("small.mps", true); } else { status = model.readMps(argv[1], true); } if (status) exit(10); /* This driver implements the presolve variation of Sprint. This assumes we can get feasible easily */ int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); // We will need arrays to choose variables. These are too big but .. double * weight = new double [numberRows+numberColumns]; int * sort = new int [numberRows+numberColumns]; double * columnLower = model.columnLower(); double * columnUpper = model.columnUpper(); double * saveLower = new double [numberColumns]; memcpy(saveLower, columnLower, numberColumns * sizeof(double)); double * saveUpper = new double [numberColumns]; memcpy(saveUpper, columnUpper, numberColumns * sizeof(double)); double * solution = model.primalColumnSolution(); // Fix in some magical way so remaining problem is easy #if 0 // This is from a real-world problem for (int iColumn = 0; iColumn < numberColumns; iColumn++) { char firstCharacter = model.columnName(iColumn)[0]; if (firstCharacter == 'F' || firstCharacter == 'P' || firstCharacter == 'L' || firstCharacter == 'T') { columnUpper[iColumn] = columnLower[iColumn]; } } #else double * obj = model.objective(); double * saveObj = new double [numberColumns]; memcpy(saveObj, obj, numberColumns * sizeof(double)); memset(obj, 0, numberColumns * sizeof(double)); model.dual(); memcpy(obj, saveObj, numberColumns * sizeof(double)); delete [] saveObj; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (solution[iColumn]setFactorizationFrequency(100 + model2->numberRows() / 50); model2->primal(); pinfo.postsolve(true); // adjust smallNumberColumns if necessary if (iPass) { double ratio = ((double) smallNumberRows) / ((double) model2->numberRows()); smallNumberColumns = (int)(smallNumberColumns * ratio); // deal with pathological case smallNumberColumns = CoinMax(smallNumberColumns,0); } delete model2; /* After this postsolve model should be optimal. We can use checkSolution and test feasibility */ model.checkSolution(); if (model.numberDualInfeasibilities() || model.numberPrimalInfeasibilities()) printf("%g dual %g(%d) Primal %g(%d)\n", model.objectiveValue(), model.sumDualInfeasibilities(), model.numberDualInfeasibilities(), model.sumPrimalInfeasibilities(), model.numberPrimalInfeasibilities()); // Put back true bounds memcpy(columnLower, saveLower, numberColumns * sizeof(double)); memcpy(columnUpper, saveUpper, numberColumns * sizeof(double)); if ((model.objectiveValue() > lastObjective - 1.0e-7 && iPass > 5) || iPass == maxPass - 1) { break; // finished } else { lastObjective = model.objectiveValue(); // now massage weight so all basic in plus good djs const double * djs = model.dualColumnSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = djs[iColumn]; double value = solution[iColumn]; if (model.getStatus(iColumn) == ClpSimplex::basic) dj = -1.0e50; else if (dj < 0.0 && value < columnUpper[iColumn]) dj = dj; else if (dj > 0.0 && value > columnLower[iColumn]) dj = -dj; else if (columnUpper[iColumn] > columnLower[iColumn]) dj = fabs(dj); else dj = 1.0e50; weight[iColumn] = dj; sort[iColumn] = iColumn; } // sort CoinSort_2(weight, weight + numberColumns, sort); // and fix others for (int iColumn = smallNumberColumns; iColumn < numberColumns; iColumn++) { int kColumn = sort[iColumn]; double value = solution[kColumn]; columnLower[kColumn] = value; columnUpper[kColumn] = value; } } } delete [] weight; delete [] sort; delete [] saveLower; delete [] saveUpper; model.primal(1); return 0; } Clp-1.15.10/examples/g.tiny0000644000076600007660000000007410763274574014044 0ustar coincoin0 1 0 2 1 3 1 4 2 3 2 4 3 5 3 6 4 5 4 6 4 7 5 8 6 8 7 8 8 0 Clp-1.15.10/examples/input.1300000644000076600007660000207141507743336601014300 0ustar coincoinBEGIN NETGEN PROBLEM 130 5000 NODES AND 12500 ARCS USER: 25440925 500 500 1 100 250000 DATA: 500 500 0 100 1 1000 SUPPLY 1 223 2 220 3 1103 4 75 5 800 6 392 7 132 8 622 9 309 10 145 11 113 12 206 13 427 14 480 15 797 16 963 17 339 18 865 19 826 20 1291 21 117 22 481 23 547 24 837 25 935 26 34 27 354 28 390 29 1016 30 934 31 693 32 411 33 137 34 800 35 48 36 854 37 817 38 756 39 523 40 1074 41 507 42 440 43 256 44 22 45 569 46 341 47 410 48 129 49 1269 50 570 51 456 52 320 53 415 54 105 55 445 56 863 57 104 58 620 59 300 60 286 61 435 62 87 63 97 64 435 65 773 66 137 67 99 68 792 69 544 70 558 71 275 72 467 73 350 74 477 75 1231 76 486 77 773 78 422 79 526 80 402 81 602 82 262 83 321 84 1135 85 459 86 915 87 505 88 193 89 1133 90 500 91 742 92 403 93 442 94 1077 95 552 96 398 97 292 98 1180 99 449 100 618 101 623 102 695 103 312 104 447 105 420 106 758 107 880 108 846 109 694 110 804 111 411 112 299 113 395 114 120 115 702 116 269 117 703 118 619 119 172 120 689 121 341 122 699 123 735 124 4 125 764 126 735 127 271 128 564 129 28 130 32 131 822 132 654 133 561 134 644 135 621 136 392 137 964 138 108 139 394 140 1149 141 284 142 433 143 346 144 168 145 982 146 790 147 469 148 287 149 427 150 763 151 407 152 323 153 776 154 1109 155 896 156 288 157 680 158 1632 159 385 160 364 161 1053 162 382 163 582 164 378 165 217 166 412 167 378 168 371 169 420 170 1017 171 719 172 24 173 476 174 692 175 334 176 426 177 26 178 71 179 45 180 97 181 619 182 803 183 236 184 293 185 571 186 497 187 390 188 451 189 545 190 524 191 27 192 402 193 468 194 721 195 497 196 584 197 630 198 755 199 308 200 853 201 1693 202 1352 203 224 204 247 205 688 206 585 207 334 208 526 209 399 210 270 211 826 212 150 213 472 214 545 215 275 216 732 217 675 218 351 219 897 220 572 221 270 222 68 223 843 224 352 225 395 226 584 227 192 228 379 229 325 230 843 231 105 232 978 233 446 234 102 235 315 236 368 237 293 238 391 239 816 240 456 241 490 242 123 243 146 244 498 245 595 246 229 247 761 248 520 249 1198 250 463 251 497 252 529 253 913 254 543 255 584 256 193 257 614 258 449 259 1 260 612 261 349 262 355 263 511 264 1586 265 383 266 192 267 92 268 842 269 601 270 39 271 276 272 363 273 371 274 53 275 486 276 348 277 407 278 647 279 417 280 1070 281 32 282 887 283 387 284 339 285 882 286 400 287 410 288 534 289 932 290 367 291 747 292 470 293 202 294 680 295 354 296 730 297 451 298 408 299 559 300 1159 301 153 302 260 303 689 304 914 305 83 306 256 307 52 308 194 309 1290 310 473 311 717 312 163 313 728 314 756 315 353 316 294 317 316 318 213 319 698 320 407 321 416 322 385 323 532 324 277 325 593 326 972 327 694 328 289 329 1387 330 296 331 922 332 184 333 535 334 1428 335 384 336 271 337 74 338 427 339 400 340 584 341 411 342 656 343 453 344 327 345 729 346 265 347 663 348 968 349 246 350 250 351 144 352 189 353 713 354 317 355 439 356 404 357 937 358 218 359 803 360 333 361 215 362 217 363 757 364 437 365 888 366 318 367 104 368 358 369 451 370 451 371 135 372 753 373 273 374 22 375 284 376 15 377 1020 378 326 379 436 380 360 381 389 382 949 383 311 384 990 385 75 386 563 387 481 388 546 389 455 390 356 391 496 392 525 393 682 394 215 395 632 396 339 397 91 398 326 399 8 400 413 401 448 402 597 403 854 404 227 405 337 406 326 407 402 408 212 409 265 410 415 411 239 412 659 413 603 414 827 415 28 416 309 417 384 418 115 419 386 420 342 421 523 422 309 423 204 424 264 425 632 426 692 427 930 428 648 429 404 430 264 431 1014 432 298 433 498 434 36 435 141 436 957 437 574 438 507 439 257 440 531 441 1178 442 689 443 445 444 422 445 1222 446 404 447 516 448 298 449 359 450 196 451 394 452 412 453 276 454 484 455 635 456 204 457 826 458 169 459 361 460 906 461 1143 462 484 463 670 464 248 465 94 466 109 467 506 468 718 469 381 470 1110 471 414 472 1002 473 327 474 452 475 379 476 315 477 1012 478 572 479 421 480 653 481 492 482 485 483 91 484 667 485 793 486 192 487 631 488 404 489 635 490 60 491 252 492 739 493 117 494 412 495 804 496 472 497 672 498 833 499 1251 500 638 ARCS 1 1890 47 223 1 1745 90 194 1 2252 68 612 505 3498 71 223 505 4707 94 223 505 2628 71 375 941 3285 33 223 941 649 1 308 941 1930 21 351 1730 2231 5 223 1730 2634 42 263 1730 167 50 156 1890 505 61 223 1890 1204 93 959 2231 4450 90 223 2231 1227 77 670 2231 2893 61 898 3285 1730 90 223 3285 2960 2 572 3285 2496 79 227 3498 941 63 223 3498 570 14 579 3498 3089 5 165 4450 4932 35 223 4450 2364 18 89 4450 1331 34 61 2 3149 96 220 2 4853 6 753 1256 3667 25 220 1256 4279 83 645 1256 3207 53 466 2358 4513 73 220 2358 202 63 151 2770 4472 36 220 2770 2837 91 401 3149 3856 15 220 3149 1948 55 604 3149 2839 94 172 3667 2358 69 220 3667 3172 12 305 3667 3591 70 846 3856 4243 52 220 3856 4684 33 220 3856 3273 39 430 4243 2770 30 220 4243 837 85 347 4243 4038 95 343 4472 1256 78 220 4472 2370 2 984 3 3225 42 1103 3 2531 61 326 3 433 2 3 2280 3684 82 1103 2280 715 53 919 2280 514 41 275 2608 3932 17 1103 2608 2138 64 293 2608 1694 49 504 3225 3734 36 1103 3225 3688 86 893 3365 2280 5 1103 3365 4245 17 654 3684 2608 99 1103 3684 4319 1 377 3684 1271 64 104 3734 3365 72 1103 3734 4578 94 1103 3734 3581 65 175 3734 484 57 539 3932 4774 95 1103 3932 820 31 479 3932 3144 36 30 4 3408 51 75 4 1634 14 68 4 4261 21 402 683 4122 86 75 683 4788 98 75 683 4142 75 57 683 1337 77 506 1857 2877 31 75 1857 2111 22 479 1857 1672 7 908 2160 683 89 75 2160 1842 56 797 2877 4822 46 75 2877 4887 67 45 3408 2160 24 75 3408 2475 7 705 3408 2044 30 727 4122 1857 35 75 4122 1102 23 480 5 2037 20 800 5 3900 58 72 5 4855 99 527 859 4848 37 800 859 2944 29 40 859 3611 46 806 864 859 51 800 864 1514 29 725 864 360 95 421 1516 4074 39 800 1516 878 3 910 1516 890 53 47 1950 864 16 800 1950 4648 80 800 1950 1965 76 897 2037 3311 71 800 2037 2166 99 478 3311 1516 44 800 3311 104 62 576 3311 4481 77 158 3786 1950 38 800 3786 159 38 685 3786 3893 27 47 4074 3786 24 800 4074 2348 71 720 6 1315 57 392 6 3193 78 763 521 2260 90 392 521 3029 27 210 1315 2412 30 392 1315 2691 77 852 1315 3526 24 565 2260 2737 62 392 2260 4233 61 486 2412 4019 99 392 2412 1325 75 322 2412 488 44 558 2641 4464 38 392 2641 4649 45 756 2641 1336 25 238 2737 2641 25 392 2737 3789 14 65 2737 378 43 616 2818 4008 20 392 2818 1081 19 814 2818 280 5 694 4008 521 1 392 4008 3922 48 516 4019 2818 83 392 4019 4776 12 392 4019 1938 65 532 4464 4634 88 392 4464 305 23 632 7 3805 73 132 7 2369 76 718 714 3037 87 132 714 1258 71 90 2715 4016 11 132 2715 4484 79 988 2715 1299 58 621 3037 4663 68 132 3037 3922 34 170 3037 2295 45 980 3733 2715 72 132 3733 1463 6 424 3805 4205 17 132 3805 4730 76 132 3805 3271 56 196 4016 714 24 132 4016 1210 69 380 4016 2371 61 209 4205 3733 90 132 4205 2075 10 677 4205 4365 95 361 8 2573 32 622 8 265 96 567 8 2946 23 597 1265 1299 50 622 1265 1230 18 451 1299 3374 13 622 1299 4280 61 408 1299 459 59 186 1326 4821 7 622 1326 4788 37 622 1326 1052 47 231 1326 1812 100 433 2573 3698 82 622 2573 1276 99 401 3374 1326 52 622 3374 4855 58 489 3698 1265 46 622 3698 653 41 113 9 2743 8 309 9 721 55 372 580 1398 98 309 580 4563 16 33 580 3738 66 973 1226 4640 45 309 1226 4243 80 667 1398 3675 94 309 1398 229 78 249 2203 2594 68 309 2203 4043 16 851 2203 857 37 514 2291 3081 63 309 2291 2627 94 252 2291 3559 89 982 2594 2291 34 309 2594 4656 12 309 2594 745 54 682 2602 2203 55 309 2602 3319 91 771 2743 580 13 309 2743 3750 42 94 3081 1226 65 309 3081 570 53 162 3675 2602 55 309 3675 1871 59 328 10 928 55 145 10 2851 51 732 10 2902 16 315 699 3326 64 145 699 4752 53 10 928 4458 11 145 928 4497 82 450 928 952 66 863 1663 3769 59 145 1663 576 49 256 3326 3817 47 145 3326 4344 69 141 3326 3536 30 702 3550 3867 34 145 3550 3793 41 534 3769 3550 82 145 3769 4795 92 145 3769 2302 9 817 3769 3809 88 349 3817 4596 68 145 3817 1627 100 326 3867 699 20 145 3867 2216 13 13 3867 1415 17 931 4458 1663 79 145 4458 3546 100 624 11 609 79 113 11 3674 75 260 11 4712 21 389 609 3975 63 113 609 2367 41 146 2190 2966 39 113 2190 3788 100 811 2190 4752 39 12 2748 3889 15 113 2748 2441 26 516 2748 3825 74 667 2832 3236 45 113 2832 4130 47 134 2832 447 34 941 2966 3963 54 113 2966 4560 94 189 3236 2748 40 113 3236 2307 22 333 3236 4629 41 916 3889 2190 35 113 3889 4118 48 172 3963 4524 42 113 3963 4739 30 113 3963 1077 38 589 3975 2832 7 113 3975 578 97 293 3975 4418 45 880 12 1959 7 206 12 321 43 854 12 586 28 298 1959 3989 66 206 1959 3783 74 508 2413 4730 1 206 2413 3221 5 206 2413 4688 34 37 2990 2413 32 206 2990 2386 68 56 2990 833 78 110 3039 4107 89 206 3039 4793 57 106 3039 328 60 358 3221 3484 4 206 3221 3605 4 179 3484 3760 86 206 3484 2298 80 497 3484 1964 55 761 3760 4518 38 206 3760 2698 94 508 3760 1927 66 694 3989 3039 30 206 3989 2577 34 305 4107 2990 48 206 4107 1964 22 218 4107 4722 21 276 13 3789 28 427 13 4977 8 84 741 2359 47 427 741 2114 26 351 741 1350 97 675 1090 4651 98 427 1090 2134 7 137 1090 1865 14 820 1551 3036 87 427 1551 1157 80 775 1551 3476 70 230 1885 1551 30 427 1885 4891 34 214 2359 3956 22 427 2359 3563 23 54 2799 741 11 427 2799 1066 32 84 2799 2255 33 447 3036 1090 9 427 3036 4640 52 427 3036 4898 55 884 3789 2799 23 427 3789 4552 85 207 3956 1885 16 427 3956 1336 53 744 3956 2873 20 242 14 2070 1 480 14 4783 56 820 14 2062 84 32 2053 3584 53 480 2053 2633 76 657 2070 3088 57 480 2070 3355 9 217 2070 1278 14 707 2092 4916 60 480 2092 3997 37 842 3088 4181 76 480 3088 2766 60 763 3584 2092 9 480 3584 422 26 69 4181 2053 99 480 4181 4874 11 480 4181 3870 26 759 4181 3938 20 814 15 3785 3 797 15 2265 67 471 15 1304 59 113 587 658 87 797 587 3791 23 185 658 4110 12 797 658 1445 65 69 658 4126 90 724 726 857 9 797 726 1085 60 104 726 4105 95 13 857 587 81 797 857 4974 45 797 857 1412 66 385 857 4441 20 230 1738 4242 8 797 1738 2194 82 647 2454 4965 57 797 2454 8 24 559 3785 726 58 797 3785 3286 34 208 3785 2162 81 681 4110 1738 99 797 4110 3466 16 607 4110 1027 9 4 4242 2454 55 797 4242 2802 81 214 16 2713 68 963 16 2425 2 2 541 4655 82 963 541 2793 33 963 541 1084 57 402 541 1056 35 72 681 3351 36 963 681 4280 82 741 681 2257 100 514 1130 2064 54 963 1130 3856 17 328 1130 2286 1 697 2064 3806 7 963 2064 4586 90 963 2064 2927 44 399 2083 681 81 963 2083 4034 14 781 2083 3692 17 329 2713 541 65 963 2713 2456 16 2 2793 3811 14 963 2793 912 39 559 3331 2083 60 963 3331 3700 95 148 3351 3658 7 963 3351 3122 29 810 3351 133 72 668 3658 4719 51 963 3658 1969 21 307 3658 1951 62 365 3806 4358 21 963 3806 2538 53 955 3811 1130 55 963 3811 1971 12 511 4358 3331 71 963 4358 3762 84 208 4358 2800 67 139 17 3009 71 339 17 2373 26 939 17 629 3 38 559 2633 38 339 559 4107 95 887 1610 3588 63 339 1610 1247 27 480 1610 1184 57 133 1694 2652 43 339 1694 4901 91 766 1694 4972 8 139 1864 4981 18 339 1864 4836 81 339 1864 339 33 138 2633 1694 99 339 2633 889 72 547 2633 315 93 255 2652 4133 24 339 2652 3483 42 711 2652 1340 68 19 2939 1864 81 339 2939 2101 39 359 2939 431 65 368 3009 559 39 339 3009 803 90 67 3588 2939 76 339 3588 2656 97 123 4133 1610 64 339 4133 4576 39 371 18 1662 78 865 18 3741 4 401 1155 4588 18 865 1155 3272 11 356 1662 4901 87 865 1662 4432 57 865 1662 4319 77 186 1676 3847 25 865 1676 3898 33 556 1911 2680 76 865 1911 177 35 495 2680 1676 99 865 2680 832 52 121 3847 4196 77 865 3847 3230 26 559 3847 3187 28 702 4196 1155 95 865 4196 2598 36 191 4196 2774 99 249 4432 1911 40 865 4432 180 58 30 4432 499 29 222 19 3610 77 826 19 3267 7 860 630 1214 86 826 630 4134 58 353 845 3372 59 826 845 2587 22 735 1101 4948 81 826 1101 630 80 826 1101 3243 90 434 1101 1994 98 356 1214 845 6 826 1214 4503 32 965 2693 3346 77 826 2693 2633 66 44 2693 4799 24 88 3346 3482 11 826 3346 2527 98 789 3372 4925 41 826 3372 1536 79 31 3372 2936 32 283 3482 1101 68 826 3482 289 67 875 3610 2693 88 826 3610 3190 94 4 3610 3966 43 734 20 3791 46 1291 20 2288 69 488 633 2383 12 1291 633 209 8 673 1309 1441 43 1291 1309 521 96 478 1441 3428 12 1291 1441 3278 15 224 1937 4987 69 1291 1937 3362 84 1291 1937 1364 33 214 2383 1937 23 1291 2383 702 95 467 3234 633 14 1291 3234 1150 14 269 3362 4651 97 1291 3362 184 1 27 3428 3234 6 1291 3428 1060 62 583 3428 3282 18 76 3791 1309 37 1291 3791 4565 10 757 3791 2018 42 773 21 3582 73 117 21 3167 62 463 990 2685 74 117 990 4158 96 572 1157 3155 69 117 1157 143 64 275 1157 4362 94 767 1473 4815 80 117 1473 105 40 383 1473 3025 98 348 1669 4590 75 117 1669 990 55 117 1669 2942 83 910 1669 4649 90 252 2522 1157 65 117 2522 2383 54 633 2685 4398 10 117 2685 4538 35 736 2685 1740 8 951 3155 1473 31 117 3155 1577 38 923 3155 1991 29 277 3412 2522 61 117 3412 2179 74 811 3582 4305 92 117 3582 2058 42 483 3582 4129 98 816 4305 1669 25 117 4305 303 92 414 4305 221 14 989 4398 3412 41 117 4398 2947 25 871 22 3778 14 481 22 900 48 461 803 4738 52 481 803 4571 53 481 803 2873 28 461 1216 2035 5 481 1216 4115 99 436 1216 4443 79 59 2035 2103 31 481 2035 2779 90 661 2084 4299 100 481 2084 1541 3 810 2103 2084 22 481 2103 3419 73 332 3048 803 64 481 3048 4506 52 655 3048 1767 85 482 3778 1216 41 481 3778 4603 41 897 3778 657 19 61 4299 3048 49 481 4299 1121 28 860 4299 1549 77 724 23 2534 69 547 23 1265 74 141 661 1053 21 547 661 504 47 897 1053 2735 41 547 1053 4992 41 15 1053 4483 100 523 1191 4867 59 547 1191 1193 12 547 1191 2700 13 928 1191 367 28 456 1193 3725 40 547 1193 945 7 373 1193 4005 59 850 1471 1191 2 547 1471 4584 88 595 1471 83 22 739 2534 1471 50 547 2534 3661 12 715 2735 4966 35 547 2735 1322 43 577 3725 661 48 547 3725 390 27 436 24 4457 47 837 24 4668 34 873 24 429 17 101 543 1437 18 837 543 4928 63 837 543 1307 70 824 1437 4866 97 837 1437 1758 36 524 2372 543 9 837 2372 4117 28 703 3264 4046 64 837 3264 873 81 406 3264 1517 55 135 3646 3731 88 837 3646 2221 30 246 3646 4595 20 494 3731 3264 71 837 3731 927 73 792 3731 2397 40 747 4046 2372 72 837 4046 634 36 861 4046 926 7 940 4457 3646 25 837 4457 1426 97 486 25 2894 36 935 25 809 2 584 1206 4932 38 935 1206 3131 1 935 1206 4086 70 875 1236 3393 13 935 1236 1195 72 363 1729 3141 13 935 1729 3841 67 468 1729 189 31 887 1770 1236 95 935 1770 2191 51 43 1770 4043 54 149 2342 3069 57 935 2342 4573 96 184 2342 3366 88 849 2843 4486 66 935 2843 1161 65 622 2894 1206 82 935 2894 4764 73 431 3069 4749 13 935 3069 3236 31 219 3131 1729 96 935 3131 4740 55 935 3131 3230 14 293 3131 143 6 848 3141 2843 13 935 3141 3303 4 85 3141 4616 93 1 3393 2342 55 935 3393 1114 24 672 4486 1770 20 935 4486 512 5 844 4486 2383 84 593 26 3964 23 34 26 88 89 25 26 3771 52 111 766 4431 99 34 766 4076 65 129 2115 2337 3 34 2115 1875 91 939 2115 102 71 353 2337 2765 11 34 2337 313 64 715 2337 1718 82 771 2765 4223 25 34 2765 4771 23 34 2765 1325 89 827 2765 4937 5 9 2789 766 18 34 2789 3674 98 648 3802 2789 29 34 3802 3973 99 625 3964 4203 11 34 3964 4253 67 942 3964 2583 47 275 4203 3802 97 34 4203 3843 16 197 4203 3364 99 239 4223 4916 55 34 4223 3397 62 977 4431 2115 15 34 4431 1414 69 985 27 3355 77 354 27 318 84 121 713 896 84 354 713 585 63 56 896 3314 31 354 896 1767 100 158 896 1772 71 441 1378 713 99 354 1378 4414 48 118 2209 1378 100 354 2209 1751 28 819 2209 4077 32 969 2842 2209 98 354 2842 4558 44 549 3314 4737 74 354 3314 4566 9 354 3314 3610 39 894 3314 4266 5 773 3355 2842 82 354 3355 2738 45 279 28 2340 50 390 28 1982 54 445 560 2334 91 390 560 1510 69 633 560 666 92 437 617 2686 36 390 617 2587 22 779 645 3807 37 390 645 1605 62 503 2122 617 53 390 2122 2762 61 59 2254 3154 17 390 2254 333 92 864 2254 3435 55 473 2316 2122 50 390 2316 2518 23 763 2334 2316 63 390 2334 4267 18 674 2340 2254 3 390 2340 3061 100 179 2340 4507 41 202 2686 645 1 390 2686 2929 79 826 3154 4610 12 390 3154 3538 37 390 3154 4792 92 390 3154 4611 27 271 3538 560 84 390 3538 4853 93 919 3538 1937 27 971 3807 4684 37 390 3807 3971 68 205 29 1844 11 1016 29 3884 99 824 563 3095 57 1016 563 3829 97 843 1453 563 15 1016 1453 3142 87 591 1844 2592 80 1016 1844 2843 6 110 1844 709 70 88 1928 4776 85 1016 1928 2803 69 1 1928 3326 31 604 2364 1928 98 1016 2364 4619 42 1016 2364 2473 71 126 2592 1453 72 1016 2592 4521 40 601 2592 2724 97 701 3095 2364 91 1016 3095 4927 98 568 30 1010 8 934 30 2846 60 424 30 150 26 269 738 1858 73 934 738 3868 12 68 738 4739 86 202 940 2759 71 934 940 1583 11 131 1010 3657 67 934 1010 2971 99 250 1010 2032 3 138 1202 940 18 934 1202 3707 54 977 1354 1202 50 934 1354 4869 46 402 1354 1572 70 15 1858 1884 21 934 1858 4829 60 934 1858 1583 33 228 1884 4777 63 934 1884 3888 38 554 1884 2302 45 475 2759 738 44 934 2759 186 46 16 2759 1726 68 458 3061 1354 69 934 3061 3047 70 388 3657 3061 29 934 3657 428 57 154 31 3585 56 693 31 2769 78 723 31 2254 90 998 1098 2549 46 693 1098 4765 15 654 1098 2717 34 551 1599 3521 54 693 1599 4951 60 351 2549 1599 46 693 2549 2542 49 814 2549 598 87 50 3359 4623 29 693 3359 394 39 846 3521 4389 29 693 3521 4017 20 64 3585 4683 33 693 3585 1098 12 693 3585 4715 12 895 3585 3642 83 718 4389 3359 43 693 4389 627 94 555 4389 4511 6 944 32 2825 46 411 32 2989 91 980 32 1897 68 9 1288 1615 24 411 1288 509 25 468 1288 2936 80 696 1615 3404 97 411 1615 3488 41 115 1615 3306 54 27 2133 1288 99 411 2133 4729 87 411 2133 3863 73 751 2133 4040 71 512 2825 3505 95 411 2825 4473 53 527 2825 3891 46 237 3404 4834 67 411 3404 3830 29 812 3404 2916 24 767 3505 2133 65 411 3505 4669 14 628 33 1176 8 137 33 4361 58 798 721 1294 31 137 721 4754 31 137 721 3277 97 408 1176 2038 82 137 1176 602 47 250 1294 1347 19 137 1294 125 98 413 1347 4647 79 137 1347 16 91 482 1347 2851 87 933 2038 2597 16 137 2038 669 70 798 2038 4531 67 123 2237 721 39 137 2237 123 69 216 2237 4967 81 591 2597 2237 3 137 2597 646 54 553 2597 406 92 542 34 2794 77 800 34 4830 9 908 1621 3767 20 800 1621 3714 67 28 1973 4244 45 800 1973 1898 75 241 2046 1973 9 800 2046 4724 1 863 2046 118 52 537 2227 4662 37 800 2227 4459 22 187 2227 3336 40 341 2794 2046 89 800 2794 2739 90 599 3157 1621 49 800 3157 3494 34 679 3767 2227 16 800 3767 4744 7 800 3767 4758 63 873 3767 108 74 694 4244 3157 30 800 4244 415 73 281 4244 4987 70 88 35 1564 72 48 35 782 20 274 35 4287 64 419 1037 1934 67 48 1037 4996 20 12 1037 1692 64 363 1491 3086 32 48 1491 2746 11 353 1491 3621 57 92 1564 3918 54 48 1564 3481 45 900 1564 4688 74 847 1934 4622 31 48 1934 2244 75 48 1934 3761 73 563 2055 1491 20 48 2055 201 21 38 2244 2055 2 48 2244 3991 51 879 2244 3475 70 551 3086 4611 70 48 3086 2405 47 654 3274 1037 9 48 3274 433 64 259 3918 3274 18 48 3918 2824 7 248 36 1696 4 854 36 2848 31 1 36 290 28 614 1148 2960 84 854 1148 3924 89 820 1496 1602 49 854 1496 3642 4 280 1602 3091 60 854 1602 4234 70 312 1696 1148 93 854 1696 3222 15 496 1696 1215 7 858 2960 1496 96 854 2960 4626 61 854 2960 698 43 688 2960 2782 32 372 3091 4894 91 854 3091 628 71 276 3091 251 86 953 37 2345 91 817 37 3013 51 683 1590 4423 14 817 1590 2464 8 613 1590 1745 7 503 1979 4828 7 817 1979 2257 23 35 1979 4348 83 120 2345 1590 46 817 2345 3215 14 872 2345 1180 76 400 2520 2682 49 817 2520 4436 50 295 2682 2970 93 817 2682 4471 51 731 2682 4480 27 149 2970 1979 57 817 2970 4300 64 61 4423 2520 63 817 4423 4892 68 817 4423 725 59 15 4423 4290 23 799 38 829 79 756 38 3503 67 779 746 2810 28 756 746 4212 67 550 746 54 84 390 829 2542 89 756 829 2095 15 630 829 382 24 86 1394 746 54 756 1394 2185 91 484 1394 3163 33 187 1896 4834 90 756 1896 4926 47 756 1896 428 59 433 1896 2645 95 507 2397 2598 69 756 2397 4720 12 42 2542 1394 19 756 2542 4653 36 898 2542 2690 14 265 2598 2965 34 756 2598 827 96 888 2810 2397 62 756 2810 4491 48 6 2810 1478 99 113 2965 1896 96 756 2965 845 75 851 2965 4859 48 396 39 2567 59 523 39 3648 49 726 39 3825 63 948 1054 3118 44 523 1054 1625 1 467 2567 3818 45 523 2567 2959 89 834 2567 1602 93 144 3118 3873 31 523 3118 4637 28 523 3118 3543 50 330 3118 4222 45 497 3818 1054 76 523 3818 4726 100 727 3818 98 70 6 3873 4970 91 523 3873 2000 95 380 3873 635 45 472 40 4274 99 1074 40 2809 28 357 725 4100 70 1074 725 4451 64 946 1654 2888 92 1074 1654 1221 24 529 1654 2703 58 368 2047 4607 100 1074 2047 3772 63 212 2047 4680 88 842 2888 2047 48 1074 2888 4876 3 623 2888 1160 22 191 3909 725 19 1074 3909 3232 1 840 4100 1654 88 1074 4100 4706 56 1074 4100 203 43 426 4100 1749 25 426 4274 3909 39 1074 4274 2248 63 485 41 3449 56 507 41 397 81 544 41 1861 20 632 1081 1616 4 507 1081 4 39 423 1106 4774 87 507 1106 3689 13 783 1106 1812 71 237 1483 1618 41 507 1483 890 28 476 1483 3393 73 447 1616 1752 9 507 1616 1551 61 983 1618 3105 35 507 1618 4080 7 261 1618 4920 57 111 1625 1982 62 507 1625 4272 65 195 1736 4597 94 507 1736 4516 7 507 1736 1625 52 507 1736 503 80 731 1736 3257 4 361 1752 1483 82 507 1752 3205 51 988 1752 3889 98 222 1982 2524 22 507 1982 4474 87 611 2524 1081 37 507 2524 389 35 262 2524 1375 34 833 3105 1106 81 507 3105 4638 20 238 3105 804 25 188 3449 1736 97 507 3449 2279 80 137 3449 1044 15 141 42 2077 67 440 42 4332 100 141 613 4919 27 440 613 1899 66 519 1681 4160 91 440 1681 3786 56 163 2077 2706 40 440 2077 959 30 200 2077 3667 35 424 2197 613 21 440 2197 4641 64 440 2197 4096 22 518 2706 1681 85 440 2706 2325 81 152 3106 2197 52 440 3106 1384 4 469 3106 2615 19 359 4160 3106 82 440 4160 2284 21 160 43 2021 87 256 43 1635 22 683 43 1329 26 210 823 2089 78 256 823 2676 33 796 1503 4794 79 256 1503 2656 65 256 1503 4115 14 196 1503 2627 64 743 2021 2915 9 256 2021 4760 25 425 2021 4047 75 325 2089 1503 96 256 2089 3708 89 189 2089 2977 15 488 2208 4700 55 256 2208 445 73 623 2208 303 37 855 2656 2208 66 256 2656 3339 96 872 2915 823 55 256 2915 4917 69 269 2915 1994 100 708 44 690 67 22 44 1066 29 199 44 3296 48 687 626 2181 71 22 626 4649 76 22 626 1886 27 838 690 626 82 22 690 3598 71 335 690 3316 1 596 1905 3323 3 22 1905 3004 1 985 1905 1010 23 51 2181 2343 2 22 2181 2100 89 716 2181 3750 62 955 2343 1905 50 22 2343 2871 89 974 2343 2443 38 573 3323 3702 59 22 3323 3031 95 425 3702 4206 93 22 3702 841 45 19 4206 4650 76 22 4206 1552 27 596 4206 2502 71 17 45 1079 52 569 45 922 37 300 592 4803 16 569 592 3624 25 48 592 3722 80 88 706 592 9 569 706 3615 46 729 768 4076 30 569 768 1924 18 215 768 2998 6 202 819 706 95 569 819 3972 72 985 819 4224 52 352 1079 4889 8 569 1079 768 87 569 1079 1151 79 131 1702 819 65 569 1702 3541 7 483 1887 2437 49 569 1887 3033 80 429 2437 1702 10 569 2437 3282 86 449 2437 4751 33 886 4076 1887 5 569 4076 2663 8 711 46 2891 93 341 46 4458 48 81 1022 4972 75 341 1022 1045 49 341 1022 2418 13 953 1045 3912 39 341 1045 1869 58 256 1493 3248 33 341 1493 4138 65 397 1787 1493 66 341 1787 3113 64 654 2891 3467 7 341 2891 1947 32 398 3248 4700 90 341 3248 4937 49 804 3248 4185 15 223 3467 1022 94 341 3467 3537 87 390 3467 536 28 396 3912 1787 55 341 3912 3383 6 358 47 2683 39 410 47 320 49 882 679 3860 94 410 679 1966 27 118 679 3483 57 990 1308 4580 34 410 1308 3612 16 410 1308 1960 24 827 1308 2161 52 838 2683 679 79 410 2683 3492 19 918 3001 1308 2 410 3001 3893 68 788 3612 4286 44 410 3612 4230 45 461 3612 4093 40 20 3674 4979 37 410 3674 896 44 524 3674 1309 41 196 3860 3001 38 410 3860 1443 87 266 3860 2255 66 81 4232 3674 67 410 4232 3687 59 364 4232 1782 10 109 4286 4232 15 410 4286 392 51 959 48 2385 11 129 48 707 31 118 729 3792 77 129 729 2665 82 588 729 4717 23 809 2385 3960 91 129 2385 769 58 905 2385 1296 84 628 2387 4887 70 129 2387 1475 92 175 2869 4168 20 129 2869 1753 77 91 2869 151 16 373 3503 2869 85 129 3503 650 94 423 3503 613 24 725 3792 2387 7 129 3792 2555 42 906 3960 4888 59 129 3960 4322 93 129 3960 4948 81 708 3960 2367 25 551 4036 3503 77 129 4036 2959 34 506 4168 729 95 129 4168 4034 33 89 4168 266 88 723 4322 4036 88 129 4322 3 21 160 4322 4094 48 418 49 831 52 1269 49 4763 79 982 49 112 59 271 518 1259 68 1269 518 617 70 841 518 1359 70 261 831 4098 33 1269 831 1415 41 93 1170 2605 6 1269 1170 3414 3 114 1182 518 28 1269 1182 4911 59 649 1259 1726 31 1269 1259 4868 38 770 1671 4705 51 1269 1671 4843 61 1269 1671 2219 63 741 1671 3913 49 816 1726 1170 83 1269 1726 279 41 235 1726 171 84 55 2605 1671 93 1269 2605 2151 56 170 4098 1182 23 1269 4098 3460 32 877 4098 1990 74 206 50 736 67 570 50 689 49 520 50 4628 87 256 736 1069 61 570 736 866 78 533 1041 4041 81 570 1041 4857 3 575 1041 4917 44 924 1069 1041 75 570 1069 2729 18 666 1983 2773 71 570 1983 4799 34 570 1983 4945 95 261 1983 905 11 965 2773 4754 15 570 2773 3892 38 182 4041 1983 6 570 4041 3488 52 471 4041 4606 45 649 51 4422 85 456 51 3598 3 180 51 4132 86 142 1513 3060 24 456 1513 3803 88 786 1608 4139 2 456 1608 846 37 403 2068 1608 26 456 2068 4811 36 456 2068 3222 9 730 3060 4999 23 456 3060 2524 56 227 3060 4274 33 767 4139 1513 74 456 4139 3143 96 624 4422 2068 74 456 4422 1284 66 479 4422 1505 42 635 52 3133 7 320 52 1910 43 481 52 811 21 836 1000 1865 59 320 1000 195 41 151 1000 1768 68 366 1529 1000 94 320 1529 610 85 990 1865 4715 61 320 1865 1574 38 4 2245 1529 65 320 2245 949 2 327 2769 2245 78 320 2769 814 11 339 2957 4485 10 320 2957 408 93 874 2957 655 40 584 3133 3524 12 320 3133 3451 75 611 3133 4482 57 50 3448 2957 5 320 3448 4934 48 320 3448 4273 29 268 3448 4348 19 797 3524 3448 40 320 3524 4545 42 788 4485 2769 98 320 4485 377 80 435 53 2073 98 415 53 3346 73 301 53 1342 48 348 739 3864 100 415 739 2868 60 828 739 39 58 677 814 4923 80 415 814 2812 4 678 1881 3361 31 415 1881 4213 2 866 2032 739 22 415 2032 3538 23 391 2073 4215 92 415 2073 2024 13 930 2073 712 17 366 2433 814 77 415 2433 1467 8 561 2433 2861 80 395 3361 4026 74 415 3361 4527 18 415 3361 4942 40 113 3361 1488 4 395 3864 2433 89 415 3864 3304 78 632 4026 2032 45 415 4026 2360 60 900 4215 1881 86 415 4215 4976 42 811 4215 4052 82 551 54 3488 82 105 54 3267 82 322 1637 4384 11 105 1637 502 55 571 1637 4616 96 636 1886 2130 48 105 1886 1918 49 536 1977 1637 10 105 1977 1861 20 902 2130 4820 64 105 2130 142 59 874 3488 4593 35 105 3488 1977 15 105 3488 2491 9 984 4384 1886 75 105 4384 3337 67 909 55 1163 96 445 55 1296 46 957 55 4058 17 439 603 2477 43 445 603 2582 98 323 603 2797 7 370 1126 603 15 445 1126 1352 28 458 1126 223 89 748 1163 3640 61 445 1163 739 20 289 1275 1126 64 445 1275 1885 53 343 1275 738 87 438 1283 3442 45 445 1283 2625 98 204 1584 4762 79 445 1584 4701 37 445 1584 1740 58 710 2477 1584 93 445 2477 3216 93 870 3442 1275 9 445 3442 3694 21 575 3489 1283 67 445 3489 4987 41 12 3489 2740 27 196 3640 3489 22 445 3640 1046 59 665 3640 3084 58 498 56 3594 78 863 56 2228 77 437 860 4304 98 863 860 4602 90 863 860 3131 74 416 860 3277 97 610 912 2752 78 863 912 4897 42 445 912 3106 99 23 2752 860 53 863 2752 1607 38 677 3003 4594 57 863 3003 3133 12 205 3003 4846 26 471 3349 912 96 863 3349 3759 54 971 3349 2706 97 660 3594 3349 81 863 3594 4409 40 36 3594 4462 88 261 4304 3003 57 863 4304 2786 24 430 4304 2732 100 468 57 4329 93 104 57 3653 23 686 57 369 55 298 1776 2666 82 104 1776 4366 49 624 1776 1710 8 400 1941 3161 72 104 1941 4800 10 104 1941 287 48 991 1941 1086 11 840 1952 1776 14 104 1952 714 72 62 2666 4734 36 104 2666 4359 3 261 3161 4342 78 104 3161 4778 30 960 3161 1180 21 761 3876 1952 44 104 3876 3034 70 104 3876 2921 92 133 4329 1941 30 104 4329 3528 74 872 4342 3876 11 104 4342 737 3 397 58 4273 55 620 58 66 85 33 58 3027 30 167 2097 3231 6 620 2097 1633 90 546 2097 1925 76 513 2488 2097 100 620 2488 3135 72 819 2488 3412 20 329 3089 3202 27 620 3089 2693 53 370 3089 4454 97 961 3202 3224 94 620 3202 3935 1 466 3224 4569 63 620 3224 1096 34 917 3224 3894 4 791 3231 3451 58 620 3231 4797 56 243 3231 2411 45 177 3451 4343 64 620 3451 4940 62 620 3451 2881 44 225 3451 1564 37 100 4273 2488 25 620 4273 1289 97 902 4343 3089 31 620 4343 1132 74 677 4343 2234 33 142 59 2523 21 300 59 4912 50 128 59 1419 19 300 1205 2110 3 300 1205 102 28 616 1305 2375 15 300 1305 4581 78 674 2110 4505 36 300 2110 1305 21 300 2110 4032 88 487 2375 4829 33 300 2375 1027 26 645 2523 1205 78 300 2523 4168 38 806 60 1061 97 286 60 2677 12 71 1061 3241 46 286 1061 199 19 311 1061 498 23 238 1832 2673 98 286 1832 2189 98 186 1832 4795 10 893 2257 1832 55 286 2257 72 87 587 2673 4720 48 286 2673 2709 75 498 2673 812 9 966 2852 4860 73 286 2852 3175 55 286 2852 1221 9 519 3175 4461 28 286 3175 4032 60 705 3241 2852 69 286 3241 2373 85 517 3241 4544 61 258 4461 2257 93 286 4461 770 90 63 61 1250 83 435 61 3215 52 624 853 1703 49 435 853 4587 76 435 853 4742 52 223 853 2132 7 837 1250 853 51 435 1250 2087 3 773 1642 1876 27 435 1642 476 86 887 1642 3153 81 22 1703 1642 51 435 1703 1191 76 648 1703 49 70 89 1840 4603 85 435 1840 2050 83 521 1876 1840 65 435 1876 2208 77 633 62 3309 9 87 62 1942 79 920 62 3568 53 381 608 2161 23 87 608 4530 50 822 869 1823 74 87 869 3054 90 511 1269 2117 7 87 1269 4954 77 941 1269 4888 12 115 1296 869 54 87 1296 4273 100 677 1823 3005 54 87 1823 1083 75 793 2117 3162 4 87 2117 2757 35 722 2161 4860 55 87 2161 3921 4 832 3005 1269 28 87 3005 4285 20 16 3005 4287 8 593 3162 608 90 87 3162 455 22 967 3162 3909 40 926 3309 1296 49 87 3309 4966 31 87 3309 782 53 985 3309 4448 88 294 63 3454 86 97 63 638 63 630 1403 3243 61 97 1403 1559 6 502 1820 3208 43 97 1820 559 78 466 2419 4796 27 97 2419 4603 61 97 2419 3740 11 470 2419 4129 38 45 3208 3302 77 97 3208 2553 36 354 3208 439 95 431 3243 1820 58 97 3243 3795 9 260 3302 2419 52 97 3302 2706 32 398 3302 4356 90 158 3454 4394 67 97 3454 1459 48 190 3454 565 91 112 4394 1403 1 97 4394 4806 92 587 64 1925 100 435 64 305 62 484 837 4637 99 435 837 4972 90 435 837 1592 25 557 1032 2365 87 435 1032 748 65 242 1032 4487 89 863 1925 3996 98 435 1925 612 63 423 2264 3514 13 435 2264 1353 17 411 2365 837 7 435 2365 2697 14 954 3514 1032 79 435 3514 3878 59 966 3996 2264 35 435 3996 262 31 909 65 2164 93 773 65 1415 53 502 65 2070 16 376 841 4400 1 773 841 1984 37 785 841 3727 28 374 893 3948 48 773 893 3871 37 777 893 4641 76 243 1036 3308 74 773 1036 4033 70 625 1036 4103 53 850 1812 4567 11 773 1812 3367 87 289 2164 841 24 773 2164 1199 86 255 3308 893 75 773 3308 2179 74 774 3308 708 99 202 3948 1812 70 773 3948 4554 41 773 3948 3541 34 928 4400 1036 34 773 4400 4887 93 405 4400 1783 46 65 66 3072 83 137 66 3650 87 350 66 1791 22 190 590 4593 92 137 590 2433 52 64 590 4904 74 151 2615 4126 23 137 2615 4509 55 259 2615 289 75 744 3072 3136 92 137 3072 2589 35 6 3136 3344 61 137 3136 1095 48 726 3344 4875 51 137 3344 3592 74 137 3344 3991 40 431 3592 4010 100 137 3592 2868 87 636 3592 1704 23 941 4010 2615 33 137 4010 2707 63 258 4126 590 6 137 4126 2656 93 897 67 3090 6 99 67 84 17 240 67 3155 62 118 1183 3743 90 99 1183 2073 69 980 2378 2824 79 99 2378 1857 45 773 2378 3229 44 126 2824 3581 70 99 2824 2975 68 257 2824 42 1 695 3090 2378 4 99 3090 92 47 815 3090 4016 26 584 3411 3961 7 99 3411 4708 42 99 3411 439 29 152 3411 587 41 59 3581 3411 45 99 3581 2234 22 470 3743 4733 97 99 3743 1519 2 793 3961 1183 92 99 3961 1054 34 250 68 1111 52 792 68 734 28 318 68 118 36 853 591 4388 20 792 591 2805 54 228 838 3038 57 792 838 97 78 544 861 2054 41 792 861 1963 37 996 861 1123 28 665 1111 3718 1 792 1111 1459 71 689 1111 592 17 290 1978 838 88 792 1978 762 32 884 1978 674 56 781 2054 1978 12 792 2054 1869 14 835 2054 4450 6 708 2314 4527 79 792 2314 3221 67 465 2314 3227 56 185 3038 591 59 792 3038 4955 70 792 3038 777 12 603 3038 2711 2 45 3718 861 8 792 3718 3504 68 528 4388 2314 42 792 4388 2991 26 849 4388 1894 24 105 69 751 81 544 69 3944 47 339 751 1333 24 544 751 22 81 656 751 2806 95 124 1310 3121 83 544 1310 3636 76 556 1333 3732 45 544 1333 4301 56 823 1333 360 35 655 2152 1310 5 544 2152 499 6 103 2152 94 15 174 2538 4520 44 544 2538 2906 81 544 2538 1297 41 185 2906 3209 49 544 2906 3993 60 657 3121 4549 13 544 3121 2815 16 951 3121 3812 7 523 3209 2152 56 544 3209 1089 48 475 3209 4396 23 766 3732 2538 31 544 3732 4575 95 410 3732 4807 54 534 70 3020 92 558 70 2643 28 138 576 3833 82 558 576 4608 94 646 680 4864 94 558 680 1614 6 558 680 2544 60 25 999 1991 45 558 999 4688 73 558 999 3409 96 835 999 324 20 534 1108 999 10 558 1108 1926 8 964 1108 2698 98 160 1189 2583 13 558 1189 1627 78 159 1189 4858 47 797 1588 4625 97 558 1588 438 69 735 1588 706 60 928 1614 576 30 558 1614 4896 65 945 1991 1189 22 558 1991 1443 56 873 2583 4017 86 558 2583 1043 24 678 2583 4064 25 393 3020 1108 13 558 3020 4924 68 646 3833 1588 33 558 3833 1509 10 440 4017 680 45 558 4017 1692 5 779 4017 3333 62 343 71 3590 78 275 71 1512 32 518 71 3566 55 276 971 1350 84 275 971 2908 18 125 1011 2849 4 275 1011 3385 17 722 1268 1011 40 275 1268 583 31 507 1268 1493 63 191 1350 1268 82 275 1350 4975 20 275 1350 4048 32 719 2543 4784 72 275 2543 2018 17 205 2849 2543 43 275 2849 1350 93 924 3240 971 63 275 3240 2980 51 965 3240 2638 59 331 3415 3240 24 275 3415 2088 21 438 3590 4092 64 275 3590 3998 69 935 4092 3415 70 275 4092 4350 88 751 72 1817 36 467 72 1927 31 60 795 4877 6 467 795 3051 97 442 1817 4529 20 467 1817 4247 83 467 1817 653 86 8 1817 4265 64 86 2667 795 22 467 2667 118 88 209 2667 1924 38 119 2911 2976 96 467 2911 218 88 726 2911 6 33 538 2976 2667 63 467 2976 2351 13 372 2976 1188 1 470 3999 2911 31 467 3999 435 5 512 4247 3999 91 467 4247 760 72 391 4247 881 41 911 73 1860 76 350 73 550 69 788 73 957 25 889 578 4355 45 350 578 544 28 866 1068 3881 7 350 1068 3793 5 129 1068 4257 46 192 1860 578 89 350 1860 4833 60 350 1860 2842 37 825 2075 1068 19 350 2075 2035 91 23 2646 4625 92 350 2646 97 11 977 2646 4851 18 499 2838 2075 35 350 2838 2389 61 682 3881 4495 8 350 3881 3367 13 121 4334 2646 88 350 4334 3033 32 691 4334 1914 56 676 4355 2838 63 350 4355 4316 29 331 4495 4334 64 350 4495 444 73 167 74 1293 3 477 74 2001 79 749 74 73 98 410 524 4730 53 477 524 4896 71 366 524 3647 48 716 1293 4350 43 477 1293 4609 7 537 1293 3988 84 852 1432 3030 4 477 1432 4616 86 884 2124 3850 36 477 2124 1651 39 638 2124 2499 75 831 3030 2124 16 477 3030 2488 51 132 3030 4990 59 679 3850 524 23 477 3850 4003 28 500 3850 1910 90 86 4350 1432 57 477 4350 4785 13 477 4350 1306 16 886 4350 4830 59 126 75 3613 48 1231 75 1858 10 886 75 2110 17 162 1153 2657 24 1231 1153 4470 34 591 1153 1279 71 708 1215 4933 28 1231 1215 1572 45 938 1457 1215 64 1231 1457 4897 11 368 1568 1690 82 1231 1568 3105 93 800 1690 1457 34 1231 1690 1454 92 186 2657 1568 32 1231 2657 4954 17 575 2657 2941 29 94 3613 3949 50 1231 3613 1747 53 757 3949 4411 32 1231 3949 4761 47 528 4411 1153 35 1231 4411 4868 81 1231 4411 2760 75 454 4411 1081 53 963 76 1468 11 486 76 650 39 678 791 3902 90 486 791 4226 36 985 791 2773 2 356 972 3556 50 486 972 695 32 173 972 2163 3 235 1369 972 33 486 1369 666 88 597 1396 791 100 486 1396 1051 67 905 1468 1396 80 486 1468 534 71 398 3556 3762 24 486 3556 2610 84 919 3556 4489 5 833 3762 4749 27 486 3762 4516 9 486 3762 2717 97 653 3902 4013 42 486 3902 2667 39 468 4013 1369 30 486 4013 272 67 749 77 3700 69 773 77 2638 66 273 77 3307 4 750 1469 2090 19 773 1469 1544 38 86 1469 965 42 690 1678 2577 3 773 1678 987 80 998 2090 2400 3 773 2090 4557 28 773 2090 3561 100 6 2090 1032 38 575 2400 2758 79 773 2400 2159 98 351 2577 2841 37 773 2577 3387 69 700 2758 3203 42 773 2758 4693 64 723 2758 552 57 811 2841 3637 71 773 2841 4068 59 106 2841 2948 67 830 3203 4587 25 773 3203 2169 97 486 3203 3487 23 856 3637 1469 54 773 3637 169 91 773 3637 4803 5 656 3700 1678 14 773 3700 4894 100 749 3700 3254 5 674 78 4195 37 422 78 2431 96 456 78 1292 25 432 637 3080 91 422 637 361 16 278 2287 4810 89 422 2287 4366 83 881 2287 2684 42 75 2977 2287 9 422 2977 3539 46 913 2977 3959 10 970 3080 4770 49 422 3080 2977 56 422 3080 3993 16 344 3080 3976 98 35 4195 637 73 422 4195 2336 77 837 79 3474 78 526 79 4411 1 145 79 399 97 616 1874 2949 39 526 1874 317 31 257 1874 2915 58 817 2949 4569 12 526 2949 166 35 134 2949 4792 72 924 3474 4057 50 526 3474 4597 20 526 3474 4563 20 94 3474 3032 78 434 3629 3803 56 526 3629 2282 54 710 3803 4289 48 526 3803 1246 87 997 4012 1874 53 526 4012 2941 54 652 4012 3666 39 471 4057 3629 90 526 4057 1023 39 876 4289 4012 42 526 4289 2646 67 205 4289 4670 72 21 80 2921 95 402 80 2138 7 282 1532 2135 73 402 1532 3684 21 760 1891 3908 63 402 1891 259 38 652 1891 1941 3 248 2135 4515 67 402 2135 3691 95 279 2141 3959 14 402 2141 341 28 309 2921 4198 45 402 2921 3242 72 376 3628 4492 9 402 3628 2332 61 715 3908 4011 60 402 3908 2677 85 525 3959 3628 14 402 3959 215 51 625 4011 1532 33 402 4011 3063 93 192 4198 2141 91 402 4198 4839 50 402 4198 1710 94 229 4198 3047 50 553 4492 1891 52 402 4492 2274 69 268 81 2434 6 602 81 4235 63 785 951 3027 53 602 951 3188 58 380 951 708 3 825 1026 2166 78 602 1026 1759 42 779 1822 3316 41 602 1822 451 10 517 2166 4572 35 602 2166 1001 19 234 2434 2636 55 602 2434 2924 58 924 2636 3298 64 602 2636 1171 34 755 2636 714 4 199 3027 4265 74 602 3027 1070 78 93 3298 951 91 602 3298 212 26 911 3298 3070 33 905 3316 4051 2 602 3316 4868 65 296 3316 2303 80 96 4051 1026 73 602 4051 48 32 377 4265 1822 77 602 4265 4840 89 602 4265 333 2 811 82 3207 87 262 82 2016 98 787 82 4323 23 472 2156 3102 41 262 2156 4856 43 262 2156 194 91 342 2156 4406 12 241 2282 2156 87 262 2282 3600 21 878 2282 2105 3 180 2902 4754 8 262 2902 188 2 596 2902 2611 63 49 3102 3922 97 262 3102 4150 64 565 3102 4750 97 446 3207 2282 12 262 3207 3378 88 279 3922 2902 19 262 3922 2040 45 500 83 2167 34 321 83 3772 54 32 554 2414 11 321 554 924 9 413 554 613 83 57 966 4272 91 321 966 4552 33 321 966 4564 56 797 966 4208 47 501 2167 3000 69 321 2167 4888 82 209 2167 3364 6 731 2171 2511 42 321 2171 1086 29 50 2296 2171 44 321 2296 4443 1 861 2296 4169 21 480 2351 2296 66 321 2351 2404 68 775 2351 2335 88 897 2414 966 34 321 2414 3381 71 435 2511 554 80 321 2511 67 17 398 3000 2351 63 321 3000 3369 54 444 3000 822 11 704 4272 4572 65 321 4272 4649 41 936 4272 922 10 679 84 2517 5 1135 84 3461 36 852 1073 2399 56 1135 1073 4178 75 920 1073 2453 84 839 1535 1073 19 1135 1535 3869 58 188 2399 3891 62 1135 2399 4528 98 855 2399 507 60 98 2517 4478 49 1135 2517 1570 85 993 3834 1535 36 1135 3834 1298 55 903 3834 4853 68 572 3891 4717 60 1135 3891 1586 72 318 3891 1121 94 954 4478 3834 28 1135 4478 4875 64 1135 4478 3712 34 959 4478 234 26 160 85 2828 6 459 85 2695 75 62 622 2427 33 459 622 4996 62 897 830 4765 48 459 830 4872 82 921 830 1500 35 109 1763 3735 12 459 1763 4070 78 274 2427 830 36 459 2427 4905 23 459 2427 3147 1 569 2427 421 19 618 2489 3755 83 459 2489 1477 94 293 2489 4960 89 480 2828 2489 14 459 2828 4961 64 644 2828 2108 24 513 3735 622 74 459 3735 4532 36 50 3735 58 65 672 3755 1763 34 459 3755 955 82 247 3755 216 99 975 86 3172 63 915 86 2576 5 971 974 3007 94 915 974 3226 30 773 1178 4784 12 915 1178 4710 94 915 1178 2987 36 508 2059 974 21 915 2059 4526 76 557 3007 1178 64 915 3007 4610 45 967 3172 3315 51 915 3172 1790 8 66 3315 2059 90 915 3315 3801 47 499 3315 2909 98 704 87 1958 92 505 87 2342 15 288 826 1629 34 505 826 2435 93 127 826 508 22 516 1272 1969 66 505 1272 127 96 585 1272 3733 90 796 1629 4035 58 505 1629 827 6 311 1629 2318 79 500 1958 4668 44 505 1958 1272 91 505 1958 4991 24 322 1969 2916 59 505 1969 992 56 723 1969 2053 72 260 2546 4815 11 505 2546 962 34 28 2916 826 37 505 2916 3974 97 202 4035 2546 6 505 4035 4988 15 268 88 957 70 193 88 4453 34 366 88 2187 93 135 957 3275 33 193 957 4735 79 193 957 4367 2 158 1474 2586 78 193 1474 1806 56 318 1474 1342 52 728 1747 2529 55 193 1747 948 13 955 1747 4244 43 745 2529 4468 95 193 2529 3203 98 350 2529 4454 45 919 2586 5000 32 193 2586 1293 79 987 3275 1747 74 193 3275 4297 8 884 3574 1474 46 193 3574 339 77 766 3574 997 41 384 4468 3574 7 193 4468 1611 60 173 4468 2428 46 43 89 3013 85 1133 89 3914 36 527 868 2491 88 1133 868 1531 28 467 868 2073 87 769 1102 1358 79 1133 1102 556 20 37 1102 575 3 956 1358 868 71 1133 1358 4483 83 798 1358 3712 11 50 2162 2350 14 1133 2162 690 11 222 2350 4544 40 1133 2350 4967 68 1133 2350 4682 39 920 2491 2162 68 1133 2491 3853 51 995 2491 2110 59 856 3013 1102 38 1133 3013 3523 71 167 3013 4563 3 313 90 1245 75 500 90 1680 96 485 90 4649 37 725 1121 3880 23 500 1121 1891 25 391 1121 948 78 448 1245 3043 40 500 1245 4679 83 89 1522 3570 99 500 1522 4310 5 416 1522 2656 94 363 2819 1522 62 500 2819 364 54 844 2819 76 55 366 3043 2819 10 500 3043 2593 27 516 3043 1101 13 674 3093 4559 39 500 3093 3399 17 746 3093 2913 56 943 3570 1121 82 500 3570 4712 98 500 3570 1172 76 522 3880 3093 84 500 3880 1111 7 690 91 3168 47 742 91 4704 57 882 781 4696 8 742 781 576 37 512 788 2622 17 742 788 3437 63 272 1772 2993 98 742 1772 2661 16 990 1772 2140 9 737 2622 3350 91 742 2622 3593 6 913 2993 4377 77 742 2993 371 47 668 3168 788 62 742 3168 255 71 602 3350 1772 78 742 3350 4117 63 355 3350 3346 66 779 4239 781 12 742 4239 3199 98 142 4377 4239 63 742 4377 4705 63 742 4377 896 46 419 92 3911 81 403 92 4815 47 696 696 2855 33 403 696 4512 92 403 696 3725 12 387 908 696 37 403 908 2771 45 110 2855 3616 33 403 2855 2413 8 439 2855 1667 63 520 2884 3185 81 403 2884 1845 28 715 2884 142 72 774 3185 908 100 403 3185 2943 72 437 3185 676 41 556 3616 4787 8 403 3616 4802 75 969 3911 2884 81 403 3911 2032 26 148 3911 3155 92 273 93 1285 13 442 93 1256 87 384 1085 4094 36 442 1085 3504 39 934 1285 2258 26 442 1285 3527 79 807 1285 2768 34 598 1442 1485 8 442 1442 915 6 951 1485 2654 64 442 1485 3834 80 555 1485 3994 82 761 1524 1085 67 442 1524 2940 59 917 1524 4380 67 454 2258 2506 49 442 2258 888 40 968 2258 980 67 841 2506 4121 61 442 2506 3016 83 650 2506 3243 39 246 2654 1524 38 442 2654 4535 30 722 2654 988 53 548 4094 4685 12 442 4094 4510 64 442 4094 1033 91 642 4094 4770 80 996 4121 1442 10 442 4121 2192 41 977 4121 4085 72 940 94 2229 77 1077 94 864 62 198 94 2522 67 40 880 1030 94 1077 880 1133 98 242 1030 2196 41 1077 1030 2607 30 569 1030 435 7 884 1064 2095 28 1077 1064 3483 14 555 2095 4002 9 1077 2095 1959 43 780 2095 1025 39 552 2196 1064 24 1077 2196 4604 60 1077 2196 4337 15 88 2196 349 100 413 2229 2555 86 1077 2229 3259 20 993 2555 880 4 1077 2555 1875 31 461 2555 1770 13 923 4002 4553 25 1077 4002 4973 4 739 4002 2160 63 399 95 1105 13 552 95 1626 85 155 95 4780 39 558 1105 2469 94 552 1105 4968 42 897 1105 4017 36 39 1499 4104 9 552 1499 4566 47 818 1656 4810 20 552 1656 1681 15 267 1660 1656 44 552 1660 4967 14 552 1660 4458 23 433 1796 3838 1 552 1796 1269 23 47 1796 2440 84 947 2469 4224 56 552 2469 4494 33 344 2469 1318 46 254 3838 1499 38 552 3838 863 68 932 3838 782 32 273 4104 1660 84 552 4104 2815 49 146 4104 384 12 65 4224 1796 64 552 4224 635 59 561 96 2831 40 398 96 360 76 538 547 4551 17 398 547 1488 19 398 547 4603 31 55 1488 3555 81 398 1488 2938 23 23 2831 3052 95 398 2831 899 82 38 2831 4748 86 300 3052 3437 46 398 3052 1237 7 945 3437 547 12 398 3437 4121 8 414 3555 4805 20 398 3555 3697 82 315 3555 1512 94 36 97 1262 55 292 97 4976 40 928 97 893 79 428 1262 4226 15 292 1262 2843 85 105 1430 2530 25 292 1430 764 7 449 1430 184 27 848 1708 4755 43 292 1708 4704 7 292 1708 4758 48 752 1708 3301 98 375 2034 2518 94 292 2034 1290 40 415 2034 4317 58 149 2328 1430 61 292 2328 660 86 174 2518 1708 29 292 2518 1002 64 215 2518 1546 19 458 2530 2034 78 292 2530 248 11 55 3405 2328 16 292 3405 4212 34 459 4226 3405 58 292 4226 2372 48 85 4226 1179 5 406 98 2206 11 1180 98 3981 19 359 1984 3801 60 1180 1984 4359 19 396 1984 3450 12 763 2206 3327 96 1180 2206 3614 67 34 3252 4910 24 1180 3252 1444 42 463 3252 2544 3 384 3327 4406 84 1180 3327 3531 4 797 3327 1981 6 795 3801 3252 2 1180 3801 4954 42 1180 3801 3455 84 818 3801 2733 58 253 4406 1984 50 1180 4406 1363 99 20 4406 4460 43 221 99 1426 5 449 99 3868 45 417 1033 1707 48 449 1033 4540 34 582 1033 4390 90 537 1426 1033 78 449 1426 1973 39 859 1707 3075 4 449 1707 340 77 364 1707 2656 45 407 1932 3458 38 449 1932 3174 52 401 1932 1745 10 567 3075 3507 61 449 3075 3216 81 904 3458 3826 95 449 3458 2361 3 445 3507 1932 53 449 3507 4667 64 449 3507 3187 15 596 3507 3053 56 624 3826 4596 82 449 3826 4735 85 173 100 2933 66 618 100 3283 61 752 2214 3465 33 618 2214 3105 74 368 2214 926 45 504 2232 2964 45 618 2232 2912 36 528 2232 4912 71 46 2330 2214 78 618 2330 2796 55 197 2330 218 27 27 2933 2232 39 618 2933 4575 75 595 2933 1473 100 380 2964 3977 38 618 2964 4738 66 618 2964 1513 88 211 3465 4825 68 618 3465 4019 41 614 3465 591 47 214 3492 3893 28 618 3492 934 35 584 3492 1613 20 543 3893 2330 20 618 3893 3425 71 204 3893 3098 31 885 3977 3492 8 618 3977 3337 12 273 3977 3129 20 758 101 4093 64 623 101 2346 8 300 101 44 7 833 581 4515 1 623 581 4648 40 623 581 3785 70 671 663 2620 53 623 663 4200 45 426 663 65 57 748 854 663 35 623 854 303 73 904 2620 3539 84 623 2620 3922 50 374 2668 4037 51 623 2668 1316 27 241 2668 3846 14 378 3539 3848 10 623 3539 2802 15 714 3848 2668 27 623 3848 2410 35 272 3848 4371 33 940 4037 581 52 623 4037 576 59 823 4037 1292 35 881 4093 854 82 623 4093 1696 56 733 102 3112 28 695 102 3029 38 598 102 2659 38 981 2175 3605 34 695 2175 2253 93 235 2753 4730 80 695 2753 3869 40 866 2798 2753 99 695 2798 3814 70 302 2798 4260 61 4 3112 4378 66 695 3112 2573 13 60 3112 3788 71 86 3605 4170 12 695 3605 2818 7 272 4170 2798 3 695 4170 871 90 79 4170 1376 9 36 4378 2175 26 695 4378 4797 22 695 4378 1485 9 200 4378 4627 45 690 103 3419 15 312 103 2244 64 796 103 2117 79 659 947 2066 83 312 947 3735 96 965 1948 3017 56 312 1948 2771 57 977 2066 1948 64 312 2066 4188 27 372 2066 4544 28 588 2112 3443 48 312 2112 1716 54 109 2112 4894 22 304 3017 4141 34 312 3017 4301 73 957 3419 947 67 312 3419 4750 34 312 3419 3115 100 96 3443 4657 46 312 3443 942 97 720 4141 2112 95 312 4141 1181 53 447 104 2878 76 447 104 4104 20 324 1954 4886 8 447 1954 4766 88 447 1954 2827 74 192 2294 4148 42 447 2294 1573 49 409 2294 4413 80 13 2391 1954 75 447 2391 1108 87 753 2756 4154 15 447 2756 2520 91 33 2756 2135 93 408 2878 3339 85 447 2878 4528 76 683 3339 2294 58 447 3339 4840 79 699 3339 4820 36 967 4148 4298 63 447 4148 791 1 923 4148 2585 20 422 4154 2391 75 447 4154 2537 20 355 4154 277 45 56 4298 2756 73 447 4298 2377 88 435 4298 4252 51 701 105 1001 71 420 105 2579 88 601 833 2678 76 420 833 1794 18 418 833 3106 63 31 994 4763 79 420 994 4061 63 81 1001 4216 92 420 1001 4109 33 335 1083 4536 60 420 1083 2547 16 420 1083 2002 79 132 1083 3648 77 215 2547 833 40 420 2547 4180 84 654 2678 994 62 420 2678 3643 5 149 2678 1533 37 43 3729 1083 24 420 3729 2255 53 328 4216 3729 45 420 4216 4242 39 204 4216 4976 93 602 106 3301 71 758 106 2686 44 985 106 199 88 235 1169 3067 79 758 1169 3709 96 789 1428 4660 62 758 1428 4888 14 636 1428 1697 39 813 1444 4367 62 758 1444 2320 9 838 1444 3097 7 274 3067 3795 71 758 3067 4295 59 590 3067 4706 29 278 3301 1169 90 758 3301 1202 78 441 3795 1444 99 758 3795 4829 100 758 3795 4709 16 476 3795 3983 67 935 4114 1428 21 758 4114 1864 41 593 4367 4114 40 758 4367 805 3 511 107 2540 86 880 107 2668 22 456 895 1987 75 880 895 2896 6 989 983 2551 67 880 983 4718 3 495 1512 895 53 880 1512 181 60 240 1512 2698 69 965 1570 983 22 880 1570 1900 73 724 1667 4916 85 880 1667 3330 59 880 1667 3571 43 110 1667 2116 81 807 1987 2581 93 880 1987 780 39 157 1987 4944 20 768 2540 1512 39 880 2540 2122 92 42 2551 4790 13 880 2551 2309 52 484 2581 1667 33 880 2581 871 83 442 3330 1570 17 880 3330 3209 88 945 108 3607 73 846 108 1800 86 435 1025 1773 28 846 1025 2608 23 157 1025 2268 47 965 1322 4862 35 846 1322 4583 43 846 1322 3588 96 849 1322 4764 23 146 1773 3946 34 846 1773 322 31 415 3607 1025 41 846 3607 4179 67 886 3607 2565 70 93 3946 1322 37 846 3946 756 32 706 109 1749 60 694 109 3051 11 184 109 2236 22 649 568 2613 61 694 568 255 53 590 568 374 53 803 1239 4856 55 694 1239 3194 100 694 1239 1299 92 291 1239 3546 34 740 1251 4172 42 694 1251 475 16 175 1251 4904 48 902 1544 4583 7 694 1544 4730 36 197 1544 1211 89 358 1620 1251 16 694 1620 4713 50 172 1622 1544 38 694 1622 3232 60 996 1749 1620 19 694 1749 618 1 254 1749 1726 16 968 1789 1239 26 694 1789 4819 63 757 1789 3838 47 153 2613 1622 75 694 2613 4476 1 813 2613 2275 6 969 3194 568 30 694 3194 4056 7 257 3194 1569 78 566 4172 1789 77 694 4172 426 45 737 110 1161 35 804 110 117 69 728 110 1036 10 858 703 4759 4 804 703 3335 76 757 703 4688 45 675 1161 3797 82 804 1161 4874 8 804 1161 3205 24 221 2890 703 12 804 2890 4144 76 835 3371 2890 15 804 3371 227 30 310 3513 3371 92 804 3513 1640 37 248 3513 3683 85 358 3797 3513 40 804 3797 4718 94 93 3797 2972 5 234 111 1888 14 411 111 2668 25 341 111 3079 95 760 1640 2502 26 411 1640 4795 10 662 1640 1519 82 70 1888 3608 70 411 1888 4742 50 411 1888 2482 93 513 2502 4534 58 411 2502 630 5 648 3608 4217 41 411 3608 2222 5 320 3608 4762 45 245 4217 1640 94 411 4217 1433 9 561 112 1346 53 299 112 298 83 310 654 2031 96 299 654 2253 15 433 654 1739 64 472 1222 2494 23 299 1222 4628 63 299 1222 4556 13 349 1346 2432 53 299 1346 1128 67 194 1346 543 9 705 2031 1222 57 299 2031 4374 62 700 2031 2103 14 325 2368 4477 56 299 2368 666 5 721 2432 3220 1 299 2432 2012 6 975 2432 4552 52 555 2494 4945 65 299 2494 2905 57 47 2494 4580 98 129 3220 4038 69 299 3220 4983 2 445 4038 2368 2 299 4038 3190 30 593 4477 654 45 299 4477 2949 61 947 113 754 93 395 113 1813 53 198 113 3854 25 26 515 3335 20 395 515 2833 21 615 515 1637 100 326 754 515 65 395 754 3831 24 626 754 1669 69 783 1057 3491 20 395 1057 897 51 407 1057 2162 96 537 3165 4968 37 395 3165 4577 18 395 3165 1797 99 665 3165 1336 26 534 3335 4059 46 395 3335 3208 40 330 3491 3165 82 395 3491 1163 29 187 3491 1744 94 974 4059 1057 2 395 4059 568 41 729 4059 2388 4 479 114 2310 33 120 114 3611 70 478 114 918 81 456 1223 4788 2 120 1223 1286 98 875 1223 1580 57 657 1899 3692 57 120 1899 2726 72 224 2310 4336 56 120 2310 1041 12 89 2310 2204 29 864 3044 1223 68 120 3044 2074 40 767 3692 4530 40 120 3692 3044 34 120 3692 2483 42 171 4336 1899 41 120 4336 643 98 207 4336 305 2 253 115 1859 32 702 115 3428 21 22 115 2699 93 499 704 2349 72 702 704 2259 49 540 704 3383 66 245 1219 704 57 702 1219 3454 5 850 1373 3500 61 702 1373 342 23 149 1859 1373 11 702 1859 1685 90 424 2349 4525 10 702 2349 4947 19 702 2349 3722 98 304 2349 4928 12 629 2402 1219 80 702 2402 669 69 560 2402 1028 21 286 3500 4347 17 702 3500 1162 92 7 4347 2402 32 702 4347 2493 68 41 4347 3658 77 500 116 3472 94 269 116 3011 21 963 956 4498 9 269 956 4617 74 147 2026 3303 4 269 2026 2098 15 78 3148 956 66 269 3148 552 91 938 3148 3512 35 688 3303 4301 38 269 3303 89 74 854 3303 1872 73 21 3472 2026 47 269 3472 672 87 889 3472 1741 57 527 4138 4649 37 269 4138 4543 7 269 4138 3018 44 628 4301 3148 36 269 4301 2178 25 181 4498 4138 72 269 4498 1577 72 975 4498 4183 5 827 117 4128 78 703 117 264 69 513 1699 4150 42 703 1699 2277 79 706 1794 4883 24 703 1794 1832 64 882 2498 1794 83 703 2498 1294 35 266 2498 2121 2 18 2512 4928 1 703 2512 3284 16 703 2512 1223 69 416 3277 2498 69 703 3277 4795 31 48 3277 1040 27 137 3284 3277 51 703 3284 3449 30 413 4128 1699 23 703 4128 2104 54 85 4150 2512 40 703 4150 1941 18 464 118 1609 88 619 118 4697 41 760 118 826 4 502 535 675 96 619 535 1075 79 479 675 1038 72 619 675 487 18 743 675 4320 33 362 1038 3824 6 619 1038 4386 71 518 1609 1647 89 619 1609 2067 34 627 1647 3466 92 619 1647 4522 57 619 1647 343 9 366 2367 3885 56 619 2367 3625 15 305 3466 2367 79 619 3466 1300 79 325 3466 2507 83 743 3824 4726 97 619 3824 2840 81 405 3824 4816 83 130 3885 535 86 619 3885 201 66 832 3885 2978 18 655 119 4219 12 172 119 1544 35 516 119 3889 43 710 512 1168 68 172 512 298 96 29 946 512 2 172 946 2531 64 33 1168 3651 15 172 1168 4770 28 172 1168 1233 54 295 1168 3464 75 267 1425 1679 88 172 1425 1241 97 379 1425 3227 73 1 1679 4496 92 172 1679 2097 51 872 1679 3031 37 688 1988 4042 55 172 1988 2769 82 381 1988 2698 17 471 2225 946 34 172 2225 2395 76 464 3398 2225 13 172 3398 4601 5 172 3398 4878 46 79 3651 1988 32 172 3651 1517 64 128 3651 4114 16 105 4042 1425 12 172 4042 4466 41 713 4219 3398 35 172 4219 441 13 574 4219 1796 45 690 4496 4810 19 172 4496 3296 39 98 120 4365 19 689 120 1075 25 988 120 2207 27 184 820 2807 35 689 820 2419 39 338 820 4397 96 963 1372 1975 15 689 1372 3149 90 680 1372 3700 73 292 1975 4043 41 689 1975 388 63 788 1975 2044 35 563 2188 2731 16 689 2188 4506 13 885 2188 3230 79 908 2731 4631 68 689 2731 207 2 314 2731 783 58 661 2807 2188 89 689 2807 606 90 393 4043 820 28 689 4043 4608 91 689 4043 1801 66 76 4043 4369 56 871 4365 1372 62 689 4365 1360 20 639 121 2262 5 341 121 3747 54 648 121 18 31 874 558 4135 59 341 558 795 65 37 558 3855 84 43 2094 3281 49 341 2094 559 72 785 2262 3360 16 341 2262 2799 10 419 2262 865 84 478 3281 4706 33 341 3281 3742 35 885 3360 3722 85 341 3360 3222 62 226 3722 4270 33 341 3722 4870 8 965 3722 1500 1 519 4135 2094 52 341 4135 3919 17 875 4270 558 26 341 4270 4602 67 341 4270 2459 98 811 4270 3188 58 73 122 3280 22 699 122 2561 51 773 122 2655 53 102 1351 1687 27 699 1351 1176 37 228 1687 3313 97 699 1687 3242 71 883 1687 2122 64 887 2216 4211 52 699 2216 3888 43 420 2216 644 54 304 3280 1351 43 699 3280 1340 56 864 3313 2216 69 699 3313 4701 100 699 3313 2388 50 175 3313 3213 33 388 4211 4924 19 699 4211 22 24 331 123 2475 78 735 123 2266 9 704 123 1573 74 424 1188 3606 80 735 1188 3915 8 68 1188 4877 69 945 1472 4876 57 735 1472 1916 12 964 1472 2662 37 68 2475 1188 19 735 2475 4078 11 427 2475 3127 20 517 2607 4844 79 735 2607 3433 61 735 2607 199 60 411 3433 1472 27 735 3433 4405 93 585 3606 4255 63 735 3606 4748 78 304 4255 2607 50 735 4255 325 77 991 4255 892 97 292 124 3596 64 4 124 4368 60 49 124 3217 77 289 847 3066 78 4 847 4912 36 430 1298 4667 36 4 1298 3310 99 4 1298 893 31 975 1744 3076 75 4 1744 1192 85 648 1818 1298 14 4 1818 3783 53 137 1818 1529 18 872 2284 3659 68 4 2284 1297 74 108 2783 1818 93 4 2783 4998 94 4 2783 1969 21 18 2783 4629 28 689 3066 1744 77 4 3066 2926 37 772 3066 332 97 136 3076 3223 7 4 3076 4141 97 22 3223 2783 30 4 3223 891 98 884 3223 3195 37 514 3310 4926 61 4 3310 4954 61 422 3596 2284 23 4 3596 1874 63 206 3659 847 76 4 3659 3640 22 32 125 1993 54 764 125 4987 76 870 125 3091 95 293 664 2548 41 764 664 637 13 835 1112 2531 72 764 1112 3485 25 449 1181 4049 65 764 1181 478 37 631 1181 2186 2 806 1993 1181 45 764 1993 2201 77 504 1993 1525 41 197 2531 4271 22 764 2531 1503 76 945 2531 4226 96 172 2548 3751 64 764 2548 489 35 981 3523 4409 55 764 3523 3440 95 732 3523 4523 40 738 3751 4879 11 764 3751 359 57 565 4049 3523 1 764 4049 4660 26 764 4049 4212 67 644 4271 664 53 764 4271 4598 79 155 4271 1712 20 722 4409 1112 24 764 4409 4155 80 476 126 4165 53 735 126 584 21 507 1438 4500 61 735 1438 4798 13 967 3139 1438 3 735 3139 4992 68 735 3139 1051 24 573 3648 4994 40 735 3648 2837 22 721 3648 1622 71 835 4165 4248 54 735 4165 147 71 593 4248 3139 88 735 4248 500 79 485 4248 4940 29 680 4500 3648 90 735 4500 4866 2 159 127 2147 34 271 127 4410 84 207 127 3844 82 943 1675 4806 38 271 1675 3433 52 132 2147 2952 17 271 2147 39 85 421 2147 4785 98 371 2952 4306 4 271 2952 2164 80 69 2952 986 95 186 3476 1675 75 271 3476 2737 16 898 3619 3476 35 271 3619 2258 80 9 4306 3619 47 271 4306 4771 18 271 4306 3907 56 556 128 2837 21 564 128 1928 27 887 598 3924 20 564 598 4518 82 915 2061 3167 61 564 2061 2424 26 941 2061 325 38 880 2651 598 45 564 2651 1699 88 20 2651 389 30 734 2837 2061 47 564 2837 4020 89 956 3113 2651 59 564 3113 2404 47 12 3113 2178 70 722 3167 3113 76 564 3167 4789 33 564 3167 3946 93 328 3167 994 21 841 3924 4853 77 564 3924 4269 86 725 3924 4869 97 877 129 3812 7 28 129 1562 38 294 903 2198 15 28 903 2683 28 412 1149 4897 90 28 1149 4884 48 28 1149 912 80 34 1149 1450 74 565 1582 903 12 28 1582 3299 27 628 1582 2590 36 999 2198 1149 43 28 2198 1144 20 556 2198 4263 96 112 3631 3992 20 28 3631 4895 85 483 3631 3912 37 279 3812 4222 61 28 3812 2515 28 262 3846 1582 51 28 3846 4482 41 499 3846 4056 67 564 3992 3846 31 28 3992 2691 83 408 3992 856 31 57 4222 3631 89 28 4222 2351 8 138 130 1565 64 32 130 3887 50 636 1091 2754 63 32 1091 57 15 30 1091 1758 1 487 1565 2201 89 32 1565 4254 99 150 1565 2314 13 227 2201 4595 37 32 2201 4112 85 32 2201 4874 30 499 2754 3965 55 32 2754 2253 45 309 2754 1120 63 529 2892 3387 37 32 2892 217 44 605 3387 1091 89 32 3387 4465 53 173 3387 1803 81 714 3445 2892 78 32 3445 4357 34 283 3445 169 77 960 3965 4767 84 32 3965 4426 34 600 4112 3445 19 32 4112 4597 3 79 4112 1924 94 58 131 1799 2 822 131 4556 21 673 131 4570 63 595 678 1021 64 822 678 4990 75 194 1021 3945 76 822 1021 4277 96 422 1040 3726 37 822 1040 3321 40 266 1040 4071 2 790 1799 4446 4 822 1799 4923 42 822 1799 2206 8 973 3726 4892 8 822 3726 2050 49 383 3945 4269 89 822 3945 228 85 205 3945 4522 19 388 4269 1040 29 822 4269 144 35 525 4446 678 64 822 4446 2143 53 862 4446 817 34 367 132 2525 51 654 132 1895 70 719 132 1168 18 831 629 4361 35 654 629 2976 76 284 629 359 57 794 1408 1648 10 654 1408 4244 23 285 1408 1535 92 408 1439 1701 67 654 1439 1550 50 471 1648 4556 94 654 1648 3997 100 654 1648 2672 48 568 1701 2868 34 654 1701 3380 20 511 2199 629 45 654 2199 339 19 189 2199 1600 76 691 2525 1408 65 654 2525 2053 2 219 2857 2199 75 654 2857 4895 49 654 2857 4005 72 960 2857 2821 39 448 2868 2908 21 654 2868 2080 18 558 2868 290 7 821 2908 4802 59 654 2908 3721 85 178 3997 2857 34 654 3997 2669 47 849 3997 580 35 590 4361 1439 75 654 4361 1403 86 684 4361 756 95 458 133 2497 100 561 133 1777 51 131 1139 4617 9 561 1139 211 56 613 2497 2956 93 561 2497 2803 17 814 2780 1139 27 561 2780 3344 1 445 2780 2169 83 175 2956 3019 46 561 2956 4965 72 413 3019 4060 37 561 3019 1628 18 115 3019 2506 32 15 3776 4117 45 561 3776 2299 45 517 3776 4820 70 606 4060 3776 11 561 4060 4715 82 561 4060 492 61 872 4060 4546 83 438 4075 2780 38 561 4075 831 33 946 4075 2563 94 837 4117 4075 10 561 4117 135 77 863 4117 63 79 713 134 660 6 644 134 1816 4 489 660 2303 41 644 660 2500 35 92 1459 1953 13 644 1459 1188 39 46 1459 2692 64 582 1834 2436 66 644 1834 1833 7 796 1953 1834 86 644 1953 3624 64 265 1953 251 82 647 1968 2007 26 644 1968 2195 58 730 2007 1459 11 644 2007 1715 32 750 2303 1968 20 644 2303 2988 24 205 2303 4063 39 107 2436 4895 95 644 2436 4746 61 644 2436 4240 18 67 2436 4684 95 715 135 3666 1 621 135 2190 15 452 135 4593 48 459 747 1463 70 621 747 2066 47 365 1463 3377 23 621 1463 1927 76 623 1463 431 51 453 2063 4767 32 621 2063 227 14 166 2411 2755 89 621 2411 4075 45 652 2411 2417 85 132 2755 3627 15 621 2755 4905 53 621 2755 3395 27 291 3377 2411 74 621 3377 1376 29 315 3627 2063 48 621 3627 4233 99 647 3666 747 16 621 3666 436 18 794 136 2134 65 392 136 3839 32 727 136 2365 89 308 783 4022 2 392 783 4956 62 167 783 2609 35 390 866 783 99 392 866 3016 42 306 938 2785 63 392 938 31 95 769 1352 1797 85 392 1352 2098 46 692 1797 866 78 392 1797 303 7 64 1797 1049 70 940 2134 938 37 392 2134 1379 17 3 2785 1352 21 392 2785 2756 24 440 2785 2882 67 86 2796 4893 56 392 2796 1810 10 388 4022 4252 25 392 4022 4600 4 392 4022 4796 86 128 4022 4685 37 214 4252 2796 42 392 4252 291 73 616 137 900 47 964 137 4185 47 824 137 2051 99 811 900 2204 20 964 900 1697 28 221 900 2493 49 451 1405 4069 19 964 1405 4465 89 773 1805 1405 35 964 1805 1453 52 900 1805 2929 3 90 1944 4996 74 964 1944 3144 7 937 2204 1805 77 964 2204 4904 22 964 2204 1203 60 280 2535 1944 78 964 2535 4303 88 810 2535 3415 7 211 4069 2535 83 964 4069 3519 3 206 4069 1305 1 96 138 4081 79 108 138 1075 15 988 138 4232 57 654 1114 2078 67 108 1114 2360 9 357 2078 4399 47 108 2078 4613 61 763 2078 1780 74 484 2527 1114 15 108 2527 1486 70 772 2527 693 83 281 2930 2527 83 108 2930 218 80 134 2930 931 55 838 3018 2930 16 108 3018 446 17 363 3018 2856 20 847 3974 3018 27 108 3974 4316 3 697 4081 3974 97 108 4081 1614 13 874 4399 4821 55 108 4399 4573 54 108 4399 2033 93 197 4399 3687 83 37 139 4335 46 394 139 792 20 410 139 4082 4 965 659 4860 61 394 659 2461 60 72 1525 1743 75 394 1525 138 27 864 1525 2743 4 163 1743 4158 77 394 1743 4046 35 812 1743 4592 97 977 1746 1525 71 394 1746 3023 28 569 2459 3092 2 394 2459 3152 89 788 2459 3837 24 167 3092 659 51 394 3092 1493 35 546 3238 4280 97 394 3238 3582 37 244 4158 2459 38 394 4158 4702 59 394 4158 1764 43 48 4280 1746 7 394 4280 3187 55 503 4280 544 14 130 4335 3238 51 394 4335 3847 2 516 4335 2380 67 335 140 2591 16 1149 140 4714 44 325 140 3703 74 9 982 1996 85 1149 982 3684 73 558 982 4080 20 64 1996 3034 29 1149 1996 4613 86 1149 1996 906 60 247 1996 4963 49 76 2591 4484 32 1149 2591 3792 93 524 3034 4976 98 1149 3034 3777 45 910 4341 982 91 1149 4341 1294 11 543 4484 4341 75 1149 4484 1347 7 996 4484 1123 55 290 141 3033 89 284 141 1191 92 26 552 3545 95 284 552 437 10 936 552 2653 60 705 1412 1824 2 284 1412 3981 9 278 1412 924 71 109 1824 4629 79 284 1824 4811 63 284 1824 4684 36 209 1824 4078 90 946 2467 552 67 284 2467 128 96 789 2467 673 89 398 2834 2467 85 284 2834 375 21 955 3033 2834 93 284 3033 4597 82 408 3033 4499 26 628 3545 4214 52 284 3545 3725 87 900 4214 1412 92 284 4214 2377 25 57 4214 1319 30 573 142 2604 62 433 142 4060 64 690 142 2123 90 783 566 4791 17 433 566 4567 34 737 566 4291 76 481 789 566 65 433 789 2826 61 487 789 6 47 257 1166 3096 43 433 1166 2782 96 645 1166 2808 62 680 2003 4841 7 433 2003 3914 33 433 2003 3193 33 376 2374 1166 42 433 2374 976 36 483 2374 571 9 338 2604 2003 14 433 2604 2912 39 98 3096 789 24 433 3096 682 8 402 3402 4240 20 433 3402 2935 26 43 3554 2374 21 433 3554 1113 97 364 3914 3402 71 433 3914 669 65 731 4240 3554 96 433 4240 1376 6 94 4240 900 66 397 143 844 34 346 143 91 45 771 143 2657 33 456 502 3245 92 346 502 2215 62 138 844 1889 19 346 844 2679 84 535 884 502 11 346 884 1377 23 30 884 4443 14 37 1889 3057 11 346 1889 1097 53 874 2645 4762 69 346 2645 1973 50 840 2645 2630 55 445 3057 4296 52 346 3057 4692 97 128 3245 4764 89 346 3245 4435 3 346 3245 510 99 5 3245 1963 55 928 4296 884 17 346 4296 896 53 294 4435 2645 1 346 4435 4081 62 73 144 2105 2 168 144 525 100 589 144 605 47 287 522 4872 12 168 522 1453 20 233 784 1915 23 168 784 4759 41 136 784 2463 92 518 1915 2423 5 168 1915 464 44 425 1915 2404 17 455 2105 4374 62 168 2105 3321 7 391 2105 1546 49 777 2217 3794 57 168 2217 966 3 621 2217 3056 60 880 2423 522 8 168 2423 4677 87 168 2423 951 24 636 2423 2368 69 610 2972 2217 51 168 2972 3811 50 855 3794 784 70 168 3794 1949 3 704 4374 2972 89 168 4374 2433 18 805 145 4444 66 982 145 3341 69 554 145 897 80 164 583 1174 81 982 583 1128 57 810 770 583 46 982 770 850 83 278 1174 4715 68 982 1174 3271 73 66 1174 2077 44 861 3062 4311 57 982 3062 4993 79 982 3062 4247 88 111 4311 770 82 982 4311 325 76 618 4444 3062 42 982 4444 4434 1 11 146 3260 67 790 146 1511 58 874 1587 3753 25 790 1587 2548 47 317 2074 4903 41 790 2074 4053 70 887 2074 719 100 432 3260 1587 38 790 3260 588 85 928 3260 4761 4 209 3753 4072 62 790 3753 369 50 245 3981 2074 25 790 3981 1852 73 578 3981 1754 28 257 4072 4179 83 790 4072 4601 64 790 4072 1505 2 676 4072 1326 71 403 4179 3981 81 790 4179 4802 5 309 4179 1935 32 694 147 3071 36 469 147 3942 11 241 147 2741 21 509 526 3369 7 469 526 3362 63 64 1260 3942 63 469 1260 4089 2 725 2914 4197 38 469 2914 1871 34 876 3071 2914 61 469 3071 1008 48 767 3258 3968 14 469 3258 4860 27 469 3258 355 98 132 3258 425 73 390 3369 4396 89 469 3369 2158 21 860 3942 526 94 469 3942 2620 51 865 3968 4576 42 469 3968 3473 84 917 4197 1260 54 469 4197 3690 95 623 4396 3258 91 469 4396 4110 50 387 148 865 36 287 148 3154 45 303 865 2948 96 287 865 4598 28 287 865 4387 3 739 865 4447 72 810 1670 2445 91 287 1670 1654 91 1000 1670 3422 16 340 2176 1670 44 287 2176 4864 83 580 2445 2509 10 287 2445 2282 72 329 2509 4931 13 287 2509 243 15 855 2509 3203 97 786 2948 2176 36 287 2948 3331 60 459 149 4364 83 427 149 2765 49 322 762 1727 73 427 762 4078 69 255 888 2111 64 427 888 311 57 42 1421 4118 50 427 1421 4582 14 761 1421 3259 54 416 1727 4101 44 427 1727 4283 9 601 1727 3345 19 193 2111 1421 77 427 2111 1061 64 339 2111 4690 28 27 2471 762 51 427 2471 4605 16 427 2471 1117 95 467 4101 4760 43 427 4101 3619 58 243 4118 2471 78 427 4118 4842 45 31 4364 888 57 427 4364 4082 45 883 150 3184 41 763 150 2928 66 501 589 777 67 763 589 3922 43 445 589 1237 31 632 777 1416 81 763 777 932 41 145 777 1917 53 950 1416 3430 95 763 1416 4977 28 763 1416 4483 28 23 3184 4202 31 763 3184 4900 19 902 3184 2263 19 95 3430 4647 55 763 3430 2094 99 224 3430 2603 31 332 4202 589 87 763 4202 3459 23 459 4202 1031 4 278 151 3389 79 407 151 3457 12 340 612 2040 64 407 612 3191 65 2 612 485 61 73 804 3662 43 407 804 4291 43 23 804 4394 62 35 1227 3497 75 407 1227 4827 76 816 2040 804 26 407 2040 1184 81 140 2805 1227 59 407 2805 2649 69 303 2805 756 44 685 3389 612 97 407 3389 3208 49 672 3497 4692 58 407 3497 4359 85 551 3662 3890 82 407 3662 4883 79 407 3662 2077 24 86 3662 4330 5 881 3890 2805 5 407 3890 3265 15 280 3890 3305 52 1 152 3586 62 323 152 3457 90 763 1552 2896 23 323 1552 3728 91 890 2029 3701 44 323 2029 3505 10 416 2873 2029 42 323 2873 3334 68 254 2896 3283 89 323 2896 1497 8 225 2896 76 87 68 3283 4359 94 323 3283 4637 11 323 3283 2985 98 761 3586 2873 34 323 3586 4702 74 413 3701 3825 27 323 3701 4964 82 295 3825 1552 96 323 3825 3781 23 724 3825 1772 61 276 4359 4829 64 323 4359 4296 58 681 153 4184 51 776 153 529 42 847 1076 4537 96 776 1076 3570 12 82 1076 4410 55 768 1931 1076 20 776 1931 1393 85 784 3796 4676 43 776 3796 1931 50 776 3796 448 52 367 3796 3715 62 314 4184 4393 33 776 4184 513 95 767 4393 3796 87 776 4393 1252 26 977 154 3599 19 1109 154 564 16 6 154 1947 60 285 810 1244 33 1109 810 4957 42 61 810 4467 52 730 1177 3232 78 1109 1177 671 43 469 1177 554 39 921 1244 4893 68 1109 1244 1856 40 362 1244 2133 83 922 2259 810 25 1109 2259 3132 2 40 2259 4765 8 586 3232 2259 97 1109 3232 4640 1 1109 3232 4985 95 927 3232 2464 26 81 3599 1177 63 1109 3599 2220 6 58 3599 2092 81 300 155 501 49 896 155 1905 92 377 501 1841 6 896 501 4621 67 896 501 1402 100 148 501 1863 64 988 827 2687 41 896 827 213 72 810 827 4248 67 647 1841 827 96 896 1841 1484 56 166 2687 3399 66 896 2687 898 28 566 3399 4726 78 896 3399 3934 70 786 3399 4651 3 600 156 1455 2 288 156 428 42 902 525 4583 53 288 525 2203 95 57 525 197 87 456 975 3844 62 288 975 1842 44 554 1118 525 40 288 1118 592 1 672 1118 1612 56 493 1345 3892 11 288 1345 2758 61 984 1345 1963 63 332 1455 4953 45 288 1455 4033 23 288 1455 3167 22 555 1455 3639 10 512 3844 1345 71 288 3844 4147 37 53 3892 1118 47 288 3892 680 56 539 3892 4073 4 591 4033 4354 3 288 4033 663 31 189 4033 201 72 973 4354 975 85 288 4354 2219 39 271 4354 1730 18 182 157 4237 35 680 157 2116 99 342 157 2488 78 412 1760 3744 85 680 1760 2328 64 291 1760 4646 100 50 2128 4417 35 680 2128 379 67 576 2312 4879 50 680 2312 2394 98 69 2728 3063 18 680 2728 708 83 589 2817 2728 23 680 2817 3789 23 145 2817 2960 65 649 3063 1760 1 680 3063 3149 73 591 3063 162 71 714 3744 2128 11 680 3744 3051 73 409 3947 4638 36 680 3947 2312 6 680 3947 2854 97 411 3947 4619 87 582 4237 2817 40 680 4237 2534 9 473 4417 3947 67 680 4417 3364 11 605 158 2428 84 1632 158 4403 51 450 910 3921 11 1632 910 4614 99 524 910 3175 32 220 939 2655 28 1632 939 4145 69 958 939 1357 82 594 1940 2670 99 1632 1940 4710 41 1632 1940 1307 69 260 2065 4660 37 1632 2065 4448 60 150 2428 1940 49 1632 2428 2600 90 127 2655 910 25 1632 2655 2257 84 622 2655 1462 37 407 2670 939 74 1632 2670 1810 65 333 3921 2065 73 1632 3921 1173 28 704 159 3672 75 385 159 3077 72 203 159 1473 26 511 579 3293 11 385 579 1752 78 135 579 4647 39 952 790 4750 13 385 790 681 90 967 1071 1160 41 385 1071 3135 37 535 1160 3366 67 385 1160 3628 34 957 1385 2751 21 385 1385 624 35 485 2751 3677 61 385 2751 4012 24 626 3293 1385 51 385 3293 2496 41 24 3293 467 84 484 3366 579 100 385 3366 2747 92 148 3672 1071 71 385 3672 4976 30 385 3672 3284 50 123 3672 2428 20 208 3677 790 35 385 3677 1577 26 867 160 3589 62 364 160 619 83 667 160 1778 89 801 881 1125 99 364 881 3647 89 342 1039 1856 29 364 1039 708 53 434 1039 3704 83 974 1125 2574 51 364 1125 4960 96 364 1125 4614 22 597 1125 910 1 90 1856 2982 95 364 1856 1195 85 106 1856 2441 40 135 1862 1039 29 364 1862 3931 32 549 2574 1862 86 364 2574 4154 32 936 2574 2115 6 169 2898 881 67 364 2898 815 39 336 2898 2146 87 414 2982 4581 15 364 2982 2350 22 211 2982 788 96 283 3589 2898 73 364 3589 3483 97 178 161 3887 58 1053 161 4993 55 503 673 1527 88 1053 673 837 25 554 822 4143 5 1053 822 4982 20 43 1527 2777 81 1053 1527 501 42 388 2366 4920 51 1053 2366 4828 27 1053 2366 1295 90 617 2777 4020 4 1053 2777 3193 45 97 2777 3024 6 508 2994 673 90 1053 2994 607 73 116 3887 2994 13 1053 3887 4893 19 281 3887 1589 97 244 4020 822 96 1053 4020 4904 91 360 4020 3773 61 861 4143 2366 94 1053 4143 469 86 879 162 2564 15 382 162 2026 70 338 1024 2750 38 382 1024 4735 14 382 1024 3907 84 7 1024 4638 13 426 1451 1024 58 382 1451 3725 99 754 2564 2918 11 382 2564 4072 81 293 2750 4649 99 382 2750 1607 46 645 2750 1888 9 686 2918 1451 34 382 2918 1403 93 762 163 2127 94 582 163 3987 45 308 163 391 57 704 1312 4005 63 582 1312 2082 39 41 1762 3417 1 582 1762 4672 81 582 1762 560 40 224 2127 3919 71 582 2127 4131 100 369 3417 1312 69 582 3417 3561 91 626 3919 1762 13 582 3919 1079 79 543 3919 2970 97 574 4005 4697 75 582 4005 1670 79 582 4005 3172 19 731 164 702 70 378 164 1795 70 625 692 4797 11 378 692 4695 16 378 692 2750 68 879 702 3553 71 378 702 3853 98 104 702 4604 74 207 3098 3257 55 378 3098 2757 17 127 3098 1537 72 828 3257 3682 9 378 3257 3627 56 603 3257 1553 62 450 3304 3098 92 378 3304 4956 48 117 3304 4657 26 198 3553 3304 83 378 3553 4400 2 401 3553 3770 26 400 3682 692 29 378 3682 784 12 192 165 961 49 217 165 1380 48 692 961 2784 74 217 961 2345 2 867 961 1756 55 253 1320 2420 51 217 1320 2368 12 648 1320 1715 55 632 1381 2306 90 217 1381 1271 2 747 1717 4922 25 217 1717 4773 60 973 1717 3259 86 878 2306 4264 85 217 2306 4614 52 294 2420 4667 3 217 2420 2771 20 217 2420 4577 75 330 2420 4412 35 896 2771 4208 46 217 2771 2495 82 293 2784 2882 6 217 2784 4701 52 235 2882 1320 73 217 2882 2780 6 457 4208 1381 14 217 4208 1141 15 811 4264 1717 9 217 4264 1573 100 459 166 3886 28 412 166 3909 77 439 1253 1997 25 412 1253 362 97 14 1997 4797 83 412 1997 1817 44 780 2009 1253 59 412 2009 3142 30 256 2309 2009 18 412 2309 815 82 985 2309 2355 62 464 3475 2309 55 412 3475 4606 26 412 3475 3507 92 66 3475 4006 10 312 3886 3475 43 412 3886 1791 89 136 3886 1869 78 179 167 4260 31 378 167 1040 11 157 167 2308 68 828 607 932 81 378 607 2639 83 513 932 3895 67 378 932 591 33 305 932 3264 33 537 2550 3198 7 378 2550 3578 54 538 2550 1683 72 993 2663 4748 25 378 2663 4895 47 378 2663 478 78 838 3198 2663 91 378 3198 89 48 122 3198 3062 27 370 3823 2550 42 378 3823 3836 83 347 3895 3823 20 378 3895 893 25 549 4260 607 22 378 4260 1714 70 39 4260 1038 19 777 168 2513 56 371 168 1425 90 794 168 253 18 388 562 3562 51 371 562 2570 75 189 562 376 52 318 616 4934 77 371 616 3055 46 371 616 294 41 299 616 1626 41 692 2513 3668 6 371 2513 423 2 621 2513 4207 23 345 2848 3580 54 371 2848 2368 47 885 2848 3362 64 921 3055 3099 76 371 3055 990 36 554 3055 4638 4 339 3099 562 27 371 3099 1711 69 233 3099 387 10 279 3562 3814 9 371 3562 2971 93 527 3562 2047 29 976 3580 3703 46 371 3580 413 74 246 3580 3272 75 443 3668 2848 77 371 3668 2764 67 886 3703 616 53 371 3703 2004 12 665 3814 4585 27 371 3814 1013 51 42 3814 4249 77 224 169 2409 28 420 169 4148 6 931 169 2556 93 512 1100 2069 99 420 1100 4926 71 423 1698 4633 16 420 1698 4590 48 769 1811 2584 75 420 1811 4612 62 356 1811 4810 92 113 2069 4757 83 420 2069 1811 8 420 2069 3603 72 504 2069 4393 69 267 2324 3436 38 420 2324 2885 81 937 2409 2324 45 420 2409 4553 92 513 2409 1120 5 497 2584 1698 49 420 2584 1322 24 785 2584 4061 86 532 3436 1100 36 420 3436 4956 76 114 170 1801 13 1017 170 3196 73 82 170 1505 86 258 665 779 76 1017 665 4306 53 648 779 4405 85 1017 779 4265 4 90 779 2909 89 796 992 665 22 1017 992 1103 16 27 992 1382 55 79 1361 2741 67 1017 1361 4816 74 639 1361 895 67 909 1801 4633 63 1017 1801 3782 47 1017 1801 3096 59 13 1801 2934 27 518 2741 4091 56 1017 2741 3436 3 95 3782 1361 87 1017 3782 4164 67 790 4091 4368 64 1017 4091 1943 59 981 4368 992 3 1017 4368 16 7 708 4368 2046 88 736 4405 4745 62 1017 4405 1958 31 740 4405 3636 2 15 171 2395 72 719 171 4135 8 921 171 4728 41 685 1539 1725 47 719 1539 2128 31 550 1725 2669 33 719 1725 2902 75 316 1725 2209 40 381 2395 2880 85 719 2395 340 80 728 2395 3890 98 842 2669 4856 36 719 2669 3716 99 1000 2880 3079 60 719 2880 1840 91 622 2880 2826 26 440 3079 1539 22 719 3079 4937 3 719 3079 1322 15 801 3079 3186 61 756 172 3420 64 24 172 3232 71 11 734 769 45 24 734 796 50 10 769 4587 57 24 769 4842 25 24 769 1449 39 378 769 2599 42 825 1237 2766 50 24 1237 4270 35 29 1237 2300 81 180 2766 734 77 24 2766 2336 66 702 2992 1237 13 24 2992 1015 80 141 2992 1181 35 165 3420 2992 42 24 3420 4916 53 307 173 3146 3 476 173 1662 76 798 173 1909 66 846 874 2664 39 476 874 310 3 27 1162 874 70 476 1162 3372 78 297 1162 4154 48 309 2576 3135 45 476 2576 1697 49 44 2664 4542 65 476 2664 3597 41 984 3135 4625 37 476 3135 1162 68 476 3135 4061 45 687 3135 448 33 998 3146 4161 44 476 3146 4004 100 869 4161 2576 35 476 4161 3684 68 389 174 3749 37 692 174 648 81 995 1115 4291 58 692 1115 651 93 580 1115 1010 15 590 2362 4390 52 692 2362 4509 24 692 2362 2951 80 384 2362 2630 59 259 3664 4880 68 692 3664 736 32 51 3664 1941 78 792 3749 1115 52 692 3749 3625 28 263 3749 4257 61 52 4291 2362 8 692 4291 4315 98 792 4390 3664 26 692 4390 96 81 366 175 1397 41 334 175 3617 58 252 1397 2585 38 334 1397 3031 92 532 1397 3842 88 45 2281 3473 11 334 2281 1676 8 392 2281 1692 65 60 2585 3986 41 334 2585 4850 68 334 2585 3478 35 115 2744 2281 67 334 2744 1271 47 504 2744 3945 39 205 2937 4604 72 334 2937 3410 77 176 3473 2937 99 334 3473 4767 98 951 3473 2713 37 463 3986 2744 4 334 3986 1060 15 589 176 763 44 426 176 1162 69 174 176 1775 36 536 763 2931 68 426 763 4340 93 254 763 913 66 791 2192 4963 13 426 2192 2310 56 623 2205 2967 4 426 2205 2795 77 389 2775 3542 24 426 2775 1707 98 178 2775 207 58 421 2931 2775 25 426 2931 4955 96 391 2931 658 91 440 2967 2192 97 426 2967 4342 41 273 3542 2205 62 426 3542 4929 61 426 3542 3761 70 771 3542 1640 48 943 177 1645 85 26 177 603 88 814 892 2625 94 26 892 2977 100 844 892 3419 60 435 1645 892 38 26 1645 4589 43 26 1645 3455 97 264 1645 1893 28 360 1956 4360 85 26 1956 1988 64 752 2625 4279 71 26 2625 4149 95 262 2625 470 35 946 2954 4671 13 26 2954 657 45 521 2954 4790 96 560 4279 1956 14 26 4279 4354 37 189 4279 3564 92 148 4360 2954 53 26 4360 2037 22 125 178 3808 67 71 178 1550 50 992 1447 4549 5 71 1447 4703 97 71 1447 4775 44 551 1447 4506 22 303 2472 2851 59 71 2472 232 72 775 2851 4385 14 71 2851 4944 77 94 3808 2472 93 71 3808 4641 79 893 3808 867 2 689 4385 1447 28 71 4385 4824 5 413 4385 1984 72 491 179 3687 6 45 179 3045 60 241 179 1887 87 890 1386 3401 50 45 1386 4981 29 45 1386 4034 98 58 1545 2709 51 45 1545 2715 38 360 1545 3227 7 926 2709 3875 72 45 2709 1212 80 603 2709 1553 97 486 3401 1545 41 45 3401 93 2 494 3401 1233 82 261 3687 1386 78 45 3687 1228 63 777 3875 4976 64 45 3875 4608 52 131 180 4366 16 97 180 778 79 317 978 3213 64 97 978 2071 33 507 978 2680 86 161 1146 4173 12 97 1146 862 40 616 1146 1724 75 36 1750 978 94 97 1750 1427 21 100 1750 3950 65 44 2361 1750 61 97 2361 4611 96 97 2361 3365 71 949 2361 4782 88 499 3201 4916 54 97 3201 4342 15 740 3201 2133 2 318 3213 1146 50 97 3213 1701 13 195 3213 1376 82 531 4173 3201 31 97 4173 4514 60 684 4173 4200 8 225 4366 2361 49 97 4366 416 74 668 4366 4407 50 424 181 1624 100 619 181 4493 3 842 181 3159 43 138 698 1400 49 619 698 37 66 273 698 906 44 583 1400 4791 11 619 1400 1392 29 229 1624 4082 12 619 1624 3987 60 688 2071 4645 83 619 2071 3756 49 619 2071 2811 63 767 2071 3371 58 625 3756 4474 41 619 3756 4684 30 985 3756 3183 14 369 4082 4178 99 619 4082 330 67 349 4178 2071 32 619 4178 4712 98 133 4474 698 39 619 4474 341 66 475 182 1137 74 803 182 1051 33 749 182 4160 10 103 1137 2881 13 803 1137 3651 81 734 1137 4082 58 906 1506 3819 13 803 1506 2014 66 851 1506 2967 18 223 2501 1506 40 803 2501 2538 6 920 2501 4541 82 424 2721 3717 61 803 2721 4305 32 461 2721 402 22 313 2738 4980 95 803 2738 4799 43 396 2738 3115 97 613 2881 2501 87 803 2881 1100 85 702 2973 2721 54 803 2973 4851 58 187 3623 2973 17 803 3623 4549 23 803 3623 3861 95 942 3717 2738 18 803 3717 3553 44 900 3819 3623 90 803 3819 2305 7 798 3819 1700 25 912 183 942 40 236 183 2355 60 227 879 3988 5 236 879 4347 39 953 942 2030 86 236 942 3270 54 729 1204 879 16 236 1204 4906 83 360 1204 2925 4 844 2030 1204 2 236 2030 4694 59 577 2288 2619 61 236 2288 4741 11 236 2288 3085 22 44 2288 1113 82 492 2619 4810 56 236 2619 828 48 925 3988 2288 88 236 3988 778 84 203 3988 633 5 478 184 2639 5 293 184 4235 15 317 184 1643 12 610 1639 4768 22 293 1639 1245 44 635 1639 4439 45 89 1980 3643 88 293 1980 379 88 764 2639 3669 49 293 2639 441 82 528 2639 329 69 484 3643 4386 24 293 3643 1004 96 488 3669 3931 8 293 3669 4260 90 771 3669 4080 30 625 3931 4707 72 293 3931 1980 83 293 3931 1462 40 897 3931 81 58 917 4386 1639 23 293 4386 3052 24 91 185 3085 69 571 185 822 8 423 1540 2320 20 571 1540 3318 64 728 1540 4718 48 284 1636 4608 57 571 1636 4604 13 571 1636 1188 62 169 1742 2804 33 571 1742 925 24 903 1742 1960 63 372 2159 1742 43 571 2159 3213 95 860 2320 1636 15 571 2320 3067 12 549 2390 1540 54 571 2390 3219 86 61 2390 4089 46 602 2804 2390 97 571 2804 1861 64 826 3085 2159 5 571 3085 4476 21 735 186 2448 36 497 186 3572 68 738 1129 1277 28 497 1129 4745 99 118 1277 4880 72 497 1277 2929 95 497 1277 4659 16 253 1633 2184 48 497 1633 4819 10 743 1633 2276 56 763 2184 3649 52 497 2184 823 92 576 2448 1633 65 497 2448 2484 44 522 2448 3462 37 267 2929 3152 63 497 2929 1203 8 387 2929 963 62 984 3152 4578 20 497 3152 888 77 202 3152 2650 11 929 3649 1129 94 497 3649 1169 29 943 3649 3644 97 457 187 2599 68 390 187 446 8 782 187 2558 91 240 935 2346 50 390 935 113 26 881 2285 4328 26 390 2285 2952 74 654 2285 1792 77 301 2346 3758 33 390 2346 4961 95 276 2346 2275 83 478 2599 2285 46 390 2599 160 89 775 3153 4928 3 390 3153 250 93 468 3307 935 61 390 3307 4339 80 931 3307 1942 76 125 3758 3153 30 390 3758 4988 27 390 3758 3486 100 197 3758 4202 83 854 4328 3307 7 390 4328 1555 72 548 4328 44 70 385 188 3559 18 451 188 597 93 255 949 1080 10 451 949 1877 46 211 949 2423 39 250 1080 1739 27 451 1080 49 20 278 1080 780 15 892 1498 3501 100 451 1498 4541 57 451 1498 266 71 16 1498 1136 10 888 1739 1498 91 451 1739 1385 71 747 2017 4798 6 451 2017 3450 53 482 2017 4571 2 920 3490 949 58 451 3490 3951 37 903 3490 3240 88 764 3501 2017 69 451 3501 2400 29 977 3501 3957 52 126 3559 3490 85 451 3559 4500 49 594 189 708 95 545 189 4237 79 784 708 3906 24 545 708 4508 2 545 708 4311 3 854 708 3313 24 733 1974 2123 19 545 1974 3500 21 234 1974 2761 77 854 2123 2446 20 545 2123 4057 13 619 2123 4271 15 199 2426 3966 94 545 2426 3631 25 997 2426 1702 61 890 2446 4822 97 545 2446 3377 1 173 3906 2426 1 545 3906 2461 58 905 3966 1974 15 545 3966 2280 42 282 190 4116 8 524 190 2149 6 569 799 1919 74 524 799 2581 21 131 1591 799 93 524 1591 1192 36 263 1919 3515 76 524 1919 2717 40 511 1919 4008 98 793 2271 4759 88 524 2271 4846 96 524 2271 2784 24 253 2271 3431 80 561 3515 3913 84 524 3515 556 16 860 3913 2271 44 524 3913 4350 100 664 3913 2735 41 586 4116 4404 56 524 4116 205 67 943 4404 1591 70 524 4404 3045 4 607 191 1718 80 27 191 4569 63 388 191 1735 40 299 529 3508 97 27 529 1186 69 4 550 2493 79 27 550 945 35 87 1718 550 52 27 1718 4815 45 116 1740 4949 81 27 1740 203 28 97 1740 3514 74 816 2493 529 1 27 2493 4954 12 27 2493 1971 95 673 3508 1740 6 27 3508 2246 50 977 192 3267 42 402 192 3082 40 585 192 631 37 485 625 4540 94 402 625 4929 49 968 1353 1715 96 402 1353 1289 85 137 1695 4402 22 402 1695 3701 55 769 1715 4892 37 402 1715 2136 5 402 1715 4391 34 497 1715 4013 93 67 2136 1695 52 402 2136 3599 79 278 2136 243 32 885 2907 625 65 402 2907 2107 37 151 2907 3797 60 222 3267 3694 68 402 3267 1568 92 650 3694 1353 54 402 3694 4959 56 311 3694 4443 27 74 4402 2907 55 402 4402 250 50 394 193 730 97 468 193 4684 70 965 599 3532 10 468 599 3962 5 10 730 2570 63 468 730 4633 10 201 730 4033 38 991 1132 1930 58 468 1132 3687 24 525 1209 1132 70 468 1209 3351 57 278 1930 2450 7 468 1930 2914 38 791 1930 3853 41 420 2450 4954 70 468 2450 2052 5 518 2450 3252 92 845 2570 599 28 468 2570 4183 52 25 3532 1209 8 468 3532 4845 37 468 3532 1343 31 636 194 3540 60 721 194 3544 97 123 194 3036 63 566 570 2612 56 721 570 4479 98 16 570 3850 51 843 921 4833 11 721 921 1927 17 721 921 1565 50 441 1246 570 64 721 1246 2014 23 115 1246 1890 19 365 1682 2104 73 721 1682 2920 64 853 1927 4463 63 721 1927 4364 66 578 2104 1246 94 721 2104 4501 95 780 2104 4783 79 849 2612 4745 5 721 2612 167 22 568 2768 921 26 721 2768 450 38 135 2768 4139 40 253 3540 2768 48 721 3540 1320 2 63 3540 3259 5 568 4024 1682 87 721 4024 960 2 541 4463 4024 29 721 4463 1106 23 799 195 2711 36 497 195 3230 87 843 794 2545 25 497 794 295 9 192 1716 3597 84 497 1716 3373 44 812 2218 1716 63 497 2218 4578 8 993 2545 4227 2 497 2545 1233 64 931 2545 959 3 459 2587 2218 77 497 2587 4256 29 335 2711 794 60 497 2711 3525 85 764 3320 4687 33 497 3320 3378 18 497 3320 3381 58 423 3320 1556 10 109 3378 4987 36 497 3378 3623 94 702 3378 4903 2 613 3597 3320 26 497 3597 689 70 946 3597 2743 60 715 4227 2587 47 497 4227 4508 20 429 196 2108 41 584 196 340 61 440 196 179 7 603 1414 2919 93 584 1414 4394 50 863 1477 1414 1 584 1477 1630 32 81 1505 4984 37 584 1505 4694 97 584 1505 1176 37 268 1596 1477 96 584 1596 1394 76 267 1596 1046 55 775 2108 1596 18 584 2108 2935 22 71 2108 1895 40 39 2919 1505 10 584 2919 4841 45 932 2919 1614 55 327 197 3865 30 630 197 2580 77 448 719 4078 2 630 719 4869 43 630 719 3557 77 839 846 3600 45 630 846 4965 47 829 1435 2272 22 630 1435 3803 51 333 1803 1435 38 630 1803 2101 56 632 1803 565 69 632 2272 719 19 630 2272 3553 62 225 3600 4939 80 630 3600 3189 53 642 3865 1803 85 630 3865 2297 5 556 4078 846 11 630 4078 3392 55 136 4078 4389 36 238 198 1775 78 755 198 122 43 937 198 968 64 773 1330 3477 53 755 1330 2669 76 518 1330 4415 93 652 1775 4475 18 755 1775 3869 78 937 2662 3414 14 755 2662 1188 86 17 3414 1330 30 755 3414 2945 21 403 3414 1211 24 259 3477 4309 44 755 3477 4590 19 755 3477 80 25 235 3477 3222 74 669 3609 3630 62 755 3609 523 62 320 3609 2263 58 864 3630 2662 99 755 3630 3389 47 676 4309 4792 93 755 4309 1649 93 583 4309 270 31 386 4475 3609 49 755 4475 47 13 292 199 1295 52 308 199 2003 14 893 199 4091 44 551 1295 3424 9 308 1295 3754 89 668 1722 3357 44 308 1722 1572 3 931 2691 1722 73 308 2691 155 60 613 3357 4535 9 308 3357 3410 29 595 3407 2691 26 308 3407 1558 18 647 3407 463 69 651 3424 3407 92 308 3424 4957 84 308 3424 1850 65 27 3424 3258 43 272 200 4337 27 853 200 3348 82 747 943 4259 58 853 943 1484 98 695 1433 4066 19 853 1433 2212 20 522 2708 3291 3 853 2708 3517 82 868 2708 4620 11 917 3291 4176 45 853 3291 2920 3 486 3300 943 97 853 3300 172 4 899 3300 3999 85 450 3770 1433 57 853 3770 1800 84 918 3770 4044 94 510 4066 4863 96 853 4066 2745 93 593 4176 3770 30 853 4176 2159 38 412 4176 2898 47 669 4259 2708 19 853 4259 4742 16 853 4259 4599 22 676 4337 3300 25 853 4337 2383 51 80 201 3928 96 1693 201 4850 64 110 201 811 33 652 744 2455 38 1693 744 4007 36 753 1006 4516 83 1693 1006 4946 98 1693 1006 716 21 22 1893 4415 21 1693 1893 1070 45 729 2455 1893 15 1693 2455 4568 78 516 2455 4546 53 848 3928 744 47 1693 3928 1142 100 711 3928 944 29 401 4415 1006 88 1693 4415 1909 39 790 202 1955 66 1352 202 3407 45 665 202 2568 31 708 731 3421 26 1352 731 3 66 673 1764 731 97 1352 1764 4988 63 1352 1764 24 97 799 1955 2872 78 1352 1955 2330 50 263 2872 1764 60 1352 2872 4006 81 328 3050 4625 23 1352 3050 3838 73 932 3050 4545 56 794 3421 3951 19 1352 3421 4602 12 84 3951 3050 71 1352 3951 3775 76 125 203 3736 26 224 203 4225 99 405 203 4158 27 165 1806 2963 53 224 1806 1585 31 575 1806 4029 9 571 2800 3845 41 224 2800 854 28 904 2800 1961 2 341 2963 4839 91 224 2963 2800 9 224 2963 4641 81 4 3736 1806 99 224 3736 2942 50 728 3736 3037 50 374 3845 4755 26 224 3845 1338 33 894 3845 4345 46 885 204 2922 36 247 204 170 65 462 856 1992 99 247 856 1724 63 628 856 3776 23 178 871 998 46 247 871 3734 45 442 871 4449 25 557 998 3352 85 247 998 4770 42 148 998 164 19 316 1409 871 84 247 1409 2782 98 993 1547 4938 46 247 1547 4511 44 247 1547 2833 9 149 1986 2384 65 247 1986 3249 53 198 1992 1409 30 247 1992 2270 50 737 2384 1547 44 247 2384 2009 58 799 2922 856 81 247 2922 3810 15 517 2922 4178 86 906 3352 1986 54 247 3352 4995 55 31 3352 1840 31 510 205 1238 2 688 205 3823 58 369 1084 2701 42 688 1084 1645 1 855 1238 1084 70 688 1238 1789 29 371 2236 4659 36 688 2236 3472 95 587 2701 2943 6 688 2701 2551 3 392 2943 3006 49 688 2943 4369 70 996 3006 4445 84 688 3006 4538 55 688 3006 2708 52 192 3006 4497 84 223 4257 2236 20 688 4257 2776 56 248 4445 4257 21 688 4445 2834 90 689 206 3883 22 585 206 2943 10 322 551 2261 61 585 551 1742 34 649 601 2988 71 585 601 4949 66 585 601 1046 71 709 743 4212 62 585 743 934 34 725 2261 2867 7 585 2261 590 87 320 2867 601 42 585 2867 4725 55 997 2867 4892 13 362 2988 4642 73 585 2988 3793 44 80 3883 743 69 585 3883 802 72 370 3883 640 34 337 4212 551 51 585 4212 306 54 262 4212 1788 47 358 207 1327 25 334 207 1665 68 196 207 4224 73 311 1180 4253 32 334 1180 2630 90 327 1180 1749 15 155 1327 3233 33 334 1327 3285 54 811 1807 4531 15 334 1807 4180 38 334 1807 1990 33 347 3233 1180 68 334 3233 1631 26 315 3233 1890 50 861 4180 4672 3 334 4180 4800 6 76 4253 1807 78 334 4253 3433 27 789 4253 227 70 250 208 3041 6 526 208 2741 31 541 948 1399 92 526 948 3297 12 404 1159 3170 80 526 1159 2227 65 562 1159 692 5 340 1399 1159 3 526 1399 645 88 275 1877 4267 58 526 1877 2102 20 65 1877 163 3 274 2224 3907 63 526 2224 4084 2 285 3041 4662 34 526 3041 948 99 526 3041 4624 28 204 3170 1877 25 526 3170 3010 50 638 3170 502 10 271 3907 4914 90 526 3907 671 80 198 4267 2224 38 526 4267 4064 43 399 209 3971 39 399 209 4521 6 462 209 1163 79 548 1196 2812 4 399 1196 1855 2 499 1631 1196 8 399 1631 4274 100 383 1631 147 82 410 2000 4591 6 399 2000 4391 60 528 2812 2000 2 399 2812 4776 36 668 2812 3753 76 204 2833 1631 43 399 2833 4655 28 399 2833 4347 53 594 3971 2833 84 399 3971 1341 88 559 3971 3517 18 264 210 657 62 270 210 4827 16 359 657 3614 57 270 657 3216 95 65 767 4561 33 270 767 526 32 697 767 3044 92 989 1391 2980 11 270 1391 1113 31 62 1391 191 88 921 2980 3031 95 270 2980 4196 77 834 2980 1503 18 969 3031 767 34 270 3031 4934 32 681 3031 2102 71 85 3614 1391 47 270 3614 4734 84 270 3614 1122 18 786 211 3937 30 826 211 1230 12 252 574 2295 60 826 574 2625 84 714 1093 2355 41 826 1093 1048 89 335 1470 3453 46 826 1470 287 99 24 1470 746 83 422 1827 2293 23 826 1827 1541 6 597 2293 574 59 826 2293 1908 53 2 2293 722 9 687 2295 3534 19 826 2295 4355 72 133 2355 1827 34 826 2355 2583 94 775 3453 3622 45 826 3453 4355 58 640 3453 2875 72 205 3534 1470 72 826 3534 655 42 220 3622 3763 98 826 3622 3519 11 886 3763 4858 53 826 3763 4782 12 826 3763 4639 50 826 3763 2261 51 559 3937 1093 41 826 3937 2660 34 399 212 2559 42 150 212 1109 57 697 212 925 25 918 1786 4103 59 150 1786 4648 19 150 1786 3409 86 986 1786 2634 46 809 2157 2301 13 150 2157 4851 54 381 2157 2703 36 606 2301 3510 56 150 2301 3545 39 537 2301 1617 27 597 2559 3836 94 150 2559 2738 21 967 2559 1075 34 313 2776 1786 99 150 2776 3155 67 825 3510 2776 4 150 3510 2494 40 519 3510 4861 74 874 3836 2157 48 150 3836 3720 26 219 3836 1336 21 406 4103 4852 80 150 4103 806 93 360 213 4099 5 472 213 170 28 197 855 2822 45 472 855 1828 52 885 855 3707 5 728 934 3432 55 472 934 1882 20 958 934 1371 57 543 1028 1970 51 472 1028 2403 26 477 1028 143 75 173 1374 1028 13 472 1374 3507 24 711 1374 836 95 291 1970 4629 53 472 1970 2478 43 94 2822 4672 50 472 2822 934 45 472 2822 2410 49 984 2822 4399 37 462 3078 855 96 472 3078 591 97 679 3078 3812 4 702 3432 1374 79 472 3432 4976 10 400 3432 4085 30 973 4027 3078 17 472 4027 3276 39 758 4027 3232 47 341 4099 4027 35 472 4099 719 78 784 214 4034 81 545 214 589 87 380 214 3758 18 932 887 3544 96 545 887 4130 15 773 952 887 29 545 952 303 70 556 952 1367 44 405 1097 1110 35 545 1097 849 1 261 1110 952 58 545 1110 2489 92 389 1110 901 16 298 1829 4807 12 545 1829 3118 81 506 1829 3107 85 98 3544 1829 33 545 3544 4834 61 545 3544 3117 86 942 4034 1097 52 545 4034 1089 23 147 4034 1889 61 347 215 2045 57 275 215 4995 30 86 215 4506 78 342 1487 4896 3 275 1487 4984 3 275 1487 126 64 185 1487 2774 67 918 1578 1487 7 275 1578 1786 5 649 1828 3464 26 275 1828 2898 52 50 1828 898 90 22 2045 1828 99 275 2045 4782 28 170 2045 4018 85 940 3464 4136 92 275 3464 2447 8 322 3464 153 63 518 4136 4459 72 275 4136 829 87 582 4136 1426 44 24 4459 1578 70 275 4459 1762 29 331 4459 4683 57 128 216 2403 42 732 216 3159 72 244 1404 2801 7 732 1404 2272 81 949 1404 4511 64 231 2321 3049 42 732 2321 4547 90 732 2321 825 45 831 2403 2321 77 732 2403 2438 59 506 2561 1404 39 732 2561 1430 48 416 2801 4810 86 732 2801 361 64 481 2801 1073 6 554 3049 3084 48 732 3049 3652 35 509 3084 2561 95 732 3084 2578 40 882 3084 2549 74 152 217 1816 78 675 217 3882 43 533 217 4007 33 252 917 4725 98 675 917 2612 60 906 1500 4433 70 675 1500 2298 16 126 1500 3395 42 166 1689 917 73 675 1689 4090 66 389 1816 3219 41 675 1816 4951 4 618 1816 2436 41 41 3219 1500 45 675 3219 2162 41 66 3329 1689 85 675 3329 2603 47 498 3329 3829 91 424 3635 3329 8 675 3635 4752 88 675 3635 2550 9 917 4433 3635 55 675 4433 1716 24 356 218 1088 25 351 218 3638 76 823 1016 3788 62 351 1016 1467 18 355 1016 972 78 194 1088 3288 71 351 1088 4996 91 351 1088 3287 18 920 2859 2861 91 351 2859 2429 57 418 2861 1016 61 351 2861 2172 85 949 3288 3593 68 351 3288 2625 6 640 3593 2859 35 351 3593 1702 38 610 3593 3730 78 168 3788 4882 21 351 3788 4861 20 144 219 4155 26 897 219 1102 33 424 219 4317 95 782 565 2360 36 897 565 2052 88 122 565 459 55 710 1593 2659 45 897 1593 4030 6 634 1593 4410 50 906 2325 4469 91 897 2325 3794 14 307 2360 4609 54 897 2360 4501 16 664 2360 923 86 249 2462 2325 78 897 2462 148 17 585 2659 565 20 897 2659 4645 19 897 2659 2946 74 983 4155 2462 86 897 4155 3746 30 334 4469 1593 5 897 4469 1841 85 596 4469 1428 12 661 220 3294 60 572 220 1290 17 806 516 929 32 572 516 4103 29 843 516 1995 62 622 724 2163 87 572 724 1676 34 862 839 1116 65 572 839 3193 33 768 929 4910 45 572 929 3531 23 572 929 91 43 982 929 3490 32 48 1012 724 75 572 1012 4315 75 551 1012 2168 49 318 1116 1165 10 572 1116 4030 36 767 1165 1012 20 572 1165 757 24 457 1165 1304 2 259 2163 516 94 572 2163 3775 32 594 3294 839 80 572 3294 4547 38 476 3531 4759 22 572 3531 13 21 67 221 4235 56 270 221 2474 31 10 1627 3306 42 270 1627 3943 17 173 1627 4681 17 152 3306 4714 6 270 3306 1392 93 78 3306 4969 10 560 3328 4070 89 270 3328 3611 14 278 3328 650 5 157 4070 4418 85 270 4070 4983 8 270 4070 1841 82 312 4235 3328 57 270 4235 3358 35 171 4418 1627 48 270 4418 777 2 296 4418 3631 72 207 222 926 76 68 222 3995 35 917 926 4023 41 68 926 339 5 207 1957 4889 6 68 1957 4456 48 68 1957 4433 67 895 1957 3965 87 124 2036 3434 24 68 2036 674 22 444 2036 2825 20 611 3269 1957 20 68 3269 2400 19 548 3269 4469 78 847 3434 4694 7 68 3434 2473 36 312 3990 3269 55 68 3990 714 45 883 4023 3990 76 68 4023 364 29 326 4456 2036 53 68 4456 1976 21 579 223 2684 83 843 223 3028 91 829 648 3373 3 843 648 3209 81 596 648 995 45 563 1198 4958 63 843 1198 439 78 645 1198 775 32 248 1479 3688 45 843 1479 763 70 78 2684 648 40 843 2684 4535 99 940 2684 224 24 399 3045 3815 22 843 3045 4400 41 663 3373 3045 12 843 3373 201 84 981 3688 1198 53 843 3688 4177 66 193 3815 1479 86 843 3815 4694 89 843 3815 224 21 990 224 4319 50 352 224 595 28 950 1027 4958 53 352 1027 2502 15 148 2080 4950 17 352 2080 3341 73 352 2080 1422 35 263 2999 1027 82 352 2999 3991 45 384 3268 4045 44 352 3268 1148 75 342 3341 2999 45 352 3341 3744 92 284 3341 1419 22 999 4045 2080 17 352 4045 3774 44 812 4319 3268 10 352 4319 149 56 764 225 2644 8 395 225 3812 66 308 225 4158 26 410 1650 4685 1 395 1650 147 61 75 1880 1650 99 395 1880 3521 60 810 1880 2599 44 884 2424 3780 97 395 2424 905 49 735 2631 1880 93 395 2631 2462 56 339 2631 4630 65 682 2644 2808 65 395 2644 1033 39 4 2808 2424 96 395 2808 3638 54 1000 2808 556 75 149 3780 2631 100 395 3780 4609 33 395 3780 3862 41 507 226 1902 77 584 226 3564 41 863 745 4834 34 584 745 2704 61 142 817 4348 42 584 817 3488 85 435 873 2464 70 584 873 3897 15 237 873 1995 98 784 1561 817 67 584 1561 4667 88 528 1561 2742 7 74 1902 2588 56 584 1902 3248 99 77 2131 873 76 584 2131 3075 70 433 2464 745 29 584 2464 816 39 843 2464 2792 68 969 2588 1561 16 584 2588 4830 58 584 2588 1558 83 85 2588 3467 11 77 3525 2131 68 584 3525 1326 56 874 4348 3525 14 584 4348 72 10 876 227 3681 74 192 227 869 51 79 227 3365 57 384 2129 3116 94 192 2129 4914 10 192 2129 1700 6 349 2924 4531 66 192 2924 731 49 246 2924 3473 34 379 3116 3263 45 192 3116 2171 92 626 3116 2063 92 314 3263 2924 2 192 3263 3985 47 224 3276 2129 25 192 3276 2599 11 373 3276 4340 27 114 3681 3276 70 192 3681 1911 70 346 228 4230 43 379 228 4758 69 289 980 3193 58 379 980 4941 1 411 1291 1691 94 379 1291 4118 26 567 1691 2440 65 379 1691 4059 28 567 1691 1466 25 912 2276 3639 95 379 2276 2621 6 544 2276 2569 12 675 2440 3840 92 379 2440 4665 84 270 3193 2276 97 379 3193 2846 42 329 3639 1291 23 379 3639 4752 22 379 3639 3099 28 273 3639 2609 34 87 3840 4869 86 379 3840 3047 99 97 4230 980 89 379 4230 2500 82 415 4230 1724 36 97 229 2699 38 325 229 1075 86 358 229 4133 13 241 802 1611 95 325 802 1836 82 795 802 2372 67 499 851 802 6 325 851 465 28 778 851 3706 96 489 976 4869 18 325 976 1176 7 615 1611 976 70 325 1611 3777 31 957 1611 2416 2 153 2699 3456 2 325 2699 4523 16 325 2699 3671 12 541 3456 3463 82 325 3456 1624 47 446 3463 851 12 325 3463 4847 35 790 230 1951 64 843 230 3913 77 339 230 2007 75 435 1141 4009 39 843 1141 3344 17 486 1951 4189 76 843 1951 4667 87 469 1951 1986 7 91 2051 4146 79 843 2051 23 52 847 2621 4591 76 843 2621 3745 42 843 2621 963 10 62 2621 2814 46 330 3745 2051 69 843 3745 792 28 186 4009 2621 11 843 4009 4668 9 504 4146 4516 79 843 4146 4982 33 698 4146 3194 59 857 4186 1141 70 843 4186 3961 62 368 4186 3096 27 203 4189 4186 88 843 4189 109 72 372 4189 29 1 879 231 3218 45 105 231 1169 10 240 800 1935 56 105 800 4842 55 422 969 3784 86 105 969 3984 40 624 969 3992 82 723 1413 969 71 105 1413 4893 30 105 1413 4804 52 900 1935 2624 3 105 1935 3491 58 310 1935 2448 66 135 2624 3899 21 105 2624 3850 75 431 3218 800 80 105 3218 3875 17 609 3218 4677 48 546 3784 4684 93 105 3784 3221 97 654 3899 1413 88 105 3899 820 52 691 3899 4188 32 334 232 584 79 978 232 4487 51 377 232 4489 1 635 584 4294 24 978 584 1737 10 296 584 365 68 681 1140 3511 9 978 1140 420 46 760 1140 4568 53 906 2406 4580 17 978 2406 1350 59 100 2995 3985 51 978 2995 454 96 341 3511 2406 39 978 3511 2303 77 17 3511 2541 99 929 3985 1140 91 978 3985 1181 51 627 4231 4701 62 978 4231 2995 100 978 4231 645 28 383 4294 4231 81 978 4294 617 1 181 233 1049 41 446 233 1268 51 975 233 4940 71 383 968 3140 48 446 968 2661 72 988 1049 968 11 446 1049 1609 71 898 1049 929 83 152 3140 4297 26 446 3140 2279 88 626 3140 1332 31 655 3159 4600 44 446 3159 454 31 676 3159 903 44 82 3765 4164 74 446 3765 1284 38 137 3765 2646 56 354 4164 3159 86 446 4164 4194 50 465 4164 4466 40 967 4297 3765 74 446 4297 4782 77 446 4297 4859 57 499 4297 655 15 548 234 919 67 102 234 1052 46 486 843 3502 52 102 843 2196 75 382 843 3816 28 864 919 3024 19 102 919 4960 75 102 919 4932 69 844 919 2559 48 308 1344 3816 43 102 1344 3427 6 868 1344 3952 86 899 3024 3230 18 102 3024 234 21 10 3230 843 1 102 3230 676 13 158 3502 1344 55 102 3502 4769 47 974 3502 3338 60 390 3816 4755 3 102 3816 488 21 923 3816 3060 68 645 235 967 73 315 235 1606 40 290 967 1926 25 315 967 4187 63 219 1297 2700 10 315 1297 1854 31 692 1926 4085 80 315 1926 4475 57 424 2202 3278 93 315 2202 4149 41 510 2202 2195 12 35 2315 3661 53 315 2315 1941 69 271 2315 102 49 98 2560 4800 10 315 2560 4513 78 932 2560 3963 60 765 2700 2315 62 315 2700 1458 47 718 2700 1693 86 676 3278 2560 79 315 3278 3371 87 814 3278 1175 17 372 3661 2202 22 315 3661 3866 100 866 4085 4709 86 315 4085 4144 26 315 4085 1701 21 391 4085 2212 73 159 4144 1297 5 315 4144 3706 11 412 4144 2030 55 859 236 3740 51 368 236 262 54 438 236 1060 11 657 902 4715 94 368 902 844 22 566 2398 3634 49 368 2398 4129 88 593 2398 4652 53 61 2418 2398 63 368 2418 4581 22 303 2418 3563 69 5 3634 4312 26 368 3634 4753 65 368 3634 1090 41 998 3634 3367 42 43 3740 2418 99 368 3740 1383 72 457 4312 902 72 368 4312 3703 27 877 4312 1296 92 248 237 4000 14 293 237 207 44 707 695 4543 75 293 695 2375 78 712 2647 695 93 293 2647 1338 52 846 3706 4220 25 293 3706 3675 71 715 4000 3706 35 293 4000 1207 94 630 4220 2647 9 293 4220 4596 13 293 4220 4513 52 513 4220 3485 80 503 238 1029 91 391 238 2508 29 331 1029 4062 62 391 1029 1888 23 744 1029 2913 96 728 1424 3296 49 391 1424 2785 1 48 1628 1424 57 391 1628 727 98 739 1628 2940 34 614 1632 1628 42 391 1632 2664 5 765 1632 4902 97 487 1765 1632 13 391 1765 4575 100 391 1765 392 33 23 1765 2822 16 138 3296 4744 71 391 3296 4909 47 229 4062 1765 65 391 4062 3630 14 464 4062 3551 52 979 239 2048 81 816 239 3523 29 323 239 3648 52 672 870 3828 3 816 870 260 63 412 1674 2533 52 816 1674 4656 40 816 1674 2651 72 889 2048 4108 73 816 2048 2066 67 593 2048 884 70 414 2533 4975 86 816 2533 4483 85 815 2533 2116 64 985 3828 1674 24 816 3828 2613 20 823 4108 870 80 816 4108 2387 18 842 4108 458 41 904 240 3888 76 456 240 785 17 496 2185 3761 12 456 2185 3305 38 618 2928 4363 35 456 2928 2584 30 245 2928 4534 88 605 3132 2928 78 456 3132 922 86 105 3292 3132 9 456 3292 3590 32 710 3292 3400 9 615 3761 4838 63 456 3761 447 89 295 3888 4387 66 456 3888 219 95 714 4363 2185 25 456 4363 4045 78 222 4363 4473 100 515 4387 3292 46 456 4387 4930 25 456 4387 588 63 106 4387 671 79 94 241 1821 98 490 241 3717 33 386 241 846 2 129 1521 3345 28 490 1521 1633 29 436 1821 3558 42 490 1821 4863 17 827 1821 569 81 799 2274 1521 2 490 2274 1292 44 612 2274 4498 94 162 2515 2274 28 490 2515 1960 64 998 2515 2100 50 674 3345 3839 54 490 3345 4757 63 490 3345 3654 54 14 3345 1077 54 30 3558 4430 84 490 3558 2860 92 510 3558 1275 35 31 3839 4826 51 490 3839 4845 80 887 4430 2515 8 490 4430 493 39 763 4430 4019 23 825 242 2763 32 123 242 4406 3 318 877 3253 58 123 877 2018 60 918 1156 2088 73 123 1156 690 88 207 1156 4044 69 214 2088 4506 15 123 2088 4980 20 553 2088 2879 97 802 2465 877 72 123 2465 2351 6 454 2763 4083 40 123 2763 134 39 244 2883 1156 63 123 2883 3338 95 971 3253 3261 26 123 3253 4824 23 388 3261 4854 29 123 3261 2883 38 123 3261 1749 57 109 4083 2465 37 123 4083 4978 82 739 243 2220 42 146 243 3109 80 592 1559 1598 61 146 1559 4731 56 146 1559 2661 79 898 1576 4353 42 146 1576 1737 33 725 1576 3522 97 16 1598 1790 32 146 1598 1477 51 912 1598 4910 91 619 1668 2650 8 146 1668 4523 88 619 1790 1576 70 146 1790 1246 48 437 2220 1559 58 146 2220 2181 39 307 2220 3102 25 699 2650 4900 33 146 2650 2016 60 449 4353 1668 86 146 4353 3998 36 407 4353 4196 9 891 244 1641 63 498 244 2800 83 498 1017 1142 7 498 1017 1641 39 673 1142 2871 46 498 1142 1842 43 509 1395 1871 85 498 1395 3358 48 374 1641 1395 51 498 1641 178 86 552 1641 246 94 68 1728 2453 67 498 1728 4600 15 498 1728 1819 92 887 1871 1728 85 498 1871 3504 26 742 1871 980 5 979 2453 2786 97 498 2453 4099 20 987 2786 1017 41 498 2786 3790 86 654 2871 3016 85 498 2871 2740 100 566 2871 4614 78 863 3016 4741 25 498 3016 1142 23 1 3016 1952 88 220 245 883 76 595 245 225 23 134 245 2882 11 774 883 4152 64 595 883 239 85 961 883 3565 68 303 1383 3054 17 595 1383 878 55 231 1867 2143 21 595 1867 1903 22 630 2143 3799 3 595 2143 1249 13 75 3054 1867 100 595 3054 1521 16 341 3054 2723 3 951 3187 4102 30 595 3187 4831 48 595 3187 2597 29 967 3799 3187 88 595 3799 903 92 967 4063 1383 6 595 4063 3342 79 268 4102 4758 41 595 4102 538 24 983 4152 4063 42 595 4152 4943 44 543 246 787 61 229 246 890 65 56 246 105 91 685 787 4802 58 229 787 1768 36 229 787 3448 21 708 787 4336 5 610 1768 3270 72 229 1768 4574 75 371 1768 2262 50 20 1791 3940 58 229 1791 454 12 821 1791 4757 7 891 2228 3471 67 229 2228 3701 59 342 2228 4174 77 661 2327 4938 59 229 2327 449 25 381 2327 2620 58 775 2726 2327 97 229 2726 4333 68 345 2726 1496 88 203 3270 1791 22 229 3270 1048 66 15 3270 4979 76 859 3471 2726 38 229 3471 22 65 757 3940 2228 37 229 3940 1375 2 568 3940 4938 48 712 247 1693 57 761 247 3380 75 857 572 1961 27 761 572 4465 82 591 600 4953 14 761 600 1579 70 85 600 2345 2 664 1510 572 59 761 1510 4960 58 761 1510 582 51 594 1693 4096 24 761 1693 77 80 364 1693 3189 59 678 1961 4369 44 761 1961 2554 15 250 1961 966 11 485 1995 600 81 761 1995 1855 16 555 4096 4371 99 761 4096 1349 33 528 4369 1995 50 761 4369 4193 75 15 4369 1503 89 467 4371 1510 1 761 4371 260 11 275 248 3495 8 520 248 2414 85 388 631 915 29 520 631 3825 15 996 631 581 57 893 915 1848 82 520 915 1432 35 413 915 1939 54 969 1131 2986 9 520 1131 2642 31 246 1825 1936 51 520 1825 3859 49 493 1848 1131 83 520 1848 4183 12 646 1936 4671 83 520 1936 4734 75 520 1936 4903 58 636 2986 3379 20 520 2986 3404 4 514 3379 1825 21 520 3379 2725 5 372 3495 631 65 520 3495 4059 46 287 3495 2822 50 82 249 1179 60 1198 249 3700 41 737 249 546 77 643 931 2863 6 1198 931 4928 57 71 1179 2194 22 1198 1179 4774 41 1198 1179 1580 38 23 1563 4763 32 1198 1563 3557 2 595 2194 4482 11 1198 2194 4564 42 483 2194 150 99 907 2430 1563 66 1198 2430 3450 54 107 2863 2430 95 1198 2863 3873 66 699 4482 931 80 1198 4482 1783 5 784 4482 4806 12 928 250 1462 3 463 250 3952 14 483 1462 2920 60 463 1462 1796 22 350 1462 292 45 159 1504 4440 73 463 1504 1263 43 579 1504 1893 26 504 1813 4538 45 463 1813 1504 12 463 1813 2903 25 804 2118 4788 73 463 2118 2368 23 210 2920 4194 16 463 2920 232 97 843 2920 4620 20 548 3129 1813 49 463 3129 1256 93 524 3129 3955 84 443 3239 3129 30 463 3239 609 23 657 3239 1753 39 769 3438 3239 80 463 3438 4804 45 959 4194 3438 68 463 4194 463 66 719 4194 284 55 478 4440 2118 19 463 4440 4239 79 63 4440 4474 47 149 251 1692 99 497 251 3642 86 285 540 2712 57 497 540 3744 97 474 689 4960 50 497 689 1375 23 363 773 689 26 497 773 2016 94 658 773 2304 74 212 1692 3774 66 497 1692 4795 10 497 1692 2371 82 529 1692 4970 30 217 2339 2593 25 497 2339 2396 15 968 2339 17 90 177 2593 3191 77 497 2593 2271 50 325 2593 3615 19 337 2712 2339 32 497 2712 1823 97 898 2764 773 74 497 2764 581 85 561 2971 540 75 497 2971 1510 54 535 2971 1054 73 322 3070 4657 28 497 3070 2764 26 497 3070 4066 6 957 3070 1915 57 42 3191 3070 31 497 3191 4096 29 237 3774 2971 12 497 3774 3399 44 625 252 988 3 529 252 1350 71 463 252 406 95 663 655 3738 26 529 655 2414 14 496 655 3589 21 462 988 2694 45 529 988 4634 13 52 1249 1603 64 529 1249 4532 78 366 1249 1714 30 349 1603 2019 99 529 1603 3494 5 659 2019 655 35 529 2019 1354 51 486 2694 1249 77 529 2694 4587 69 529 2694 26 61 681 2694 1751 52 441 3738 4690 72 529 3738 4684 99 122 3738 4449 66 160 253 1966 92 913 253 636 33 275 761 3025 68 913 761 2291 11 840 761 3077 73 449 1107 4302 36 913 1107 3975 32 617 1966 4316 57 913 1966 1381 3 876 1966 4255 43 44 3025 4476 3 913 3025 930 89 451 3025 3265 37 87 3591 4509 41 913 3591 1200 49 356 3936 3591 34 913 3936 64 7 370 4302 3936 67 913 4302 1432 69 901 4302 3987 28 642 4316 761 29 913 4316 4314 30 398 4476 1107 82 913 4476 4620 60 913 4476 2452 90 346 4476 4972 15 576 254 3083 62 543 254 1824 56 746 2132 2554 3 543 2132 3771 91 141 2132 1444 12 260 2487 2132 61 543 2487 3435 69 394 2487 1184 59 982 2554 2978 59 543 2554 2412 6 458 2978 4119 17 543 2978 1069 84 593 3083 2487 20 543 3083 4560 62 543 3083 1102 18 821 3246 4709 85 543 3246 3023 99 115 4119 4175 54 543 4119 1879 63 626 4119 4358 80 159 4175 3246 86 543 4175 183 77 40 4175 1021 6 615 255 4420 20 584 255 133 55 598 255 1365 82 50 878 3265 41 584 878 4899 56 897 1086 1464 15 584 1086 4518 69 319 1464 3752 56 584 1464 1404 52 156 3265 3853 54 584 3265 142 60 476 3265 1668 83 745 3752 878 71 584 3752 4515 8 584 3752 1200 45 36 3752 146 25 796 3853 4809 66 584 3853 2247 6 902 3853 430 6 168 4420 1086 99 584 4420 123 61 439 256 735 9 193 256 4601 44 807 667 1075 69 193 667 3097 69 598 735 4127 18 193 735 3254 15 260 818 4928 90 193 818 54 70 905 818 3718 91 49 1046 3615 70 193 1046 2515 19 995 1046 4769 53 562 1075 2969 37 193 1075 80 13 487 1075 2474 84 780 1733 4532 82 193 1733 818 77 193 1733 2435 31 111 1733 237 82 660 2689 1733 6 193 2689 332 100 44 2969 2689 13 193 2969 2169 53 260 3615 667 43 193 3615 4062 32 593 4127 1046 63 193 4127 2696 59 695 257 1078 91 614 257 1771 8 49 624 4606 92 614 624 4894 25 614 624 2384 28 135 624 4024 86 429 984 2876 82 614 984 3626 18 494 1078 3998 29 614 1078 1700 21 298 1144 984 82 614 1144 4826 90 614 1144 3394 49 832 1144 1250 19 45 1555 1851 15 614 1555 2712 58 685 1555 3117 43 52 1851 4193 85 614 1851 3639 28 780 1851 1469 10 86 2001 624 49 614 2001 2669 94 455 2001 1666 37 137 2823 2001 99 614 2823 4343 12 285 2876 1555 68 614 2876 2253 50 42 3097 1144 93 614 3097 4106 24 527 3998 3097 67 614 3998 2264 59 987 4193 2823 27 614 4193 875 31 147 258 2806 1 449 258 3451 70 110 749 4693 61 449 749 170 22 735 1314 3930 28 449 1314 3492 51 622 1338 2846 93 449 1338 1021 54 37 1338 311 50 698 2148 2938 86 449 2148 1924 72 211 2519 749 21 449 2519 4932 75 449 2519 3877 80 487 2519 3260 25 200 2806 1314 17 449 2806 209 78 442 2846 3535 9 449 2846 1194 77 364 2938 1338 86 449 2938 4949 94 978 3186 4149 52 449 3186 2698 95 580 3535 3186 75 449 3535 1498 47 674 3535 2102 78 41 3930 2148 89 449 3930 757 11 714 3930 4396 54 79 4149 2519 20 449 4149 4512 32 449 4149 3468 70 465 259 3124 22 1 259 2540 61 415 1077 1849 2 1 1077 709 21 480 1077 2337 33 43 1774 1077 85 1 1774 4718 42 255 1849 2816 89 1 1849 4822 78 58 1849 2953 79 223 2571 4593 100 1 2571 4944 23 1 2571 247 13 908 2571 3861 95 277 2816 3403 62 1 2816 2348 17 590 3124 4123 81 1 3124 313 47 419 3403 3878 1 1 3403 4162 92 635 3878 2571 93 1 3878 1809 35 494 3878 1816 69 706 4123 1774 98 1 4123 2126 7 251 260 4183 35 612 260 4784 64 218 260 2371 28 247 727 4916 49 612 727 3764 1 612 727 786 74 368 1478 4538 68 612 1478 4134 36 112 1478 4123 95 548 1557 727 49 612 1557 2208 38 137 3764 3855 89 612 3764 1382 22 451 3855 1478 44 612 3855 1992 10 23 4183 4479 8 612 4183 2116 82 567 4183 1494 97 615 4479 1557 67 612 4479 4161 5 998 261 2642 50 349 261 2663 11 763 530 4761 76 349 530 765 79 464 530 435 26 953 1087 2482 88 349 1087 1405 2 128 1185 530 74 349 1185 296 39 530 1723 1087 80 349 1723 1245 72 864 2213 1723 93 349 2213 4786 87 349 2213 3689 10 1000 2213 3766 94 321 2482 1185 70 349 2482 752 18 694 2642 2213 84 349 2642 632 72 210 2642 3593 69 958 262 1704 100 355 262 323 99 206 716 2242 62 355 716 1520 96 809 891 716 20 355 891 1311 42 163 996 4508 56 355 996 3836 17 654 1704 3697 12 355 1704 1133 47 542 1704 1776 38 305 2242 996 96 355 2242 3935 29 489 2242 59 92 647 3697 891 90 355 3697 4868 42 355 3697 2282 19 679 3697 1858 96 197 263 2844 49 511 263 1082 8 162 1560 1754 74 511 1560 3827 44 186 1560 3266 13 498 1735 2661 71 511 1735 3848 12 598 1754 4419 2 511 1754 4564 67 185 1754 3435 72 647 2191 1560 96 511 2191 1388 58 853 2318 4694 18 511 2318 3744 37 848 2661 4163 89 511 2661 1945 63 641 2844 2961 93 511 2844 2987 10 891 2936 2191 53 511 2936 2432 16 92 2961 1735 85 511 2961 2504 95 159 2961 528 4 612 4163 4668 13 511 4163 2936 13 511 4163 4676 19 338 4163 3896 95 605 4419 2318 55 511 4419 4681 57 185 4419 1112 83 232 264 1878 76 1586 264 1256 87 161 264 1483 80 875 793 1407 61 1586 793 2598 64 263 1290 3642 20 1586 1290 1995 44 697 1290 2662 67 691 1407 4654 83 1586 1407 3645 37 1586 1407 906 37 400 1784 3577 40 1586 1784 829 24 858 1784 958 10 235 1878 793 81 1586 1878 3798 7 375 1878 4843 70 981 3145 4307 45 1586 3145 234 9 587 3214 4790 47 1586 3214 1887 55 168 3214 4544 73 389 3217 4849 2 1586 3217 3145 82 1586 3217 1214 21 628 3577 3217 99 1586 3577 4306 6 683 3642 3214 25 1586 3642 2833 82 116 3645 1784 41 1586 3645 4753 3 338 3645 4609 65 882 4307 1290 85 1586 4307 3244 88 977 265 1316 36 383 265 1788 95 887 815 3380 31 383 815 3446 76 463 815 3126 25 467 1060 3130 40 383 1060 4530 7 383 1060 3372 18 16 1316 4483 24 383 1316 3744 48 349 1461 3915 52 383 1461 1512 28 683 1461 2986 80 785 2474 1461 50 383 2474 2110 86 779 2474 1560 8 769 3130 815 74 383 3130 2717 10 304 3130 4319 45 272 3250 1060 35 383 3250 3377 18 465 3380 2474 84 383 3380 3680 16 704 3380 2304 87 812 3915 4847 90 383 3915 2688 77 791 4483 3250 59 383 4483 3692 94 995 266 619 97 192 266 4688 30 661 266 721 88 832 545 3952 21 192 545 1016 11 733 545 3775 19 335 619 3858 31 192 619 19 92 313 641 3775 13 192 641 3947 33 640 641 3571 25 196 682 641 76 192 682 4735 53 192 682 2994 34 176 682 4822 27 743 1466 545 19 192 1466 1039 11 505 3775 4018 36 192 3775 1162 49 977 3775 3955 16 547 3858 682 26 192 3858 3952 74 106 3858 2446 1 179 3952 4602 30 192 3952 3897 12 683 3952 2477 79 340 4018 1466 27 192 4018 2062 46 231 267 2537 73 92 267 2596 56 656 267 995 80 335 671 3541 29 92 671 1002 21 145 671 3792 67 271 707 3548 30 92 707 3516 74 96 2067 3690 5 92 2067 1516 43 95 2067 1421 46 587 2307 4804 20 92 2307 2699 69 314 2537 4330 25 92 2537 380 37 625 3541 2067 76 92 3541 2008 38 392 3548 2307 91 92 3548 1521 95 124 3690 707 11 92 3690 1371 91 874 4330 671 49 92 4330 4993 87 92 4330 18 57 105 4330 3518 23 750 268 2072 21 842 268 3731 35 216 646 4266 34 842 646 1774 99 816 646 2274 99 220 669 4357 91 842 669 1253 5 633 669 4999 72 364 1167 1371 75 842 1167 1584 82 632 1371 669 94 842 1371 1847 41 905 2072 4564 22 842 2072 4317 46 842 2072 2889 41 18 2072 3822 90 241 4030 4826 62 842 4030 2682 93 578 4266 4030 99 842 4266 285 74 182 4266 732 86 335 4317 1167 14 842 4317 3279 70 497 4357 646 32 842 4357 1454 28 286 4357 3239 71 700 269 4134 58 601 269 395 69 300 269 1841 98 555 1173 2243 23 601 1173 4186 45 221 1173 3505 33 375 1657 3576 15 601 1657 2815 80 39 1666 2925 7 601 1666 616 19 890 2243 4453 52 601 2243 3018 92 967 2243 4568 73 946 2925 4771 12 601 2925 4831 92 160 3249 1173 21 601 3249 2724 86 330 3249 3990 82 449 3576 4996 98 601 3576 4229 90 601 3576 3883 23 774 4134 1657 52 601 4134 3816 44 164 4134 4252 21 75 4229 3249 37 601 4229 1951 73 221 4229 2987 100 953 4453 1666 65 601 4453 4690 22 447 270 1661 83 39 270 1388 93 762 511 4748 15 39 511 1970 100 133 511 4921 34 800 717 2575 92 39 717 3205 3 24 1661 4499 55 39 1661 1889 58 432 2052 511 22 39 2052 4838 74 39 2052 4603 6 239 2052 2116 75 841 2575 2052 93 39 2575 4287 33 684 2609 3216 15 39 2609 2314 89 952 2609 1874 65 23 2820 2609 85 39 2820 2553 11 351 3156 2820 100 39 3156 2083 59 563 3156 1384 47 527 3216 717 87 39 3216 41 70 962 3686 3156 38 39 3686 2431 75 856 4499 3686 96 39 4499 3037 7 960 271 3506 40 276 271 592 88 628 670 2425 99 276 670 171 92 362 670 3738 63 984 914 2299 47 276 914 885 2 50 1706 1947 81 276 1706 1710 54 867 1947 2606 89 276 1947 3419 62 227 1947 3746 63 600 2299 1706 50 276 2299 417 76 890 2425 914 27 276 2425 2974 10 793 2425 4166 48 993 2606 3663 99 276 2606 4743 85 276 2606 4239 38 435 3506 670 56 276 3506 3888 24 914 3506 3747 90 120 3663 4898 19 276 3663 1417 31 839 3663 4095 83 79 272 1467 17 363 272 3815 90 140 715 4113 65 363 715 3382 30 978 1467 1943 75 363 1467 3217 46 820 1467 325 14 910 1830 715 9 363 1830 1366 94 388 1943 1830 59 363 1943 3362 67 497 1943 4006 14 657 2893 4372 62 363 2893 641 51 523 4113 4421 76 363 4113 1072 100 556 4113 4457 21 864 4372 4833 27 363 4372 4718 66 363 4372 843 53 742 4372 3161 60 564 4421 2893 45 363 4421 4721 71 695 273 2634 6 371 273 25 16 547 514 2354 98 371 514 4981 57 803 1460 4803 14 371 1460 1476 8 371 1460 2452 77 21 1460 3766 8 902 1476 514 34 371 1476 3936 94 871 2354 3647 33 371 2354 650 15 649 2634 4015 12 371 2634 1643 95 926 3647 4740 24 371 3647 2340 43 155 4015 1460 3 371 4015 406 75 383 4015 1438 22 362 274 4397 86 53 274 401 96 28 274 3190 20 62 1043 4667 42 53 1043 3026 94 53 1043 3080 78 312 1517 3367 26 53 1517 4209 13 469 1845 3695 69 53 1845 1814 88 369 2761 3683 51 53 2761 4437 83 957 2761 2240 83 25 2934 1845 27 53 2934 4659 33 654 2996 1517 37 53 2996 134 19 287 3026 2934 90 53 3026 1757 2 150 3367 2761 1 53 3367 3308 60 650 3683 4974 14 53 3683 2285 40 932 3683 2165 49 76 3695 2996 3 53 3695 1411 64 402 4397 1043 25 53 4397 1426 11 384 275 3676 9 486 275 484 89 844 275 710 16 357 809 1753 98 486 809 2762 81 236 809 2029 60 335 1062 2566 100 486 1062 3092 100 384 1062 542 97 234 1089 2747 85 486 1089 2321 47 730 1533 3984 45 486 1533 4774 34 538 1753 1757 84 486 1753 3312 50 325 1753 2802 58 824 1757 4548 58 486 1757 4922 25 486 1757 1459 70 630 1757 2124 49 142 1923 1062 28 486 1923 4008 50 684 2566 1089 22 486 2566 2391 49 455 2566 3540 69 938 2747 3127 96 486 2747 1894 25 482 3127 809 51 486 3127 947 43 817 3676 4951 41 486 3676 1533 39 486 3676 2354 25 80 3984 1923 12 486 3984 4794 14 979 3984 2573 21 755 276 993 32 348 276 4462 4 844 276 2644 58 738 993 3358 64 348 993 4715 91 348 993 1460 89 650 993 780 12 726 1261 4147 32 348 1261 2399 18 804 1920 4710 58 348 1920 2118 63 346 3358 1261 41 348 3358 998 19 597 3358 176 80 812 4147 4467 63 348 4147 216 53 938 4467 1920 82 348 4467 1807 85 213 277 4300 31 407 277 1245 51 180 277 3369 82 665 555 3679 75 407 555 977 99 918 555 1190 94 643 1008 4835 82 407 1008 3579 57 407 1008 391 49 376 1558 1008 56 407 1558 3784 54 101 1558 837 34 59 1589 2912 17 407 1589 4505 30 407 1589 2636 7 825 2091 1589 33 407 2091 2921 98 717 2091 4397 76 428 2508 2091 73 407 2508 1568 90 225 2508 1330 10 519 2589 1558 20 407 2589 1010 15 289 2589 1746 31 196 2610 4677 1 407 2610 4553 97 768 2912 2589 54 407 2912 3610 38 361 3579 2610 63 407 3579 2131 90 419 3579 4826 71 345 3679 2508 79 407 3679 984 30 590 4300 555 57 407 4300 1485 61 524 278 4278 77 647 278 1401 73 713 653 1534 75 647 653 350 85 251 653 4765 30 724 1337 1793 32 647 1337 4129 11 1000 1337 2035 49 789 1534 4589 90 647 1534 377 51 83 1534 1798 96 160 1709 4086 32 647 1709 4528 83 647 1709 2496 98 656 1709 2431 31 337 1793 4190 22 647 1793 2343 84 506 3337 1337 39 647 3337 4645 78 74 3337 3263 28 811 4086 3337 25 647 4086 3774 11 363 4086 3148 51 510 4190 653 79 647 4190 823 41 326 4190 3186 14 541 4278 1709 15 647 4278 2290 16 609 4278 2734 20 15 279 674 18 417 279 990 60 282 656 2579 62 417 656 4550 79 613 674 2637 83 417 674 4393 32 984 890 1367 10 417 890 4694 13 116 890 180 90 581 1367 4816 94 417 1367 1819 44 643 2579 4471 7 417 2579 1749 81 578 2637 656 2 417 2637 1634 97 6 3318 4958 38 417 3318 890 28 417 3318 4676 52 509 3318 348 93 572 4471 3318 25 417 4471 859 90 258 280 1745 55 1070 280 665 100 143 1511 4351 76 1070 1511 4406 100 416 1713 3188 55 1070 1713 2292 59 503 1745 2681 32 1070 1745 4765 57 134 2096 3205 92 1070 2096 3670 64 405 2096 1232 87 591 2178 1713 16 1070 2178 3477 98 738 2681 2178 40 1070 2681 2772 92 97 2681 1215 2 631 3188 1511 57 1070 3188 4025 57 438 3205 4504 15 1070 3205 4045 82 301 3205 918 12 850 4351 2096 43 1070 4351 4731 10 1070 4351 879 33 704 281 3422 36 32 281 3113 7 995 1128 2638 73 32 1128 2796 57 795 1128 2739 33 441 2297 1128 1 32 2297 1272 9 373 2297 4313 73 677 2638 2998 24 32 2638 4672 97 32 2638 3345 2 741 2998 4826 86 32 2998 4992 28 459 2998 778 54 273 3422 2297 34 32 3422 4316 64 828 282 811 40 887 282 358 42 739 282 4225 91 164 811 2802 87 887 811 4961 10 887 811 1999 39 523 1673 4512 83 887 1673 3797 37 897 1673 3243 31 184 2353 4131 37 887 2353 344 40 477 2802 3656 34 887 2802 1451 77 733 3656 4321 72 887 3656 4241 78 620 3656 1839 72 668 4131 1673 4 887 4131 264 44 371 4131 4514 38 889 4321 2353 62 887 4321 1474 90 181 283 1257 39 387 283 291 79 733 759 3117 36 387 759 2103 8 191 1117 759 34 387 1117 250 98 899 1257 2486 10 387 1257 4978 53 519 1257 2889 36 507 1484 2811 95 387 1484 4598 24 387 1484 536 28 717 1484 2395 50 218 2027 2120 33 387 2027 1754 49 626 2027 4210 39 815 2120 4004 45 387 2120 4693 64 387 2120 4392 14 719 2120 4282 67 50 2486 1484 92 387 2486 2950 44 490 2811 1117 62 387 2811 1695 51 836 2811 4554 100 539 3117 2027 23 387 3117 3690 64 331 3117 4616 69 638 3813 4909 28 387 3813 2823 18 620 3813 400 7 102 4004 4376 98 387 4004 4894 39 53 4004 202 62 436 4376 3813 44 387 4376 1321 7 719 4376 722 49 502 284 3279 66 339 284 1049 76 96 284 4340 21 904 1683 4413 82 339 1683 358 70 940 2404 4657 93 339 2404 4119 84 245 2404 2343 15 55 2710 2404 70 339 2710 1734 99 531 3279 4251 59 339 3279 3648 2 78 3279 4216 71 485 3493 2710 44 339 3493 3180 86 475 3493 231 48 85 3665 4530 91 339 3665 1683 13 339 3665 4543 1 33 4251 3665 98 339 4251 4918 6 77 4251 1117 75 865 4413 3493 24 339 4413 30 90 955 285 1147 54 882 285 3609 59 774 701 1145 15 882 701 723 8 570 701 1408 22 426 1145 1519 43 882 1145 4057 100 194 1145 548 87 825 1147 701 57 882 1147 481 97 740 1147 2138 55 975 1519 2452 79 882 1519 3952 72 904 2174 3251 99 882 2174 4629 8 882 2174 3033 14 435 2174 3371 27 484 2298 2174 93 882 2298 2277 8 287 2452 2792 61 882 2452 44 74 263 2792 3242 11 882 2792 4986 68 73 3242 2298 69 882 3242 575 61 70 3242 1143 95 169 3251 4684 79 882 3251 769 52 530 286 4303 31 400 286 1041 82 678 286 4841 81 931 1201 1389 26 400 1201 4991 38 739 1375 1201 36 400 1375 693 92 427 1375 2942 83 867 1389 2495 41 400 1389 4698 10 244 1389 2191 4 1000 1548 3487 14 400 1548 4643 19 622 1548 1751 53 133 1875 1548 22 400 1875 4619 2 400 1875 3637 36 808 1875 4168 49 298 2140 1375 63 400 2140 4815 73 899 2495 4856 24 400 2495 584 96 559 3376 1875 76 400 3376 4783 7 604 3376 4847 17 308 3487 2140 77 400 3487 4985 27 799 4249 3376 53 400 4249 193 74 471 4249 757 23 752 4303 4249 25 400 4303 246 32 999 4303 615 83 346 287 4029 78 410 287 3554 14 440 287 2555 91 435 556 848 96 410 556 346 16 358 848 2885 2 410 848 2419 54 950 848 4282 58 342 2447 3435 26 410 2447 1635 73 361 2885 4288 95 410 2885 4731 99 410 2885 3122 52 778 2955 3455 58 410 2955 635 61 866 3435 2955 18 410 3435 1436 23 301 3435 2607 66 435 3455 556 12 410 3455 1407 81 560 4029 2447 39 410 4029 1998 21 430 4029 1302 55 378 4288 4770 38 410 4288 4746 82 508 4288 4401 12 994 288 3125 12 534 288 459 76 866 672 4922 15 534 672 1277 81 793 672 4763 89 982 987 2665 86 534 987 1711 10 101 987 342 98 367 1450 2044 87 534 1450 3110 16 875 1450 1876 48 266 1604 672 97 534 1604 2756 53 181 1604 2836 29 823 1839 4891 36 534 1839 1450 5 534 1839 1511 35 437 1839 4487 66 769 1910 3877 9 534 1910 2454 18 6 1910 581 76 856 2044 1910 67 534 2044 1291 69 229 2044 3589 77 988 2356 3370 39 534 2356 4509 37 534 2356 2916 9 577 2356 4430 53 825 2665 2356 63 534 2665 4856 97 884 3125 987 27 534 3125 1727 39 525 3370 1839 68 534 3370 4911 51 323 3877 1604 16 534 3877 4057 99 534 289 3962 17 932 289 813 60 307 289 2110 6 64 963 4375 56 932 963 727 78 746 963 851 48 212 1051 1592 66 932 1051 4800 84 932 1051 1815 60 826 1501 1741 61 932 1501 755 33 1 1592 4766 10 932 1592 4930 26 288 1592 2554 54 313 1741 963 86 932 1741 1637 41 427 2357 1051 99 932 2357 1858 92 147 2357 3210 51 650 3962 1501 36 932 3962 2318 96 368 4375 2357 92 932 4375 2755 98 537 290 3479 55 367 290 3686 85 78 290 789 95 939 2169 2947 2 367 2169 3409 56 37 2169 3126 10 706 2484 3804 49 367 2484 2673 47 847 2484 1874 42 6 2947 3189 13 367 2947 1148 17 93 2947 4748 8 824 3189 4068 8 367 3189 2915 37 553 3418 4947 24 367 3418 662 42 19 3418 4749 71 440 3479 2484 19 367 3479 4560 66 464 3804 2169 73 367 3804 873 91 72 4068 3418 79 367 4068 4932 83 367 4068 3704 39 422 291 4254 25 747 291 2018 97 145 291 3167 28 629 586 4089 28 747 586 2680 80 816 1569 4961 74 747 1569 4627 3 747 1569 3489 57 724 1569 1398 48 640 2180 586 31 747 2180 4085 84 437 4089 4356 65 747 4089 885 36 740 4254 4491 16 747 4254 3763 61 320 4356 1569 71 747 4356 2586 16 481 4356 3751 39 405 4491 2180 88 747 4491 4221 25 381 4491 1200 27 660 292 3820 76 470 292 64 70 101 292 2612 63 413 537 2085 90 470 537 278 8 749 981 4512 49 470 981 752 77 247 1972 2989 34 470 1972 3900 58 331 1972 4315 3 940 2085 1972 71 470 2085 3232 1 12 2085 202 34 668 2989 981 53 470 2989 4135 61 682 3757 537 16 470 3757 4292 67 853 3757 1098 27 551 3820 3757 58 470 3820 4766 11 470 3820 1722 31 810 293 954 95 202 293 491 83 717 293 2886 91 944 954 997 68 202 954 623 45 134 997 1838 29 202 997 4801 51 93 997 4336 49 925 1013 4789 18 202 1013 3096 2 149 1838 2510 86 202 1838 1039 48 570 2510 4345 6 202 2510 1717 59 320 2510 3246 83 36 4345 1013 8 202 4345 4625 19 202 4345 3274 39 589 4345 69 99 36 294 882 91 680 294 3735 25 561 882 1092 67 680 882 1028 35 544 882 3148 70 142 1044 2720 31 680 1044 432 65 667 1092 4151 26 680 1092 1333 76 145 2720 4846 31 680 2720 3200 20 283 2720 715 13 172 2897 3111 43 680 2897 4506 11 680 2897 1800 80 842 2897 683 63 238 3111 1044 79 680 3111 4679 53 633 3111 1748 9 667 4151 2897 72 680 4151 4794 97 683 4151 1461 68 564 295 4275 9 354 295 4475 29 326 295 4538 33 9 548 2772 85 354 548 2749 9 298 652 4490 5 354 652 3291 96 615 652 3333 98 44 1384 4680 67 354 1384 2504 74 143 1653 2717 18 354 1653 2709 32 139 1653 1969 99 295 1879 652 77 354 1879 2538 13 523 2012 1653 42 354 2012 1954 51 799 2012 70 53 686 2717 1384 100 354 2717 3774 76 676 2772 4542 53 354 2772 4182 31 354 2772 494 34 691 4182 2012 32 354 4182 2517 9 86 4182 4318 69 124 4275 1879 58 354 4275 1207 48 124 4275 1335 36 527 4490 548 3 354 4490 1088 93 174 4490 624 53 600 296 3716 18 730 296 1419 75 781 296 3413 29 623 904 3322 2 730 904 3470 7 967 904 4370 29 230 1229 3518 96 730 1229 3507 48 785 1229 2254 61 593 1509 1815 37 730 1509 4130 41 233 1815 4513 65 730 1815 4748 33 730 1815 4417 73 509 1815 4465 68 761 3322 1229 58 730 3322 2661 12 888 3322 3001 25 653 3496 1509 4 730 3496 6 22 296 3496 943 59 981 3518 4047 43 730 3518 4393 61 719 3518 2245 41 223 3716 904 48 730 3716 1043 52 939 3716 890 30 54 4047 3496 61 730 4047 3144 11 832 297 643 94 451 297 446 100 861 297 2259 99 248 643 3011 2 451 643 1181 75 130 1266 3671 31 451 1266 1769 98 928 1843 1266 8 451 1843 3082 51 994 2381 3262 81 451 2381 4741 4 451 2381 266 34 650 2381 3030 40 664 3011 1843 94 451 3011 1445 49 177 3011 4317 68 567 3262 4669 59 451 3262 4403 36 448 3262 4027 17 748 3671 4185 22 451 3671 30 96 243 4185 2381 52 451 4185 739 85 602 298 3809 36 408 298 35 82 975 298 3738 67 242 1573 4705 12 408 1573 2865 43 408 1573 544 80 308 1945 2189 88 408 1945 3996 55 294 2189 4382 2 408 2189 1085 35 131 2865 3827 49 408 2865 3037 96 33 2865 4242 76 389 3572 4106 55 408 3572 1419 97 426 3572 3004 14 214 3809 1945 6 408 3809 4547 47 508 3809 526 38 447 3827 4518 43 408 3827 4034 2 992 3827 948 62 505 4106 1573 7 408 4106 2372 25 20 4382 3572 48 408 4382 803 91 651 4382 2601 99 880 299 757 33 559 299 4995 33 494 299 200 7 839 757 1520 64 559 757 3872 74 781 757 196 70 475 1307 4588 98 559 1307 301 46 410 1307 327 60 919 1520 2745 88 559 1520 2052 53 562 1520 4721 45 578 2371 4442 56 559 2371 1233 5 567 2371 3728 77 977 2745 3022 95 559 2745 4827 6 702 3022 2371 76 559 3022 4986 2 127 3022 3379 40 36 3529 3861 43 559 3529 4797 87 421 3529 2134 72 96 3551 1307 8 559 3551 3286 42 133 3551 1615 15 931 3861 3551 28 559 3861 2594 16 875 4442 3529 60 559 4442 4613 66 559 4442 3985 57 350 300 2049 20 1159 300 3666 8 114 2049 2240 53 1159 2049 1517 75 435 2240 2813 66 1159 2240 4833 6 1159 2240 2994 31 776 2267 3440 46 1159 2267 3048 64 720 2313 3955 32 1159 2313 3271 20 340 2813 2267 97 1159 2813 4977 43 440 2813 3486 18 484 3440 2313 11 1159 3440 3193 21 243 3440 1393 66 28 3955 4427 84 1159 3955 2747 48 832 4427 4968 83 1159 4427 4157 1 881 4427 2341 67 491 301 812 85 153 301 2132 7 363 301 3919 15 486 812 3517 8 153 812 4266 2 888 1325 3993 96 153 1325 391 85 214 1393 4707 8 153 1393 3068 72 153 1393 743 61 766 1393 3361 78 758 1546 4890 57 153 1546 747 66 755 1546 3799 1 634 2081 1546 41 153 2081 4737 85 217 2081 2481 33 180 2974 2081 89 153 2974 1418 20 816 2974 2758 39 456 3068 2974 89 153 3068 1913 51 304 3068 1230 26 32 3517 1325 93 153 3517 4400 6 28 3993 1393 21 153 3993 2215 88 673 3993 1508 89 420 302 3854 58 260 302 3386 51 514 1714 2539 62 260 1714 3765 28 757 1714 4617 40 426 1897 4157 37 260 1897 3497 35 348 2079 1897 77 260 2079 1715 43 317 2079 2759 59 745 2444 3122 71 260 2444 799 49 653 2473 4979 93 260 2473 2444 8 260 2473 1897 43 734 2473 3072 92 741 2539 2079 87 260 2539 3572 50 76 2539 2673 10 208 3122 1714 23 260 3122 2407 88 538 3122 1287 36 790 3854 2473 94 260 3854 1713 59 614 4084 4429 11 260 4084 268 35 476 4157 4084 65 260 4157 371 67 672 4157 1360 7 112 4429 4781 80 260 4429 2761 59 576 4429 149 29 720 303 1918 48 689 303 4081 42 166 875 1113 57 689 875 1763 79 739 875 851 4 80 1113 1712 3 689 1113 1881 88 142 1712 4661 19 689 1712 3316 96 383 1712 4570 26 291 1918 3053 31 689 1918 3398 76 525 1918 2224 47 701 2086 2210 84 689 2086 1090 3 821 2210 3900 67 689 2210 2756 23 483 3053 2086 28 689 3053 535 27 268 3053 2036 38 319 3900 875 17 689 3900 4666 71 689 3900 2354 19 587 3900 4205 41 235 304 3259 69 914 304 3667 62 7 748 2945 52 914 748 4215 99 428 1854 4503 66 914 1854 3830 17 914 1854 1196 20 840 2004 3109 21 914 2004 4102 24 666 2004 707 43 508 2215 2449 42 914 2215 4391 8 61 2215 2673 6 585 2449 4623 42 914 2449 4376 4 845 2945 1854 1 914 2945 223 35 158 2945 3691 48 140 2946 2004 58 914 2946 1158 76 104 3109 2215 81 914 3109 180 47 601 3109 1092 99 866 3259 4381 9 914 3259 3186 93 305 3830 2946 50 914 3830 1838 11 623 3830 3092 56 794 4381 748 10 914 4381 4003 41 552 4381 1142 6 89 305 3604 41 83 305 3154 70 608 305 4420 49 335 977 2716 44 83 977 4317 37 332 977 1751 59 519 1301 2099 6 83 1301 2396 20 237 1301 1038 7 335 1579 977 83 83 1579 3126 76 828 1579 1725 39 615 1600 2595 68 83 1600 2892 6 626 1705 4949 22 83 1705 2695 57 992 2008 1579 77 83 2008 3396 18 381 2099 1600 86 83 2099 4583 73 83 2099 4550 7 360 2116 1705 100 83 2116 4515 68 113 2595 2008 87 83 2595 4942 98 83 2595 1661 81 209 2716 3382 10 83 2716 2135 51 24 2716 3199 88 376 3382 2116 46 83 3382 234 55 682 3382 1952 56 560 3604 1301 28 83 3604 4268 100 86 306 2514 96 256 306 3235 33 909 306 3932 57 807 758 1836 23 256 758 1663 18 563 1440 1863 11 256 1440 851 84 577 1613 1440 42 256 1613 3004 100 909 1836 1613 28 256 1836 1769 34 983 1863 4648 71 256 1863 4994 94 256 1863 3514 81 534 2431 758 96 256 2431 3247 53 486 2431 2667 37 759 2514 2431 25 256 2514 3104 95 216 307 2601 31 52 307 233 26 813 1377 4976 50 52 1377 2233 73 52 1377 99 81 813 1553 4434 15 52 1553 2430 64 214 1553 1069 4 931 1804 1377 44 52 1804 3311 35 109 2233 3520 56 52 2233 3810 90 575 2601 3282 39 52 2601 196 47 19 2601 172 63 728 3282 4489 64 52 3282 3781 44 149 3282 666 54 272 3520 1553 57 52 3520 2624 21 599 4434 4796 71 52 4434 3458 68 821 4489 1804 55 52 4489 302 19 99 308 3598 98 194 308 291 76 609 634 4989 6 194 634 2102 87 194 634 647 62 590 1136 4742 13 194 1136 3880 16 148 2102 1136 38 194 2102 676 66 202 2139 634 70 194 2139 3687 72 835 2139 1756 80 975 3598 3783 15 194 3598 4699 66 929 3598 4647 78 352 3783 2139 93 194 3783 854 82 177 309 4284 96 1290 309 1790 26 78 309 4580 83 456 508 4579 53 1290 508 3170 90 647 508 1557 23 595 1034 508 82 1290 1034 4697 45 217 1034 4837 42 666 1597 2552 78 1290 1597 4016 53 244 1597 3370 10 315 2552 1034 100 1290 2552 418 47 331 2552 2025 65 964 4263 1597 74 1290 4263 4654 54 1290 4263 2169 13 187 4263 3316 11 874 4284 4426 55 1290 4284 2774 57 544 4426 4263 24 1290 4426 1293 29 415 4426 1231 66 85 310 1274 58 473 310 3545 6 767 825 2466 32 473 825 4941 48 265 1274 825 33 473 1274 4763 28 473 1274 2298 44 401 1274 1681 41 524 1883 2879 51 473 1883 635 42 711 1883 1526 69 654 1998 1883 91 473 1998 749 45 538 1998 3760 68 216 2268 1998 55 473 2268 3547 20 277 2466 4025 94 473 2466 4362 72 981 2466 220 96 188 2879 4508 60 473 2879 3287 44 41 4025 2268 9 473 4025 4039 67 250 311 3938 42 717 311 4002 62 283 311 2995 10 540 662 4979 3 717 662 128 9 966 662 1194 15 390 862 3934 57 717 862 4886 60 717 862 4811 8 195 862 2920 44 931 1781 662 5 717 1781 22 74 477 2439 4156 91 717 2439 1332 37 601 3934 2439 62 717 3934 583 4 760 3938 4145 80 717 3938 3536 90 729 4145 862 72 717 4145 1672 33 660 4145 3177 16 650 4156 1781 53 717 4156 4023 21 970 312 2840 34 163 312 3786 53 525 1341 3779 90 163 1341 2288 53 930 1990 2421 13 163 1990 2998 81 514 1990 4607 31 832 2394 1341 87 163 2394 2059 84 6 2421 4087 76 163 2421 4408 62 999 2421 2322 72 504 2840 1990 78 163 2840 2343 98 312 2840 1542 84 861 3779 4742 17 163 3779 4969 64 163 3779 4486 28 659 4087 2394 26 163 4087 4510 80 803 313 2503 6 728 313 3690 20 189 313 1243 92 605 611 2821 59 728 611 3971 27 921 710 4428 55 728 710 3442 38 832 1542 611 70 728 1542 53 20 532 1542 2111 35 975 2279 3462 100 728 2279 1263 50 987 2503 710 33 728 2503 2985 76 116 2503 4920 11 559 2821 4584 71 728 2821 2279 70 728 2821 1743 3 717 2821 989 73 987 3462 4682 75 728 3462 2639 86 749 4428 1542 64 728 4428 4531 98 943 4428 524 83 352 314 3512 17 756 314 3235 31 964 573 3494 96 756 573 174 98 874 573 2010 69 162 916 2249 97 756 916 4741 84 756 916 3010 47 665 1186 916 27 756 1186 1633 22 113 1186 2455 42 901 2249 573 63 756 2249 850 27 984 2249 4565 5 158 3494 4691 73 756 3494 1579 36 602 3512 1186 57 756 3512 1151 59 700 315 2082 46 353 315 551 35 417 513 3567 2 353 513 2390 56 385 513 3148 92 913 1419 2815 65 353 1419 391 3 985 1419 3826 83 59 1536 3058 65 353 1536 2849 11 705 1720 3837 40 353 1720 1864 82 712 1720 3918 29 187 1967 4890 72 353 1967 1720 64 353 1967 2487 100 974 1967 283 18 549 2082 513 25 353 2082 4962 57 353 2082 1971 96 248 2815 4541 61 353 2815 1583 42 790 2815 1217 1 616 3058 3957 98 353 3058 3856 54 525 3058 1256 72 199 3567 4283 80 353 3567 1032 7 89 3567 265 90 24 3837 1536 32 353 3837 390 81 253 3957 1419 43 353 3957 4438 37 821 4109 1967 25 353 4109 1313 100 908 4109 1827 63 364 4283 4109 3 353 4283 2576 67 857 4283 3397 83 26 316 1009 10 294 316 4747 11 372 316 4770 1 521 894 4750 99 294 894 4937 76 294 894 3222 34 986 1009 2909 96 294 1009 950 7 966 1009 3138 43 370 1248 2170 62 294 1248 3302 86 374 2170 894 95 294 2170 912 58 45 2170 2088 8 285 2909 1248 99 294 2909 3557 66 346 2909 4505 73 677 317 2932 2 316 317 4149 14 922 317 1570 29 687 546 4690 65 316 546 3229 76 316 546 1214 76 552 546 3183 18 178 2932 3200 43 316 2932 1767 30 377 2932 2621 3 806 3200 3863 45 316 3200 762 43 90 3229 4040 76 316 3229 1000 77 708 3229 838 14 104 3746 4877 91 316 3746 4554 18 301 3863 546 25 316 3863 2356 54 743 3863 2706 40 849 4040 3746 22 316 4040 1090 100 499 4040 3554 25 519 318 557 8 213 318 38 24 281 318 592 18 956 523 4645 18 213 523 1358 30 199 523 3522 28 656 549 911 35 213 549 1511 12 188 549 392 49 754 557 3388 99 213 557 2800 52 857 557 451 78 514 911 523 39 213 911 3427 63 474 1528 549 48 213 1528 4888 81 213 1528 4545 87 389 1528 4236 35 158 1761 1528 20 213 1761 2539 28 290 1761 673 53 30 2596 1761 24 213 2596 2419 82 245 3388 2596 4 213 3388 1882 47 939 3388 2597 63 229 319 2630 31 698 319 3985 49 852 319 630 24 614 650 3004 73 698 650 2592 7 388 842 2935 26 698 842 1684 92 795 1917 650 87 698 1917 1665 32 331 2005 3741 26 698 2005 1032 58 107 2005 34 85 332 2630 3721 74 698 2630 4926 77 38 2630 2382 33 330 2697 1917 35 698 2697 4537 73 654 2697 3595 99 804 2935 4527 30 698 2935 2697 23 698 2935 3675 59 554 3004 4692 26 698 3004 3735 44 711 3721 2005 98 698 3721 1681 53 98 3721 760 77 855 3741 842 8 698 3741 2342 96 330 3741 1771 35 840 320 506 89 407 320 3938 40 274 506 1537 70 407 506 2372 54 112 1258 4686 78 407 1258 1994 78 713 1258 1362 78 584 1328 3884 82 407 1328 485 28 881 1328 1116 53 368 1537 2643 42 407 1537 2351 80 255 1846 1258 22 407 1846 2945 17 832 1846 4995 42 739 2643 1328 46 407 2643 3989 87 391 2643 664 51 64 3074 3926 47 407 3074 209 22 7 3884 3074 35 407 3884 1684 81 22 3884 1064 91 886 3926 1846 47 407 3926 4755 13 407 3926 2784 32 609 321 897 23 416 321 72 37 180 321 304 75 496 694 2238 44 416 694 3970 75 160 694 513 88 666 897 1697 67 416 897 1198 31 445 1697 2632 23 416 1697 4862 67 416 1697 3054 32 67 2238 2410 26 416 2238 176 60 112 2410 3447 56 416 2410 1269 29 484 2632 694 87 416 2632 196 38 787 2632 881 97 925 3447 4904 92 416 3447 3988 57 62 322 3114 82 385 322 2243 47 600 1074 1685 29 385 1074 2136 42 459 1234 2101 9 385 1234 598 65 4 1242 1074 21 385 1242 502 58 496 1242 4074 6 354 1685 1234 44 385 1685 4738 17 80 2101 4848 77 385 2101 4014 11 245 3114 1242 97 385 3114 4716 12 385 3114 1038 45 934 323 4448 86 532 323 1422 24 805 323 812 93 190 764 1497 35 532 764 4956 97 532 764 4485 68 695 1212 4065 27 532 1212 2622 72 528 1212 3103 46 731 1497 1212 4 532 1497 3735 64 672 2950 764 52 532 2950 1663 83 990 2950 3947 4 781 4065 4614 21 532 4065 1251 67 669 4065 2299 71 239 4448 2950 55 532 4448 1896 59 900 324 2211 67 277 324 2739 81 52 324 3090 88 930 1014 4798 43 277 1014 4599 80 662 1489 2341 86 277 1489 1749 24 774 1489 357 39 312 2211 4315 5 277 2211 4547 70 277 2211 3152 93 287 2317 2326 25 277 2317 1398 17 276 2317 4477 13 115 2326 1014 39 277 2326 4617 43 616 2341 2317 36 277 2341 1154 6 925 2341 3362 43 420 4315 4318 18 277 4315 4312 14 999 4318 1489 1 277 4318 2545 27 569 325 1852 76 593 325 67 36 110 325 3376 24 796 632 3748 67 593 632 1434 82 28 1852 3522 29 593 1852 1785 71 515 1852 623 16 315 2981 4571 87 593 2981 3299 2 446 3522 632 47 593 3522 2607 4 870 3522 733 40 61 3711 4924 13 593 3711 2981 29 593 3711 4334 18 784 3711 2665 62 549 3748 3711 72 593 3748 3847 52 508 326 3499 48 972 326 828 83 444 326 1565 45 633 544 3759 38 972 544 4414 86 819 544 44 2 559 1349 3910 33 972 1349 826 71 672 1349 571 78 533 2393 4140 5 972 2393 1290 10 898 3325 4533 89 972 3325 2393 70 972 3325 1415 62 623 3499 544 64 972 3499 3808 87 162 3759 1349 10 972 3759 4467 16 669 3910 3325 2 972 3910 1411 2 276 3910 3142 36 368 3967 4914 84 972 3967 1466 72 853 4140 3967 53 972 4140 1531 9 374 4140 4187 76 557 327 3624 7 694 327 3428 100 248 327 4988 82 432 1225 3051 10 694 1225 1833 56 103 1225 4619 22 513 2382 4914 21 694 2382 4638 19 919 2382 153 60 938 2405 1225 61 694 2405 3607 29 619 3051 2382 27 694 3051 3850 14 767 3624 4941 20 694 3624 4115 38 694 3624 3527 78 6 4115 2405 65 694 4115 3431 36 331 4115 4640 92 745 328 3059 99 289 328 1350 64 434 328 1797 81 732 732 4137 99 289 732 3099 22 537 899 1187 54 289 899 1694 42 95 1187 1721 66 289 1187 4875 65 289 1187 154 31 200 1721 732 61 289 1721 1890 75 344 2942 899 46 289 2942 2631 80 929 2942 3459 51 51 3059 3206 64 289 3059 108 6 2 3059 3323 16 604 3206 2942 7 289 3206 2439 76 226 3206 587 49 295 4137 4928 10 289 4137 541 6 759 329 577 27 1387 329 4573 56 216 329 3796 76 154 577 3179 84 1387 577 574 71 178 577 2552 81 963 872 4722 79 1387 872 4538 22 211 872 1711 70 293 1318 2767 48 1387 1318 98 9 291 1318 4562 75 778 2376 4031 8 1387 2376 4387 79 476 2376 2672 57 470 2480 1318 77 1387 2480 2223 85 804 2480 33 10 309 2767 872 99 1387 2767 1933 19 786 3179 2376 9 1387 3179 3356 96 679 3179 4931 96 359 4031 2480 3 1387 4031 4709 99 1387 4031 3192 96 340 4031 4681 77 176 330 2458 54 296 330 52 76 175 561 4097 44 296 561 4512 10 291 1538 3446 61 296 1538 3224 7 623 1686 1771 96 296 1686 1524 85 245 1771 3015 42 296 1771 4939 33 282 1771 4602 25 106 2458 1686 86 296 2458 2586 97 749 3015 3983 55 296 3015 2116 42 99 3035 4708 90 296 3035 4551 60 296 3035 2226 43 558 3035 2693 9 380 3446 3035 73 296 3446 662 5 142 3446 2923 2 548 3983 4438 54 296 3983 957 59 935 4097 1538 46 296 4097 2983 16 902 4438 561 71 296 4438 168 22 513 331 2050 2 922 331 526 86 618 782 1566 52 922 782 4934 50 922 782 2977 79 913 1007 1921 84 922 1007 3597 54 2 1007 1882 22 503 1566 3903 13 922 1566 3891 37 393 1566 281 49 282 1921 3944 99 922 1921 4210 94 754 2050 3174 99 922 2050 1556 40 920 3174 1007 15 922 3174 1858 23 496 3903 4528 55 922 3903 808 41 810 3944 782 11 922 3944 1455 88 223 332 3334 32 184 332 2538 76 459 593 4523 85 184 593 2521 58 751 593 3038 19 994 1319 4579 64 184 1319 2719 17 184 1319 2068 66 55 2719 593 81 184 2719 3621 32 477 3334 4346 40 184 3334 3013 34 696 4346 1319 54 184 4346 3885 28 530 333 3356 73 535 333 1613 95 612 333 3147 1 57 636 4258 78 535 636 87 67 240 636 3801 11 838 2983 3573 93 535 2983 4335 16 967 3021 3082 55 535 3021 141 32 314 3021 3181 1 798 3082 636 45 535 3082 99 16 8 3082 1421 99 147 3356 3021 100 535 3356 4977 32 535 3356 2051 97 161 3356 4564 18 209 3573 4787 22 535 3573 4243 67 86 3573 4711 27 236 4073 2983 87 535 4073 2807 62 936 4177 4073 2 535 4177 4478 27 628 4177 1560 55 760 4258 4177 41 535 4258 4224 47 709 334 4245 65 1428 334 1409 17 172 334 3886 20 787 1254 3413 28 1428 1254 4214 42 766 1254 1510 81 578 2173 2905 36 1428 2173 4683 38 1428 2173 3880 15 700 2173 1950 52 553 2723 2173 16 1428 2723 4186 91 519 2723 2895 94 389 2905 1254 86 1428 2905 1232 41 78 3413 4665 84 1428 3413 2056 25 383 4245 2723 59 1428 4245 4979 18 713 4245 980 64 116 335 1894 66 384 335 994 1 620 335 1036 10 46 1042 4625 44 384 1042 43 72 509 1042 2674 94 140 1224 4132 1 384 1224 3426 94 704 1317 2628 95 384 1317 4730 54 384 1317 2514 69 585 1638 1317 31 384 1638 3243 18 241 1894 1224 7 384 1894 1256 19 95 2628 3150 27 384 2628 1951 74 359 2628 4899 78 53 3150 1042 46 384 3150 2027 74 613 4132 1638 42 384 4132 1642 58 242 4132 1842 43 687 336 1780 12 271 336 1340 2 373 336 2455 72 205 588 1486 97 271 588 467 7 689 588 871 42 439 1486 3181 28 271 1486 2066 64 521 1486 2055 87 831 1780 2109 3 271 1780 2933 75 787 1780 4038 33 17 2109 2528 59 271 2109 4483 58 727 2109 4251 71 842 2528 588 86 271 2528 3536 27 734 2528 1360 91 71 3181 4584 33 271 3181 4877 4 271 3181 4349 76 23 337 4218 39 74 337 2481 16 863 2093 3478 34 74 2093 1390 38 774 2392 4313 64 74 2392 4705 77 74 2392 4295 64 603 3375 2093 26 74 3375 4381 36 119 3478 4403 36 74 3478 2687 15 772 3478 1908 35 156 4218 3375 49 74 4218 55 91 325 4313 4924 34 74 4313 57 21 306 4403 2392 58 74 4403 1117 66 944 338 2835 73 427 338 3938 40 145 597 3750 67 427 597 4775 31 295 780 2457 23 427 780 1126 1 394 2457 597 94 427 2457 4727 40 427 2457 1625 95 648 2803 4003 77 427 2803 906 32 725 2835 2803 77 427 2835 4202 50 173 3486 780 53 427 3486 2971 86 923 3486 2496 36 560 3602 4414 59 427 3602 4477 66 540 3602 1126 77 425 3750 3602 54 427 3750 2191 18 606 4003 3486 56 427 4003 2871 75 511 4003 797 36 817 4414 4760 7 427 4414 1343 27 181 4414 4943 71 452 339 1913 81 400 339 4296 70 640 339 2699 80 355 1912 4683 58 400 1912 4204 51 877 1913 2114 62 400 1913 3685 50 500 2114 3450 95 400 2114 505 46 796 2114 943 68 322 2347 4576 94 400 2347 3587 30 400 2347 1270 6 366 2347 134 53 42 3450 2347 79 400 3450 3400 52 860 3587 3894 51 400 3587 1259 96 916 3894 1912 87 400 3894 887 53 554 340 1127 85 584 340 3969 66 139 775 2270 94 584 775 223 49 86 775 50 29 59 1127 1626 96 584 1127 2995 95 549 1127 4541 14 919 1207 3255 70 584 1207 4321 75 984 1207 2065 88 110 1431 2248 39 584 1431 3103 38 552 1431 4573 45 739 1626 1431 94 584 1626 4080 17 320 1626 3420 2 511 1861 2015 7 584 1861 3150 98 355 2015 775 2 584 2015 4682 45 584 2015 737 91 604 2248 1207 45 584 2248 510 28 672 2248 2943 91 29 2270 4776 29 584 2270 2419 85 292 2270 4192 78 467 3255 1861 41 584 3255 2991 6 382 3255 3947 75 467 341 1514 65 411 341 4750 1 753 341 2443 46 500 1514 3237 93 411 1514 4714 73 925 1550 3904 73 411 1550 4991 72 411 1550 4587 79 710 1550 721 59 75 3002 4290 60 411 3002 4409 45 305 3002 3867 2 280 3237 3002 51 411 3237 1915 80 501 3237 2422 67 882 3904 4810 49 411 3904 4510 37 378 4290 1550 91 411 4290 4818 83 666 342 1436 72 656 342 1545 87 221 342 3166 53 130 697 3338 2 656 697 4442 12 978 697 4362 3 13 1436 1855 90 656 1436 3191 76 715 1855 697 28 656 1855 4616 75 656 1855 1040 51 165 1855 1810 96 554 2056 3256 36 656 2056 152 91 769 3256 4765 82 656 3256 4453 6 654 3338 2056 97 656 3338 4626 84 939 343 2623 19 453 343 4213 58 971 343 623 24 867 1164 4052 71 453 1164 1678 61 143 1164 4802 68 194 1809 1164 88 453 1809 1242 88 568 1809 3193 90 453 1929 1809 52 453 1929 4534 97 864 1929 4495 39 543 2623 1929 35 453 2623 4574 65 453 2623 4652 75 525 2623 4789 55 144 3655 4277 20 453 3655 813 79 914 3655 2676 41 446 4052 4201 63 453 4052 1747 5 345 4052 2436 10 992 4201 3655 100 453 4201 2178 22 326 4201 3974 49 987 4277 4614 97 453 4277 1703 82 731 4277 1775 91 733 344 1909 59 327 344 154 60 81 886 4956 56 327 886 4887 88 327 886 4579 2 740 1454 2014 80 327 1454 4180 90 145 1800 1454 15 327 1800 2170 16 400 1800 1536 41 214 1909 4466 87 327 1909 2110 51 634 2014 3950 46 327 2014 3710 95 794 3516 886 81 327 3516 396 55 647 3516 442 13 179 3829 3516 94 327 3829 26 11 392 3829 657 2 243 3950 3829 18 327 3950 2647 33 444 3950 4433 54 640 4466 1800 28 327 4466 4859 85 999 4466 1114 45 111 345 1267 97 729 345 4640 100 944 925 4794 73 729 925 873 76 332 1267 2106 24 729 1267 3276 64 342 1267 29 55 837 1365 2558 16 729 1365 825 30 766 1541 925 29 729 1541 4789 73 729 1541 2175 8 2 1541 1142 85 78 2106 3254 67 729 2106 1665 21 629 2106 2048 5 810 2558 1541 79 729 2558 3766 17 736 2558 4867 67 154 3254 1365 54 729 3254 3099 69 909 346 4326 36 265 346 3471 100 922 1066 4999 8 265 1066 4918 88 683 1942 2724 6 265 1942 926 91 884 2438 3504 97 265 2438 2630 70 265 2438 2604 62 268 2724 2438 35 265 2724 2647 35 315 2856 3859 54 265 2856 4898 29 265 2856 2881 13 422 2856 4721 43 83 3504 2856 22 265 3504 784 12 803 3504 1962 30 348 3859 1066 24 265 3859 2158 45 905 3859 4927 16 661 4326 1942 70 265 4326 4244 8 808 4326 2038 24 858 347 691 54 663 347 2933 24 303 347 4336 81 314 691 1672 34 663 691 1848 68 187 691 154 74 302 760 1562 21 663 760 2586 89 554 1434 3363 49 663 1434 1776 53 712 1434 4747 69 868 1562 4700 56 663 1562 4952 18 663 1562 3625 44 893 1562 4263 48 386 1672 3617 17 663 1672 2691 93 480 1672 1448 45 264 1732 1434 47 663 1732 594 55 835 3363 3537 94 663 3363 551 38 342 3363 183 57 976 3537 760 7 663 3537 12 30 98 3537 1729 80 390 3617 1732 98 663 3617 1764 8 227 348 687 78 968 348 219 95 898 348 712 37 10 687 3709 83 968 687 1827 14 892 687 2231 48 110 959 3235 49 968 959 3231 77 511 959 1684 68 673 962 3429 23 968 962 2368 85 75 1119 1415 37 968 1119 2891 57 38 1119 1208 40 716 1143 959 2 968 1143 3383 98 980 1143 1405 16 163 1415 3995 43 968 1415 4995 97 968 1415 4472 97 184 2042 1119 97 968 2042 4793 21 968 2042 1545 33 33 2042 625 95 873 3235 962 100 968 3235 4404 31 524 3429 4557 29 968 3429 2178 50 534 3429 557 42 69 3709 3822 35 968 3709 3257 49 412 3822 2042 19 968 3822 1842 4 577 3822 3432 62 394 3995 1143 71 968 3995 4684 67 131 3995 1438 98 282 349 3192 93 246 349 36 41 516 2221 2887 39 246 2221 4735 76 89 2221 407 89 118 2703 4626 91 246 2703 4098 32 976 2703 50 2 153 2887 3685 58 246 2887 1954 53 46 2887 528 20 419 3142 2221 57 246 3142 4629 29 246 3142 3790 57 33 3142 3968 11 510 3192 3142 54 246 3192 3793 94 589 3685 2703 7 246 3685 3728 44 477 350 1737 62 250 350 2076 56 883 350 966 24 26 1035 2557 26 250 1035 4554 25 250 1035 1108 2 883 1737 1964 85 250 1737 779 91 833 1737 1841 41 308 1964 3543 62 250 1964 1374 60 311 1964 3415 2 629 2247 2676 42 250 2247 1325 8 144 2247 3232 5 720 2541 3673 78 250 2541 4151 6 181 2557 4963 82 250 2557 4267 36 543 2676 3101 10 250 2676 15 2 160 2676 518 33 386 3101 1035 10 250 3101 512 39 329 3273 2247 78 250 3273 493 5 180 3543 2541 98 250 3543 2081 57 405 3673 3273 29 250 3673 4491 49 643 3673 944 93 15 351 582 76 144 351 4378 70 566 351 4262 3 876 582 2435 31 144 582 1907 81 199 635 1356 87 144 635 3247 60 524 635 1975 61 361 651 3173 25 144 651 3837 63 86 651 4015 99 879 1356 3480 41 144 1356 486 33 72 1356 4674 61 759 2435 651 2 144 2435 369 7 48 2435 3642 15 419 2698 635 45 144 2698 4788 70 144 2698 2327 90 531 2698 101 22 433 3173 2698 30 144 3173 3110 12 267 3173 4298 32 556 3480 4805 10 144 3480 367 31 984 352 2223 94 189 352 2006 27 841 709 4600 33 189 709 2171 47 803 1976 4088 38 189 1976 1574 86 507 1976 1270 92 74 2223 4199 14 189 2223 981 85 768 2223 1609 95 391 2289 4840 27 189 2289 709 35 189 2289 1902 25 711 2289 2273 30 483 4088 2289 65 189 4088 1374 99 919 4088 4691 99 632 4199 1976 92 189 4199 3882 59 591 4199 4969 72 520 353 835 27 713 353 3652 25 882 835 4362 48 713 835 4127 96 355 898 1343 79 713 898 4542 56 685 898 4661 27 236 1343 4401 2 713 1343 2007 2 236 4362 898 6 713 4362 4069 94 174 4401 4601 22 713 4401 4637 11 713 4401 2825 34 995 354 1646 96 317 354 789 37 471 354 2060 48 577 792 1526 67 317 792 3412 31 164 792 1117 84 929 850 792 95 317 850 1153 39 210 1526 4513 9 317 1526 1330 75 146 1526 495 47 591 1646 2600 58 317 1646 255 68 1000 1646 2947 86 399 2600 2866 74 317 2600 1630 27 244 2600 2420 54 978 2866 3898 90 317 2866 4397 13 19 2866 4966 88 133 3898 850 17 317 3898 4570 10 317 3898 3033 50 386 3898 2722 58 893 355 1306 24 439 355 2183 51 909 355 4811 95 813 531 2874 21 439 531 979 65 661 1306 3557 63 439 1306 4318 58 576 1306 535 93 487 1355 2618 92 439 1355 4272 20 479 1355 3155 93 774 2618 4416 57 439 2618 4807 98 439 2618 3151 51 650 2874 1355 75 439 2874 4171 99 810 2874 2002 99 899 3557 531 97 439 3557 4761 66 227 3557 4109 4 285 4416 4542 6 439 4416 3569 64 599 4416 4118 22 94 356 936 9 404 356 1174 64 848 356 358 99 503 936 1850 20 404 936 4609 55 512 936 234 88 914 1390 3713 96 404 1390 3664 4 208 1390 1957 75 354 1850 3042 33 404 1850 1174 77 851 3042 1390 53 404 3042 4214 82 250 3042 590 14 843 3713 3800 73 404 3713 4824 66 404 3713 213 25 740 3800 4848 83 404 3800 2918 42 283 3800 3456 69 761 357 1655 97 937 357 1902 1 81 357 93 86 451 737 836 7 937 737 3022 23 188 836 1630 63 937 836 2642 78 179 836 147 79 291 1281 3754 11 937 1281 4867 27 51 1281 638 79 456 1339 4517 58 937 1339 3140 80 960 1339 1232 19 876 1630 4061 80 937 1630 4978 56 992 1655 1281 69 937 1655 4634 96 937 1655 431 3 729 1802 737 99 937 1802 2842 1 440 3754 1802 51 937 3754 3111 28 89 3754 1084 68 261 4061 1339 25 937 4061 3273 98 639 4061 2800 100 856 358 1417 35 218 358 3667 46 531 358 4882 28 242 1417 4210 84 218 1417 4629 84 218 1417 2373 83 493 3394 3979 55 218 3394 445 87 258 3394 858 100 218 3632 3866 89 218 3632 3505 57 936 3632 3229 79 246 3866 4053 8 218 3866 733 44 916 3866 202 85 209 3979 4597 21 218 3979 903 56 765 3979 98 56 284 4053 3394 17 218 4053 3418 71 632 4053 4065 45 682 4210 4241 15 218 4210 1320 80 792 4210 1040 99 623 4241 3632 70 218 4241 2023 61 280 4241 1910 22 629 359 2797 95 803 359 4335 44 982 359 3080 39 943 1748 4951 4 803 1748 1484 70 437 2041 4494 80 803 2041 4194 12 856 2797 3969 16 803 2797 1085 77 51 2797 1411 60 464 3483 4898 86 803 3483 1748 85 803 3483 163 26 741 3483 3024 49 923 3969 2041 25 803 3969 4263 52 616 4494 3483 14 803 4494 4326 5 348 4494 784 43 767 360 2658 72 333 360 1900 68 122 1103 1594 46 333 1103 3560 52 338 1594 4700 10 333 1594 3387 75 671 1594 4390 98 607 2266 4913 23 333 2266 1103 47 333 2266 761 65 210 2266 3704 58 45 2658 3336 72 333 2658 2459 87 762 3183 2266 76 333 3183 1421 44 18 3183 4819 68 190 3336 3183 26 333 3336 1437 37 351 3336 1855 19 841 361 1231 38 215 361 1161 5 403 361 914 77 715 534 3790 59 215 534 1441 80 982 534 2904 14 450 1231 2212 65 215 1231 4795 67 215 1231 3495 71 907 1231 2986 28 637 1523 534 23 215 1523 2883 25 477 1523 2072 55 582 1605 1523 18 215 1605 2349 27 668 1605 4272 63 150 2212 3571 34 215 2212 673 64 334 3571 1605 40 215 3571 3523 98 947 3790 4855 37 215 3790 4355 14 168 362 4209 13 217 362 2727 71 289 362 4696 41 759 1096 3340 48 217 1096 217 71 959 1096 1382 41 618 1531 4815 58 217 1531 2506 70 298 1531 1856 83 878 1758 1096 79 217 1758 1076 68 36 3340 4221 86 217 3340 2707 45 557 3340 2677 37 947 4209 1758 95 217 4209 2264 43 139 4209 4419 50 357 4221 1531 84 217 4221 4783 49 217 4221 2417 37 5 363 1448 51 757 363 4112 33 623 363 3321 45 463 538 3929 43 757 538 2771 89 878 538 1054 8 50 705 3295 26 757 705 4065 22 176 1448 2408 73 757 1448 214 84 92 1448 2588 24 76 2028 2422 50 757 2028 4978 13 76 2408 3459 2 757 2408 1788 68 923 2408 523 83 865 2422 4882 59 757 2422 2458 47 193 2864 538 3 757 2864 2557 12 713 3295 2864 96 757 3295 1448 22 113 3295 2742 59 596 3459 705 72 757 3459 4961 73 757 3459 859 52 961 3459 4099 91 703 3929 2028 73 757 3929 911 72 806 3929 2667 13 410 364 644 39 437 364 2131 9 511 571 965 64 437 571 3548 38 123 571 1116 46 876 644 1150 100 437 644 1649 9 968 644 4205 6 131 700 4548 14 437 700 1122 68 527 965 4535 95 437 965 1070 5 437 965 4662 37 437 965 2299 44 309 1070 3395 49 437 1070 908 76 863 1070 3670 2 892 1150 1882 21 437 1150 1053 90 551 1150 2291 26 811 1423 3104 39 437 1423 4854 94 54 1423 3225 51 338 1882 1423 96 437 1882 2076 54 585 2854 571 2 437 2854 4848 70 400 2854 362 47 84 2991 4028 84 437 2991 978 13 244 3104 2854 58 437 3104 2588 91 113 3104 2082 38 520 3353 700 26 437 3353 312 92 730 3395 2991 92 437 3395 3342 67 329 4028 3353 22 437 4028 4421 61 147 365 3103 98 888 365 3950 98 890 365 1103 7 508 1481 1495 46 888 1481 1367 76 915 1495 3444 86 888 1495 4025 68 953 3103 3390 82 888 3103 2339 49 21 3390 4324 37 888 3390 4454 45 298 3390 4584 80 487 3444 4886 53 888 3444 432 1 30 3444 3725 6 55 3869 1481 95 888 3869 4965 49 888 3869 1677 10 874 4324 3869 29 888 4324 3583 41 943 4324 4265 47 90 366 2997 75 318 366 1927 56 281 686 1651 51 318 686 4713 47 135 1556 4746 63 318 1556 3180 51 318 1556 299 17 457 1556 2877 30 828 1651 4920 8 318 1651 4019 17 187 1651 4865 61 946 2481 1556 22 318 2481 2225 71 410 2481 4087 1 85 2997 2481 65 318 2997 4506 16 328 3120 4171 55 318 3120 4564 37 383 3120 590 30 97 3180 3871 91 318 3180 2875 55 984 3871 3120 7 318 3871 2367 18 907 3871 2532 80 645 4171 686 75 318 4171 3886 55 866 4171 1118 64 281 367 1826 39 104 367 3744 23 483 776 3773 87 104 776 2619 65 685 776 4924 42 643 1172 2251 28 104 1172 2428 87 980 1172 1267 31 982 1387 776 39 104 1387 1421 34 848 1387 1968 77 464 1826 2018 9 104 1826 2752 57 197 2018 1172 78 104 2018 4940 6 947 2251 3014 80 104 2251 3482 35 265 2269 2456 96 104 2269 1544 47 328 2456 2953 29 104 2456 4721 61 104 2456 2198 24 488 2953 4861 80 104 2953 4838 29 104 2953 1373 26 677 2953 4629 85 330 3014 1387 86 104 3014 1078 76 245 3126 2269 58 104 3126 327 61 788 3126 815 58 920 3773 3126 30 104 3773 4657 2 370 3773 3786 62 996 368 1406 9 358 368 3565 66 772 368 4802 42 875 1406 1586 18 358 1406 3908 49 466 1406 1413 98 463 1586 2565 64 358 1586 482 19 240 1586 498 70 99 1985 4729 68 358 1985 445 46 580 2338 4837 3 358 2338 2582 33 358 2338 3834 73 440 2565 2338 74 358 2565 133 96 590 2582 3396 58 358 2582 2325 82 705 2582 4556 25 722 3396 1985 88 358 3396 4969 82 184 3396 1466 45 768 369 3470 22 451 369 198 40 175 594 4064 99 451 594 1830 10 335 1120 2377 14 451 1120 4833 51 632 1151 2496 83 451 1151 2864 67 385 1151 1037 72 764 1158 1151 29 451 1158 2829 95 653 1158 2619 55 133 1649 2718 73 451 1649 4672 88 451 1649 2267 59 944 2256 1158 62 451 2256 89 27 837 2256 3364 42 853 2377 1649 100 451 2377 3979 36 516 2377 268 78 111 2496 594 66 451 2496 2470 97 879 2496 2086 35 749 2718 2256 38 451 2718 2506 84 740 3222 4797 6 451 3222 1123 10 78 3222 2853 94 233 3470 4940 30 451 3470 1120 77 451 3470 1551 14 70 3470 512 86 703 4064 3222 93 451 4064 3363 66 404 370 840 14 451 370 852 52 705 840 3163 14 451 840 4131 79 369 991 4558 6 451 991 4982 57 451 991 2052 35 416 1783 991 46 451 1783 2864 17 212 2722 1783 81 451 2722 2794 38 154 2722 4072 5 625 3163 3793 95 451 3163 2466 70 314 3793 4379 32 451 3793 1937 84 88 4379 2722 30 451 4379 3459 63 842 371 3457 93 135 371 4349 35 867 371 1497 82 755 1058 2043 76 135 1058 4446 24 720 1058 2513 3 694 1230 1058 69 135 1230 3774 59 24 1230 912 17 496 1420 1465 21 135 1420 4132 41 844 1465 4436 95 135 1465 1444 38 142 2043 2302 23 135 2043 2736 5 348 2043 2263 5 484 2302 4581 41 135 2302 3351 28 403 3457 1420 48 135 3457 4144 3 724 3457 960 47 692 4436 1230 97 135 4436 4851 93 135 4436 42 41 474 4436 3792 15 605 372 3680 2 753 372 1770 68 642 372 580 22 486 778 2154 85 753 778 4587 54 904 2154 2675 92 753 2154 4600 7 906 2675 4380 75 753 2675 4977 29 512 2730 4981 32 753 2730 1120 1 739 3680 778 73 753 3680 4694 7 753 3680 2199 26 813 3972 2730 63 753 3972 3167 15 550 4380 3972 92 753 4380 711 39 934 4380 3980 93 803 373 3691 62 273 373 2713 16 458 373 1781 78 658 1050 4981 75 273 1050 2416 71 273 1050 4132 23 485 1050 503 93 862 1382 4911 30 273 1382 3533 6 312 1382 4485 13 774 1652 3787 90 273 1652 496 31 189 1652 2648 55 470 2013 3595 74 273 2013 4801 32 102 2416 1382 42 273 2416 1183 29 878 2416 333 95 329 3595 4125 76 273 3595 2259 54 631 3595 2764 80 775 3691 4014 61 273 3691 3660 41 346 3787 4349 88 273 3787 603 68 732 3787 4347 94 164 4014 2013 43 273 4014 4877 24 207 4125 1652 35 273 4125 4778 10 426 4349 1050 4 273 4349 394 16 55 374 1782 16 22 374 1534 99 734 374 2856 24 967 532 676 38 22 532 2702 78 957 676 4071 73 22 676 284 40 321 1782 3227 22 22 1782 1049 97 538 1904 4741 47 22 1904 532 63 22 1904 4079 43 604 2137 1904 9 22 2137 3482 36 212 2774 2137 17 22 2774 1186 50 72 2774 84 64 521 3227 3392 8 22 3227 3503 20 685 3227 242 48 593 3392 3708 84 22 3392 4490 28 831 3392 1008 95 344 3708 2774 21 22 3708 4830 39 813 3708 1607 65 468 4071 4987 97 22 4071 232 68 986 4071 842 78 510 375 510 90 284 375 3764 16 245 375 1704 61 616 510 3077 75 284 510 3005 44 606 510 1190 19 953 602 4077 52 284 602 3994 70 719 602 2434 59 451 927 4054 24 284 927 1722 38 849 927 3202 93 730 2060 2507 26 284 2060 4268 75 493 2060 754 37 324 2183 602 68 284 2183 1477 56 656 2183 851 76 298 2507 4733 92 284 2507 4529 30 284 2507 3338 27 946 2507 1004 55 184 3077 4310 98 284 3077 4731 6 175 4054 2060 63 284 4054 3894 90 271 4054 645 18 363 4077 927 53 284 4077 935 71 670 4077 2811 54 694 4310 2183 15 284 4310 3321 98 390 4310 619 45 829 376 2150 71 15 376 4556 24 657 376 4303 100 416 798 1004 73 15 798 640 30 195 824 1340 24 15 824 2399 81 663 1004 2913 62 15 1004 3267 2 303 1004 4201 17 122 1243 824 52 15 1243 255 4 9 1340 798 86 15 1340 760 97 401 1922 2572 86 15 1922 4962 22 15 1922 418 71 247 2150 1243 71 15 2150 3295 11 370 2572 4710 40 15 2572 2710 29 283 2572 863 100 923 2913 1922 38 15 2913 4582 74 833 2913 1635 100 245 377 4320 74 1020 377 4370 81 803 796 4169 9 1020 796 1283 7 797 796 3285 51 552 1065 3385 73 1020 1065 4467 80 927 1443 4983 11 1020 1443 3640 69 22 3385 796 71 1020 3385 3081 59 350 3385 272 25 451 4169 1443 5 1020 4169 2497 52 155 4169 3519 1 717 4320 1065 73 1020 4320 4544 33 1020 4320 574 70 242 4320 1573 41 81 378 1901 43 326 378 379 73 844 378 1798 5 597 924 1724 40 326 924 1445 99 159 924 2550 54 979 1724 3348 57 326 1724 3203 86 263 1724 1593 86 523 1901 3935 47 326 1901 3508 62 703 2010 2460 39 326 2010 4835 59 326 2010 4282 43 272 2460 3354 48 326 2460 3093 37 657 3348 4250 83 326 3348 819 43 875 3348 1573 67 99 3354 924 1 326 3354 1690 37 919 3354 4629 87 918 3935 2010 74 326 3935 3751 87 903 4250 4803 28 326 4250 2248 93 708 379 569 46 436 379 4819 47 463 379 807 67 459 569 2332 10 436 569 1716 54 219 1518 2886 52 436 1518 1011 60 125 1518 3261 1 54 1684 4236 88 436 1684 4964 36 70 2332 4373 9 436 2332 4675 37 436 2332 2709 39 668 2886 3704 17 436 2886 4248 20 305 2886 2146 50 360 3601 1518 33 436 3601 164 49 256 3601 4700 4 706 3704 4653 58 436 3704 2995 94 952 3704 4374 26 368 3714 3601 57 436 3714 2889 50 25 4236 3714 48 436 4236 2590 84 349 4373 1684 7 436 4373 32 57 435 4373 1333 76 814 380 2563 41 360 380 2761 12 159 677 3196 6 360 677 1448 14 906 1192 4120 26 360 1192 730 97 390 1577 677 83 360 1577 29 50 517 1577 4902 50 183 2563 1577 28 360 2563 3743 51 205 2563 3182 19 824 3196 1192 100 360 3196 4693 20 360 3196 4500 75 649 3196 389 86 557 4120 4564 33 360 4120 3762 83 638 4120 3526 20 516 381 4325 82 389 381 3303 1 726 2100 3923 15 389 2100 3153 77 210 2100 959 75 718 3073 2100 61 389 3073 4771 85 389 3073 1952 25 908 3536 4167 12 389 3536 1210 43 689 3603 3073 52 389 3603 330 46 128 3923 4609 83 389 3923 4181 92 5 4167 3603 72 389 4167 1300 80 989 4325 3536 76 389 4325 873 64 22 382 2344 42 949 382 1912 9 996 382 994 88 659 889 4544 2 949 889 4643 94 949 889 3987 39 907 909 2590 34 949 909 4455 23 760 1658 909 13 949 1658 1123 99 702 1658 3303 31 39 1680 1719 12 949 1680 562 55 605 1680 1692 54 181 1719 1778 89 949 1719 2586 39 629 1778 889 4 949 1778 632 6 406 2344 1658 21 949 2344 357 43 557 2344 719 13 451 2590 1680 62 949 2590 326 60 366 2590 3482 55 792 383 2979 74 311 383 625 71 780 383 968 98 679 1005 3137 40 311 1005 903 35 406 1255 4582 62 311 1255 1421 57 450 2352 3939 44 311 2352 2844 98 153 2483 4631 84 311 2483 2352 88 311 2483 584 27 242 2979 3032 79 311 2979 5000 1 649 2979 3402 49 609 3032 3215 10 311 3032 1105 78 387 3032 2354 99 989 3137 1255 19 311 3137 2328 96 917 3137 1037 92 964 3215 2483 39 311 3215 2723 38 435 3939 1005 17 311 3939 3280 45 30 3939 2025 72 89 384 3431 21 990 384 3698 23 489 384 4140 46 248 1278 3832 62 990 1278 1690 82 782 1422 4323 19 990 1422 295 78 266 1422 4784 4 556 3138 4830 52 990 3138 4968 30 990 3138 1076 34 499 3138 603 55 984 3147 3546 98 990 3147 3929 43 441 3147 4561 82 17 3431 3147 57 990 3431 2469 32 430 3431 2935 37 28 3546 3728 91 990 3546 2669 76 143 3728 1278 87 990 3728 4164 1 29 3832 1422 84 990 3832 2405 90 950 3832 1764 97 491 4323 3138 87 990 4323 2087 78 981 385 1279 41 75 385 869 38 962 1279 4333 93 75 1279 1742 10 258 2779 3290 6 75 2779 2393 77 90 2779 4930 98 427 3290 3917 52 75 3290 3154 71 582 3461 4497 96 75 3461 1103 23 462 3461 2757 57 487 3917 4451 26 75 3917 3797 88 584 3917 4912 47 69 4333 2779 14 75 4333 1628 17 850 4451 3461 54 75 4451 4780 71 75 4451 2610 67 223 4451 4718 84 469 4497 4610 5 75 4497 712 26 972 4497 3213 64 901 386 649 73 563 386 734 9 58 649 1711 35 563 649 561 46 39 1003 1492 73 563 1003 2423 68 824 1152 2578 12 563 1152 4780 98 563 1152 3704 71 976 1152 2249 74 261 1492 2526 38 563 1492 207 67 573 1492 3608 33 46 1711 1971 84 563 1711 796 72 404 1971 2959 59 563 1971 1230 17 351 2526 1152 5 563 2526 4873 74 629 2578 4556 46 563 2578 373 80 83 2578 75 66 408 2959 3178 40 563 2959 2915 65 878 3164 1003 100 563 3164 4282 17 857 3178 3164 82 563 3178 2449 88 546 387 2850 33 481 387 264 48 31 711 4510 57 481 711 2174 31 822 711 2141 39 462 1554 711 5 481 1554 898 22 394 1554 2711 91 31 1583 3879 41 481 1583 2385 90 453 2850 4615 62 481 2850 4130 11 481 2850 1588 29 330 2850 2201 45 290 3879 1554 22 481 3879 1228 28 766 3879 1463 82 360 4130 1583 7 481 4130 3235 43 976 388 4056 25 546 388 3304 61 512 807 1688 22 546 807 188 25 897 1235 4443 78 546 1235 731 8 779 1235 1875 3 666 1688 4789 51 546 1688 2391 63 839 1914 1235 63 546 1914 3907 84 31 2039 807 100 546 2039 4454 98 784 2521 1914 40 546 2521 2488 72 389 2521 3175 98 627 4056 4207 12 546 4056 1926 40 323 4207 2521 47 546 4207 3001 62 547 4225 2039 34 546 4225 4527 18 546 4225 3417 25 515 4443 4225 9 546 4443 4150 45 429 4443 3293 33 330 389 885 19 455 389 4326 84 914 885 1357 37 455 885 3657 57 493 1203 4992 57 455 1203 2417 75 220 1203 515 65 655 1357 4603 99 455 1357 4460 93 455 1357 892 53 724 1357 244 74 12 2158 3509 43 455 2158 532 88 947 2158 799 17 194 2853 3882 6 455 2853 3672 29 167 2853 2665 24 989 3509 4067 50 455 3509 1470 46 71 3509 1468 44 44 3882 4292 27 455 3882 3375 47 67 4067 1203 68 455 4067 2910 50 908 4292 2158 75 455 4292 4013 93 74 4460 4462 91 455 4460 2996 9 752 4462 2853 64 455 4462 3824 84 711 4462 1708 39 859 390 4105 59 356 390 2400 22 402 390 3138 5 780 816 2740 100 356 816 2979 4 525 1048 1677 67 356 1048 1261 81 335 1048 2265 17 831 1549 1048 26 356 1549 3993 73 12 1677 2380 84 356 1677 1085 97 58 1677 4156 32 908 2380 3441 74 356 2380 4315 63 193 2740 3730 25 356 2740 4961 60 742 2740 1262 27 726 3441 816 64 356 3441 4713 64 567 3730 4700 89 356 3730 2756 39 585 4105 1549 96 356 4105 4907 100 356 4105 1240 1 591 391 1376 38 496 391 69 38 533 964 4285 78 496 964 2500 5 526 964 2752 41 553 1376 4755 28 496 1376 2729 67 496 1376 535 58 183 1376 988 93 871 1916 2640 76 496 1916 1559 54 588 1916 3804 79 918 2151 4937 59 496 2151 4931 28 872 2500 1916 33 496 2500 2561 18 296 2500 3110 93 896 2640 964 64 496 2640 430 53 556 2640 226 31 800 2729 2500 38 496 2729 4623 55 400 4285 2151 48 496 4285 4598 87 881 4285 802 82 730 392 4268 57 525 392 480 35 16 623 797 23 525 623 1721 67 47 623 375 24 951 797 4261 71 525 797 4128 37 983 1020 4725 1 525 1020 2813 88 893 1020 2555 92 242 1052 623 5 525 1052 2768 94 752 1052 5 16 606 2727 3364 16 525 2727 4855 51 525 2727 4697 10 85 2727 828 35 261 3364 3857 91 525 3364 1071 63 18 3364 2853 73 612 3857 1020 47 525 3857 3695 56 200 4228 1052 100 525 4228 653 70 1 4261 2727 20 525 4261 4466 45 864 4268 4228 38 525 4268 2592 22 337 393 2504 30 682 393 4283 32 652 1280 4864 1 682 1280 2165 85 682 1280 308 10 506 1280 4202 48 230 1289 1280 95 682 1289 4837 75 249 1289 4142 37 796 1452 3439 64 682 1452 3231 91 471 1452 1521 36 617 2165 4191 91 682 2165 31 57 483 2386 3343 29 682 2386 1260 17 808 2504 2386 97 682 2504 1206 50 176 3343 1289 57 682 3343 4919 34 32 3343 4552 61 135 3439 4843 61 682 3439 2604 39 393 3439 3499 23 887 4191 1452 19 682 4191 1979 16 173 394 2331 14 215 394 2618 5 946 394 619 31 819 527 4558 2 215 527 4908 52 215 527 2845 76 235 953 3151 27 215 953 1482 72 949 1220 953 74 215 1220 3665 12 241 1220 2389 8 60 2331 1220 3 215 2331 769 53 239 2331 986 16 404 2441 2616 30 215 2441 315 1 562 2616 3271 65 215 2616 4736 20 468 2616 1441 100 720 3151 2441 42 215 3151 3801 74 622 3151 1241 34 73 3271 527 72 215 3271 4457 8 577 3271 3227 63 681 395 2336 32 632 395 598 62 456 395 2358 15 857 832 1837 35 632 832 4076 38 912 832 3239 16 27 1300 1792 43 632 1300 1846 40 180 1580 3771 69 632 1580 926 36 996 1580 2806 47 458 1792 3849 6 632 1792 1267 65 245 1837 1300 3 632 1837 4352 85 362 1837 1414 14 423 2336 1580 63 632 2336 3085 35 901 3481 832 31 632 3481 189 91 209 3583 3481 94 632 3583 4634 69 771 3583 2969 52 943 3771 3583 98 632 3771 976 90 845 3849 4911 21 632 3849 4697 48 632 3849 1939 34 517 396 1360 75 339 396 1692 87 499 973 4760 33 339 973 379 89 566 1360 3874 16 339 1360 2341 100 405 1360 3201 63 992 1853 2193 38 339 1853 4771 93 550 1853 4865 76 133 2193 4159 94 339 2193 1126 57 32 2193 1054 27 55 2253 4281 91 339 2253 4729 77 155 3874 2253 43 339 3874 4901 58 339 3874 4846 92 790 3874 3486 34 108 4159 973 33 339 4159 4106 48 428 4159 3081 77 265 4281 1853 46 339 4281 1232 36 202 4281 4690 46 919 397 1323 66 91 397 3119 77 45 397 3057 73 161 1323 3798 46 91 1323 4112 60 897 1585 2910 86 91 1585 341 60 539 1585 1105 89 469 2553 3547 47 91 2553 3022 90 963 2829 3468 29 91 2829 4765 78 91 2829 2982 54 583 2910 2829 93 91 2910 1201 66 123 2910 1817 18 243 3468 2553 9 91 3468 1383 2 67 3547 4784 21 91 3547 4507 99 348 3547 449 89 489 3798 1585 25 91 3798 1916 51 739 398 755 55 326 398 3184 88 482 398 4595 78 249 528 3552 27 326 528 386 96 199 755 528 78 326 755 4644 33 326 755 2791 19 354 755 3028 68 348 1379 4007 37 326 1379 1363 99 488 3552 1379 92 326 3552 1088 84 140 4007 4816 12 326 4007 548 60 292 4007 128 82 698 399 2611 38 8 399 832 89 188 399 1731 54 191 1247 2058 41 8 1247 1245 31 602 1247 4282 100 368 1359 1751 46 8 1359 4509 18 8 1359 710 48 840 1751 3400 79 8 1751 348 41 83 1751 4477 54 578 2058 4987 26 8 2058 616 78 879 2058 4516 19 583 2611 1359 46 8 2611 2427 37 56 2611 2678 63 460 3400 1247 28 8 3400 1961 33 39 3400 3807 17 296 400 922 44 413 400 2971 29 483 753 3176 37 413 753 4849 87 341 753 1831 12 52 922 1769 53 413 922 3604 51 471 1769 4338 71 413 1769 4946 42 413 1769 4436 64 721 3176 3696 100 413 3176 1857 35 299 3176 4607 77 123 3324 4761 95 413 3324 1012 30 975 3696 3324 40 413 3696 2864 42 734 3696 1379 65 19 4338 753 47 413 4338 1301 51 174 401 1938 92 448 401 3173 94 849 401 4047 18 566 1869 4649 79 448 1869 1655 96 189 1869 189 32 542 1938 1963 5 448 1938 3299 51 577 1938 3018 37 568 1963 3920 62 448 1963 2496 81 61 2142 4976 11 448 2142 3563 15 448 2142 4255 25 668 2142 3871 77 802 3563 3715 24 448 3563 4554 60 976 3715 1869 56 448 3715 2918 100 950 3920 2142 51 448 3920 1467 86 546 402 3171 38 597 402 2192 84 882 402 3855 69 90 2125 2858 79 597 2125 3193 32 516 2858 4383 46 597 2858 918 40 444 2858 2765 42 495 3171 3868 27 597 3171 4145 78 521 3868 2125 47 597 3868 4675 90 597 3868 4806 32 930 3868 4054 76 777 4383 4956 53 597 4383 4792 41 223 403 2900 42 854 403 546 51 229 403 1431 11 459 750 4545 55 854 750 4841 52 854 750 1007 81 958 1271 4001 97 854 1271 944 99 773 1623 3916 15 854 1623 936 63 32 1623 1364 57 487 1949 1623 8 854 1949 2706 64 431 2627 1949 18 854 2627 3645 34 483 2900 1271 96 854 2900 1270 68 958 3916 750 97 854 3916 3650 93 102 4001 2627 90 854 4001 2494 17 683 404 1962 35 227 404 2090 4 729 404 3234 84 559 1264 4395 71 227 1264 782 68 411 1264 1237 46 120 1962 2451 12 227 1962 4824 59 262 1962 1837 32 323 2076 4480 78 227 2076 3800 1 10 2076 2684 40 464 2451 2562 86 227 2451 4880 84 451 2562 1264 75 227 2562 3105 48 654 2562 1968 43 223 3065 4630 23 227 3065 194 84 423 3065 2165 59 539 3204 2076 65 227 3204 4412 17 594 3204 2492 100 16 4395 3204 65 227 4395 2480 89 581 4480 3065 37 227 4480 4972 16 227 4480 3924 95 606 4480 4499 13 616 405 2987 5 337 405 201 21 391 867 2113 51 337 867 1483 99 141 867 4932 48 330 2113 2707 3 337 2113 4403 72 5 2707 4965 11 337 2707 3591 89 281 2707 2775 71 308 2926 3195 71 337 2926 4510 57 51 2926 521 60 908 2987 2926 13 337 2987 1956 14 528 2987 1534 9 865 3195 867 13 337 3195 4916 3 337 3195 3030 15 319 406 1023 94 326 406 1736 28 13 1023 3028 77 326 1023 4696 39 326 1023 1908 56 200 1023 1821 54 766 2335 3896 5 326 2335 2740 54 946 2335 1191 30 272 3028 2335 59 326 3028 1583 84 22 3028 4744 34 528 3896 4553 84 326 3896 119 83 532 407 668 100 402 407 768 52 659 407 4505 84 935 668 2263 78 402 668 1020 42 607 945 1895 38 402 945 4705 51 172 1895 3087 13 402 1895 2498 38 857 1895 3231 26 68 2263 945 66 402 2263 2304 51 790 3087 3720 72 402 3087 4919 85 402 3087 289 4 891 3087 282 98 840 3720 4834 50 402 3720 2864 58 827 3720 3010 68 351 408 821 40 212 408 393 17 204 408 1466 89 501 740 4584 18 212 740 1541 28 222 740 4921 73 516 821 3660 59 212 821 2543 48 191 821 2493 10 149 1099 2239 23 212 1099 2143 80 459 1099 4072 16 677 2239 740 27 212 2239 2483 94 737 3530 4737 11 212 3530 1099 72 212 3530 4145 67 392 3660 3530 97 212 3660 3123 30 29 409 2839 69 265 409 1422 24 255 409 1368 40 874 536 4797 73 265 536 2819 64 547 728 3158 27 265 728 1432 62 892 728 1485 51 69 979 536 60 265 979 1477 58 148 979 1297 30 199 1055 2704 23 265 1055 1941 90 791 1055 618 5 191 2704 728 93 265 2704 1205 24 396 2839 1055 77 265 2839 4725 78 265 2839 13 83 837 2839 4698 18 495 3158 979 53 265 3158 4392 54 237 3158 2442 7 437 410 3197 54 415 410 2092 88 868 533 4811 77 415 533 805 54 799 533 992 57 221 849 2308 22 415 849 1054 55 335 1313 1456 50 415 1313 4687 56 415 1313 3569 25 298 1313 2378 1 176 1368 1313 51 415 1368 3322 21 48 1456 533 35 415 1456 2696 37 690 1456 519 89 424 2308 3177 93 415 2308 4977 81 708 2308 771 41 36 3177 1368 38 415 3177 4992 9 922 3177 349 75 59 3197 849 34 415 3197 2540 26 390 411 2250 34 239 411 2855 23 732 411 16 52 909 1232 1924 17 239 1232 2643 23 867 1429 1232 38 239 1429 4253 27 297 1429 4628 85 808 1924 2200 17 239 1924 1451 51 688 2168 1429 81 239 2168 635 93 648 2168 2206 27 342 2200 4838 93 239 2200 1889 34 341 2200 1169 93 85 2250 4810 17 239 2250 2749 36 239 2250 4392 94 422 2749 2168 45 239 2749 4741 95 377 2749 4404 75 620 412 1292 60 659 412 1801 77 143 412 2673 98 976 575 2705 38 659 575 2685 52 685 575 4980 89 662 907 4437 55 659 907 3897 34 380 907 1941 66 342 933 1380 33 659 933 3075 70 725 1217 933 50 659 1217 740 14 859 1292 907 69 659 1292 2586 57 101 1364 1217 68 659 1364 2406 78 763 1380 4895 19 659 1380 1798 30 469 1380 2935 19 430 2705 1364 62 659 2705 110 96 55 2705 2533 2 68 4437 575 6 659 4437 4737 24 659 4437 4501 10 922 4437 1983 45 540 413 3347 82 603 413 206 62 508 876 4640 89 603 876 4537 17 603 876 2106 61 550 876 2609 36 69 1635 876 17 603 1635 2738 81 181 1635 2929 76 703 3287 1635 24 603 3287 1694 51 220 3347 3739 15 603 3347 2744 32 508 3386 3287 75 603 3386 1612 96 869 3739 3386 45 603 3739 1869 83 680 3739 1050 32 660 414 3321 78 827 414 412 79 737 723 2006 58 827 723 1890 74 876 723 50 63 217 2006 3941 59 827 2006 209 75 429 2006 533 46 311 2505 4187 91 827 2505 2601 2 671 2505 2275 4 436 2649 723 68 827 2649 2547 74 786 3321 2505 59 827 3321 4869 58 827 3321 2533 65 58 3321 226 14 325 3941 4902 35 827 3941 1221 33 387 3941 656 43 694 4187 2649 8 827 4187 3910 88 688 415 4447 15 28 415 4347 66 705 415 4077 80 532 1363 4690 75 28 1363 4855 36 98 2492 1363 49 28 2492 4589 58 800 3210 3650 11 28 3210 2217 55 88 3210 2897 26 85 3333 2492 3 28 3333 2840 63 882 3650 3333 77 28 3650 4522 73 580 4447 3210 82 28 4447 4697 45 28 4447 1168 48 716 416 1575 33 309 416 3415 100 458 416 4499 89 882 693 4344 59 309 693 3800 79 904 1059 693 4 309 1059 2902 29 988 1575 2788 30 309 1575 1870 76 683 1575 63 50 344 1700 4856 90 309 1700 389 26 11 2788 4295 46 309 2788 706 56 42 2788 1608 80 868 4295 4828 87 309 4295 1059 52 309 4295 1714 38 63 4344 1700 64 309 4344 1288 71 268 417 828 33 384 417 1264 10 421 417 527 55 390 828 4392 4 384 828 3839 14 563 828 1551 63 982 1664 1873 12 384 1664 4746 68 593 1664 2159 9 203 1873 3094 80 384 1873 4611 90 384 1873 509 58 358 1873 2880 39 371 2787 1664 76 384 2787 4427 86 77 2904 4048 99 384 2904 4076 10 666 2904 4995 1 898 3094 2904 25 384 3094 3446 75 725 3772 2787 18 384 3772 1142 69 504 3772 312 30 919 4048 4906 68 384 4048 3177 20 877 4392 3772 94 384 4392 1233 46 485 418 2087 20 115 418 1212 64 356 618 1304 22 115 618 2146 98 633 642 4757 49 115 642 331 6 262 1200 618 42 115 1200 1111 58 764 1211 1900 10 115 1211 3669 60 669 1304 1211 19 115 1304 1377 17 935 1304 1508 93 57 1900 642 60 115 1900 2940 40 259 2087 2968 30 115 2087 4182 75 242 2968 1200 55 115 2968 4719 7 115 2968 3512 58 894 2968 2553 67 636 419 4050 58 386 419 4171 18 29 1194 2516 6 386 1194 1033 20 649 1263 1194 38 386 1263 1564 31 844 1263 1745 82 444 1324 2975 26 386 1324 1628 28 228 1324 3326 75 692 2516 3119 23 386 2516 1529 12 523 2516 3231 3 908 2951 4994 92 386 2951 1263 29 386 2951 313 65 822 2975 2951 34 386 2975 4927 1 982 3119 4619 56 386 3119 2982 57 774 3119 2334 47 827 4050 1324 34 386 4050 3856 57 246 420 805 82 342 420 3945 48 664 805 3991 86 342 805 1198 93 391 805 1093 76 265 1056 2277 70 342 1056 611 24 677 1056 1179 1 503 1366 2011 8 342 1366 3687 81 491 1366 467 10 332 2011 4851 91 342 2011 1056 94 342 2011 1565 56 655 2277 3943 18 342 2277 565 12 314 3943 4753 80 342 3943 2199 53 546 3991 1366 76 342 3991 4172 89 667 3991 4264 28 954 421 1063 74 523 421 4589 73 933 606 1302 96 523 606 3904 98 789 1063 2746 57 523 1063 522 94 274 1302 4570 17 523 1302 1370 16 523 1302 1038 25 324 1370 4408 55 523 1370 1890 2 604 2322 606 64 523 2322 761 53 11 2746 3654 45 523 2746 4433 10 952 2746 2508 24 131 3654 2322 76 523 3654 2504 8 228 4408 4565 21 523 4408 887 89 683 422 2476 68 309 422 318 56 149 1273 4200 12 309 1273 537 43 291 1411 2062 14 309 1411 3918 60 596 1411 4720 72 960 1866 4803 37 309 1866 4141 36 711 1866 3677 86 752 1903 4502 36 309 1903 4166 80 309 1903 308 13 974 1903 3450 67 613 2062 1866 50 309 2062 2119 31 375 2476 1273 22 309 2476 2697 81 125 3299 1903 76 309 3299 19 42 974 3299 4445 85 488 4166 1411 99 309 4166 42 19 618 4166 210 72 561 4200 3299 55 309 4200 196 44 742 4200 1940 97 524 423 1392 45 204 423 2126 67 347 423 2610 48 815 960 3781 65 204 960 4928 49 110 1392 2241 48 204 1392 1061 1 32 2241 3980 12 204 2241 376 84 807 2241 3984 30 552 3047 4546 51 204 3047 4535 90 176 3781 3047 78 204 3781 4796 36 204 3781 3178 41 395 3781 1563 95 617 3980 960 40 204 3980 3379 99 163 424 1908 38 264 424 1245 27 774 666 4535 74 264 666 3489 5 335 666 1423 10 855 1490 4021 29 264 1490 799 13 813 1490 713 27 301 1798 666 28 264 1798 2610 71 774 1908 1490 100 264 1908 1266 14 577 1908 3556 31 854 4021 1798 41 264 4021 4626 15 264 4021 4221 23 778 425 742 79 632 425 283 92 794 610 3427 69 632 610 2266 78 496 610 4716 53 474 742 1898 78 632 742 2133 26 278 742 975 88 640 1303 2901 48 632 1303 185 6 944 1303 902 20 550 1898 4238 43 632 1898 4634 87 632 1898 1825 92 951 2827 2941 87 632 2827 3296 33 57 2901 4953 70 632 2901 4677 49 632 2901 4661 80 995 2901 3433 19 55 2941 1303 82 632 2941 621 36 245 2941 4479 34 673 3427 3976 14 632 3427 1414 5 83 3533 610 40 632 3533 925 100 186 3533 1917 70 800 3976 2827 72 632 3976 4160 81 240 4238 4331 50 632 4238 3282 33 223 4238 4356 45 878 4331 3533 24 632 4331 2401 98 179 4331 184 48 798 426 3933 24 692 426 1951 90 104 426 3461 46 108 604 4909 33 692 604 3853 82 639 604 3610 6 262 2246 4683 52 692 2246 2300 92 692 2246 3774 88 313 2300 604 72 692 2300 2074 82 633 3933 4339 69 692 3933 4004 5 609 3933 1143 8 313 4339 2246 63 692 4339 2946 81 578 427 3526 56 930 427 2645 60 376 2478 4623 35 930 2478 3954 70 930 2478 2649 65 121 2478 896 1 534 3289 4079 8 930 3289 965 9 588 3526 3289 49 930 3526 2068 79 76 3526 757 14 885 3633 3810 35 930 3633 2958 42 333 3633 3627 4 384 3810 4829 21 930 3810 4860 97 746 3954 3633 76 930 3954 2150 76 304 4079 2478 22 930 4079 4414 42 237 428 2461 31 648 428 4556 8 434 428 1608 34 549 2155 4576 71 648 2155 2407 36 648 2155 4521 47 107 2155 1981 11 180 2407 4913 43 648 2407 4557 97 279 2461 4142 32 648 2461 3834 72 311 4142 2155 60 648 4142 297 30 514 4142 3369 22 726 429 2304 61 404 429 1033 16 225 2187 3410 63 404 2187 2531 50 443 2304 3927 12 404 2304 4540 9 404 2304 1716 9 670 2304 899 33 84 2305 2187 60 404 2305 4270 59 607 2305 3425 63 808 2369 2305 27 404 2369 1094 95 23 2369 2972 2 930 2895 2369 5 404 2895 4314 12 795 2895 3988 36 459 3410 4624 89 404 3410 3446 79 498 3410 3536 39 5 3927 4090 23 404 3927 1334 23 888 4090 2895 90 404 4090 868 25 406 4090 1244 20 233 430 3342 21 264 430 933 33 242 621 4439 18 264 621 4852 2 877 621 3474 46 807 3266 4974 54 264 3266 2799 68 775 3266 3876 75 314 3342 3978 47 264 3342 4703 89 988 3342 1512 60 720 3978 4737 57 264 3978 621 10 264 3978 4006 15 317 4439 3266 38 264 4439 2888 38 135 431 1123 63 1014 431 2610 86 52 1082 3897 9 1014 1082 2593 36 704 1082 4390 11 787 1123 1643 49 1014 1123 765 13 105 1123 3548 54 673 1643 4493 38 1014 1643 2835 13 297 1643 2331 94 223 3008 3843 62 1014 3008 1050 87 25 3123 3008 32 1014 3123 3740 51 184 3123 4929 83 469 3843 4845 87 1014 3843 1082 31 1014 3843 4650 1 432 3897 4573 10 1014 3897 4243 81 158 4493 3123 21 1014 4493 680 46 693 432 1731 91 298 432 3089 94 816 432 3482 54 964 1731 3406 71 298 1731 2667 54 715 1767 2725 61 298 1767 2041 12 747 1767 2160 18 812 1933 1767 54 298 1933 4937 71 298 1933 19 3 874 1933 2477 75 123 2696 4757 19 298 2696 4213 92 57 2725 2696 41 298 2725 3001 40 348 3406 1933 1 298 3406 1612 44 329 3406 2186 21 836 433 2958 38 498 433 742 67 917 1606 3852 70 498 1606 4918 4 776 2177 1606 61 498 2177 4430 83 407 2177 1288 66 602 2688 2177 20 498 2688 4510 16 498 2688 1322 75 651 2791 2688 25 498 2791 3957 85 566 2791 1103 75 170 2958 2791 23 498 2958 4833 78 14 2958 4857 60 499 3742 4862 98 498 3742 517 22 974 3742 3183 96 765 3852 3742 5 498 3852 4919 98 344 434 1276 86 36 434 4871 90 531 434 1378 72 399 1072 3128 81 36 1072 4959 73 36 1072 4181 33 116 1072 1532 30 297 1276 1072 93 36 1276 3779 57 103 1276 4545 1 534 1401 4643 64 36 1401 3103 81 825 1892 2144 8 36 1892 1992 94 274 1892 4899 59 619 2144 1401 36 36 2144 1634 19 34 2144 3635 44 660 3128 3416 91 36 3128 2561 20 223 3128 4679 87 756 3416 1892 100 36 3416 3117 75 861 435 585 11 141 435 2795 67 117 435 1996 38 507 585 3611 46 141 585 1921 97 277 585 286 51 527 944 4908 29 141 944 288 91 270 1665 4838 23 141 1665 3012 76 141 1665 869 94 142 1665 4774 44 965 3012 3029 14 141 3012 1802 57 826 3012 250 2 107 3029 944 74 141 3029 1857 86 290 3611 1665 58 141 3611 321 37 269 436 1154 99 957 436 1409 93 395 436 434 17 925 906 1595 5 957 906 4542 39 957 906 164 2 47 906 1126 69 963 1154 1335 15 957 1154 4305 54 456 1184 906 48 957 1184 2088 21 443 1335 4282 20 957 1335 446 74 128 1595 4873 79 957 1595 2784 72 784 1595 1143 97 23 2149 1184 37 957 2149 3905 55 63 2149 710 68 621 4282 2149 89 957 4282 2523 17 959 437 1134 60 574 437 4496 10 304 1018 3272 83 574 1018 2980 96 162 1031 3064 54 574 1031 2816 73 426 1134 1018 30 574 1134 4530 29 574 1134 2018 67 593 1134 2387 96 401 1710 1031 45 574 1710 1988 16 29 1710 3546 1 549 3064 4526 41 574 3064 3919 16 732 3272 1710 90 574 3272 2440 58 446 438 4256 99 507 438 4889 74 409 958 4192 10 507 958 1754 10 883 1287 2532 42 507 1287 1303 24 390 1287 973 64 502 2286 958 55 507 2286 3023 29 298 2532 3618 37 507 2532 253 56 375 2532 1873 17 946 3319 2286 89 507 3319 780 60 60 3319 3704 43 527 3618 4800 5 507 3618 4683 90 507 3618 3879 54 807 3618 4379 55 760 4192 1287 52 507 4256 4332 62 507 4256 4300 73 774 4332 3319 84 507 4332 222 70 19 439 4095 14 257 439 2258 9 709 1480 2311 22 257 1480 4749 82 257 2023 4633 69 257 2023 596 42 242 2311 2870 100 257 2311 1675 57 224 2311 2088 91 113 2648 1480 72 257 2870 2023 55 257 2870 1869 53 768 4095 2648 81 257 4095 3689 80 703 440 1284 37 531 440 686 57 423 440 1740 74 566 627 3768 56 531 722 4640 99 531 722 1111 44 183 985 3561 32 531 985 291 37 594 1284 627 47 531 1284 500 54 11 1284 407 9 21 2025 722 87 531 3286 2025 47 531 3286 837 78 468 3561 3286 5 531 3561 3990 13 447 3561 138 65 515 3768 4327 51 531 3768 4778 45 531 4327 985 28 531 441 509 77 1178 441 2704 41 431 509 2022 31 1178 509 61 51 433 509 2606 51 543 647 3409 44 1178 1572 647 5 1178 1572 2098 90 345 2022 3381 83 1178 2022 4743 3 1178 2219 3485 6 1178 2219 4198 2 234 2415 2219 44 1178 2415 1742 28 284 2671 3107 41 1178 2671 4613 45 292 3107 4781 69 1178 3107 1289 17 273 3381 1572 22 1178 3381 4547 75 909 3381 1073 33 581 3409 3575 91 1178 3409 4733 69 1178 3485 2671 45 1178 3575 2415 19 1178 3575 688 2 855 442 2809 76 689 442 4350 73 576 442 3644 90 721 772 4246 92 689 1218 1311 71 689 1218 4301 99 526 1218 1448 31 497 1311 4487 75 689 1348 1810 49 689 1348 3360 58 333 1810 3644 38 689 1810 1634 61 310 1810 1967 88 275 2569 4830 36 689 2809 772 86 689 2809 4685 33 306 3644 1218 73 689 3644 1504 5 219 3644 2419 46 269 4246 1348 27 689 4487 2569 66 689 4487 4824 70 689 443 2278 90 445 443 738 89 376 443 101 88 290 918 2830 54 445 1135 4910 64 445 1135 2556 32 864 1321 1946 70 445 1321 94 50 682 1612 3747 54 445 1612 1007 4 76 1946 1135 60 445 1946 4129 91 583 1946 4158 80 602 2278 918 11 445 2278 4512 30 445 2544 1321 3 445 2830 1612 73 445 2830 2721 57 98 3747 2544 60 445 3747 4874 17 505 3747 725 84 618 444 1756 55 422 1410 4552 99 422 1410 3226 68 201 1659 1872 88 422 1659 2856 98 478 1659 3267 63 773 1756 1659 50 422 1872 3621 58 422 1872 522 40 693 2348 1410 99 422 2348 4564 75 422 3621 3678 21 422 3621 4337 87 167 3678 4111 36 422 3678 443 79 644 4111 2348 54 422 4111 1892 35 420 445 1755 17 1222 445 3943 13 601 445 2542 79 88 995 4584 85 1222 1329 995 69 1222 1329 2491 88 540 1329 3914 88 257 1755 2923 22 1222 1870 2739 9 1222 1870 1971 64 39 2121 4044 13 1222 2121 21 1 507 2146 2734 36 1222 2146 3343 63 562 2146 3549 21 39 2734 4948 18 1222 2734 1870 53 1222 2739 1329 28 1222 2923 2121 36 1222 2923 2184 30 786 4044 2146 43 1222 4044 381 44 687 446 3737 67 404 446 1920 41 526 446 2117 39 641 1795 4925 89 404 1795 4854 11 404 2172 3905 33 404 3723 1795 43 404 3723 1588 53 584 3737 2172 20 404 3737 3410 84 277 3737 804 26 719 3905 3723 54 404 447 4470 69 516 447 2609 86 728 950 4608 95 516 950 582 83 719 2429 3549 96 516 2429 1407 32 282 2429 3634 54 996 2795 3705 9 516 3549 2795 73 516 3549 3319 50 178 3705 950 81 516 3705 1788 55 860 3705 955 73 438 4470 2429 5 516 4470 4844 97 516 448 2826 45 298 955 1122 47 298 955 3479 32 363 1122 1171 59 298 1122 4643 96 298 1171 3312 12 298 1171 1826 28 767 1171 1545 64 428 1788 4986 27 298 2826 955 37 298 2826 578 46 526 2826 4940 22 287 3312 1788 62 298 449 1336 86 359 449 2178 62 946 628 4986 16 359 628 132 51 224 1210 4985 61 359 1210 1907 59 359 1336 1210 47 359 1336 785 44 447 1907 628 15 359 1907 1879 57 527 450 596 16 196 450 709 40 193 596 2845 55 196 596 3765 30 312 596 3339 74 79 858 3925 38 196 937 1252 50 196 937 4691 9 886 989 937 19 196 989 4990 32 196 1252 858 1 196 1252 372 77 975 2845 989 86 196 2845 4952 16 771 3925 4913 29 196 3925 4068 15 906 451 2536 80 394 451 680 94 499 1819 4823 68 394 1819 1728 4 791 1835 2033 45 394 1835 1863 85 329 1835 2619 33 731 2033 2463 93 394 2388 1835 74 394 2388 892 63 318 2463 1819 14 394 2463 4830 34 394 2536 2690 72 394 2536 657 13 768 2690 2388 8 394 2690 2830 99 924 2690 1269 63 717 452 3638 17 412 638 2222 55 412 638 4801 44 171 1342 1777 21 412 1342 294 12 584 1607 4352 5 412 1607 3073 72 449 1607 2195 45 548 1619 638 7 412 1777 4841 78 412 1777 1906 66 412 1906 2002 1 412 1906 3759 2 38 1906 1997 21 610 2002 4514 58 412 2222 1607 27 412 2222 625 81 3 3368 1619 4 412 3368 3415 25 706 3368 1243 55 315 3452 4645 22 412 3452 1342 27 412 3638 3368 50 412 4352 3452 8 412 4352 4706 16 255 4352 4834 4 734 453 1241 77 276 1241 2329 69 276 1241 3434 57 216 1241 1835 12 16 2329 2379 2 276 2379 3528 31 276 2379 261 65 592 3010 4907 71 276 3010 4066 42 880 3528 3565 20 276 3528 4509 37 276 3565 3010 50 276 3565 3356 53 883 3565 4845 18 491 454 2333 58 484 542 2145 93 484 542 1147 53 410 786 3641 43 484 786 1396 12 603 786 4512 13 819 2016 542 78 484 2145 3578 29 484 2145 3048 7 22 2333 4412 34 484 2333 4518 80 282 2333 4173 23 438 2417 4204 52 484 3578 786 34 484 3578 3466 14 625 3641 4913 3 484 3641 665 68 346 4204 2016 51 484 4204 4542 51 484 4412 2417 35 484 4412 294 28 624 4412 3289 61 230 455 2814 72 635 1785 2273 44 635 1785 2312 20 949 1808 1785 90 635 1808 4525 16 268 1808 2134 22 249 2273 2292 47 635 2292 4410 2 635 2292 1905 60 684 2732 4793 30 635 2732 3900 1 501 2732 1011 69 909 2814 1808 25 635 2984 2732 60 635 2984 1046 22 402 3620 2984 76 635 3620 4676 70 938 3620 3628 52 343 4410 3620 27 635 4410 4962 59 635 456 1508 72 204 1233 2672 45 204 1233 2614 53 411 1482 1233 21 204 1482 505 90 879 1508 2679 27 204 1508 1683 34 51 1508 4526 83 883 1574 4774 26 204 2226 1574 97 204 2226 3461 16 276 2672 2226 24 204 2672 1078 42 600 2672 4104 34 693 2679 1482 34 204 2679 4817 99 204 457 2057 25 826 1047 1960 67 826 1047 4884 76 826 1449 4473 3 826 1449 183 87 454 1960 3190 84 826 1960 1588 29 253 1960 733 83 682 2057 1047 56 826 3190 1449 75 826 3190 1834 25 684 3190 3429 95 857 4473 4554 1 826 458 688 33 169 458 3560 79 587 688 1332 38 169 688 4861 69 169 1332 2790 39 169 1332 2326 79 722 1332 4161 100 253 2790 3226 70 169 3226 4129 66 169 3226 1544 51 811 3226 1015 51 848 4129 4934 58 169 459 2778 19 361 459 1608 22 283 685 3625 72 361 685 3346 32 832 685 1369 28 607 1175 2614 69 361 1515 1530 38 361 1515 785 78 272 1515 4211 34 995 1530 4996 37 361 2614 4039 88 361 2614 4608 2 361 2778 3247 72 361 2778 2811 20 948 3247 685 67 361 3247 1998 2 10 3625 1175 11 361 3625 268 84 16 4039 1515 38 361 4039 1433 65 536 460 4032 61 906 460 1230 54 949 460 3942 76 972 923 2252 56 906 1240 3199 63 906 1240 3890 69 991 1240 4353 60 31 2252 4788 32 906 2252 4685 7 906 2695 4454 71 906 3199 2695 3 906 3199 1789 2 554 3519 923 19 906 3519 3083 31 675 3519 242 59 887 4032 4340 49 906 4340 1240 71 906 4340 3480 56 50 4454 3519 36 906 4454 863 13 97 461 3212 70 1143 461 284 36 253 461 4996 93 135 564 913 96 1143 863 4879 87 1143 863 4981 93 1143 913 2479 43 1143 913 1786 16 992 913 2453 69 42 1494 863 100 1143 2126 4233 43 1143 2126 4272 4 733 2126 3969 67 784 2479 3425 98 1143 3212 2126 46 1143 3212 4687 90 256 3212 2716 10 560 3425 1494 47 1143 4233 564 59 1143 4233 2357 70 201 462 3872 6 484 462 306 57 119 752 1213 29 484 752 633 80 560 852 4488 39 484 852 3620 74 832 852 4280 2 118 920 2195 21 484 1213 852 76 484 1213 2627 19 865 1213 3699 51 35 2098 920 87 484 2195 2674 14 484 2195 4642 42 484 2674 3821 43 484 2674 1082 43 985 2674 1188 87 323 3821 752 66 484 3872 2098 68 484 3872 3065 93 711 4488 4916 63 484 4488 3428 96 536 463 4308 23 670 463 2581 4 130 463 3574 76 36 503 2186 6 670 905 4631 39 670 905 4274 32 574 905 990 23 55 1221 905 67 670 2186 4945 15 670 2186 1221 39 670 4308 503 40 670 4308 806 24 833 464 3391 55 248 464 393 39 694 1507 4789 18 248 1507 1449 86 875 2207 1507 5 248 2207 2070 9 596 2207 570 20 944 2363 3636 66 248 3391 2363 19 248 3391 3834 28 661 3391 221 4 699 3636 2207 100 248 3636 4573 55 248 465 2499 92 94 756 2235 34 94 756 4026 19 753 756 3461 29 976 785 1067 7 94 1067 1133 98 94 1067 4528 88 13 1133 756 86 94 1133 701 7 185 1133 2571 60 911 1734 2875 84 94 2235 4838 22 94 2235 1763 20 810 2499 3831 75 94 2499 2136 1 854 2875 4635 87 94 2875 785 69 94 3831 1734 15 94 3831 1890 69 466 3831 2931 45 215 466 2677 23 109 640 3670 53 109 640 2159 35 920 1362 3169 91 109 1362 3500 25 202 2468 3397 47 109 2468 284 54 819 2677 1362 57 109 2677 3378 83 278 2677 2712 58 521 3169 2468 16 109 3397 3973 18 109 3397 4836 50 235 3670 4728 56 109 3670 4608 68 109 3973 640 50 109 3973 3295 78 137 3973 4064 36 764 467 4153 77 506 774 3305 4 506 774 4988 92 387 774 2008 46 403 1095 1994 41 506 1994 774 38 506 1994 4963 26 908 2138 2626 21 506 2138 836 75 514 2138 938 2 810 2626 4961 18 506 2626 1095 48 506 2860 4293 90 506 3305 2860 31 506 3305 117 21 660 4153 2138 78 506 4153 2631 62 917 4293 4769 4 506 4293 3075 88 838 468 615 42 718 468 2001 61 706 615 3693 16 718 615 3101 27 543 684 4668 3 718 684 3134 91 718 813 4681 47 718 813 731 47 115 2733 684 27 718 2733 3238 52 128 2733 1752 58 809 3134 813 57 718 3460 2733 100 718 3460 3551 2 729 3693 3460 64 718 3693 1545 58 176 3693 4703 30 558 469 1388 44 381 520 1402 85 381 520 3704 94 431 1388 2617 6 381 1388 1347 25 885 1402 4949 78 381 1402 403 83 83 2617 4649 9 381 2617 3707 78 381 2917 4213 16 381 2917 1651 75 703 3160 2917 32 381 3160 3488 17 708 3707 3160 57 381 3707 4925 77 958 3707 4892 85 547 4213 520 36 381 470 1019 29 1110 470 1900 96 388 519 733 73 1110 519 3056 78 105 733 4932 97 1110 733 3137 22 177 733 4724 80 753 1019 2944 96 1110 2568 519 43 1110 2568 1364 30 90 2944 4234 51 1110 2944 4630 91 1110 4124 2568 46 1110 4124 1272 24 671 4124 1291 45 125 4234 4124 18 1110 471 3228 4 414 471 809 23 33 517 4774 98 414 517 3400 76 520 517 881 75 401 1634 517 11 414 1634 4967 11 414 2443 1634 48 414 3228 3564 48 414 3228 1877 38 867 3228 4718 41 479 3564 2443 94 414 472 3182 1 1002 472 4334 61 17 1195 4424 21 1002 1195 644 45 89 3182 3211 61 1002 3182 1228 38 331 3182 2767 83 414 3211 3469 53 1002 3469 1195 59 1002 3469 4626 65 1002 4424 4855 29 1002 4424 4598 45 750 473 801 85 327 473 3783 22 467 801 3108 97 327 801 4465 98 235 801 990 10 255 1109 3297 47 327 2736 1109 7 327 2736 3667 14 728 2736 1953 57 838 3108 4276 2 327 3108 4643 68 327 3297 4287 10 327 4276 2736 41 327 4276 2372 13 232 4276 659 98 203 4287 4511 41 327 474 1759 71 452 474 1202 60 963 474 1947 1 278 1418 3689 29 452 1581 1779 34 452 1581 155 27 674 1581 1757 23 5 1759 2940 17 452 1779 2020 14 452 1779 1126 28 687 2020 1418 78 452 2020 3331 78 461 2940 1581 91 452 2940 3331 33 696 2940 932 89 994 3689 4601 24 452 3689 4656 84 452 475 3835 33 379 3046 4856 71 379 3046 3842 31 379 3244 4914 19 379 3244 2721 15 574 3244 755 89 504 3835 3046 66 379 3842 4391 33 379 3842 397 39 528 3842 4182 90 694 4391 3244 39 379 476 2847 50 315 476 1987 52 512 1766 4735 19 315 1766 3943 75 348 1766 1717 60 682 2119 4795 92 315 2119 1766 62 315 2847 2889 11 315 2889 2119 68 315 2889 645 62 246 477 2234 37 1012 477 3926 94 40 477 4325 96 37 901 4586 63 1012 2234 3699 4 1012 2234 2332 32 190 2603 2702 32 1012 2603 2682 67 578 2702 901 96 1012 2702 1231 45 546 3699 4481 40 1012 3699 2501 39 825 3699 651 76 225 4481 2603 17 1012 4481 4777 74 1012 478 1138 29 572 620 2442 87 572 620 4799 25 572 712 4314 79 572 712 330 13 806 712 1036 94 380 718 4867 79 572 1002 620 56 572 1002 320 79 189 1002 1845 37 413 1138 1002 25 572 1831 3982 61 572 1831 2423 47 660 1831 83 95 457 2442 1831 1 572 3982 712 13 572 3982 4008 60 951 3982 804 28 389 4314 718 70 572 479 3056 99 421 479 1720 48 494 479 2994 87 983 614 3110 28 421 1190 1999 61 421 1190 4183 14 467 1999 2490 46 421 1999 4752 55 421 2490 614 54 421 2490 2830 63 120 2490 509 88 457 3056 1190 39 421 3110 4917 19 421 3110 4719 72 770 480 1197 79 653 480 2349 3 855 567 3560 30 653 567 3864 28 397 1197 2782 80 653 1197 3207 84 798 1197 2835 51 23 2265 2323 5 653 2323 2401 81 653 2323 2111 89 443 2401 4900 35 653 2401 4779 95 712 2580 567 92 653 2580 347 9 911 2580 272 2 574 2782 4452 83 653 3560 4663 7 653 3560 2265 68 653 4452 2580 1 653 4452 109 68 866 481 3653 30 492 481 1158 54 611 481 4867 73 62 970 4807 72 492 970 4674 41 492 2107 4188 5 492 2692 970 67 492 2692 3213 50 988 2692 4241 50 605 2985 2692 23 492 3653 2107 89 492 3653 2628 70 350 3653 532 77 650 4188 2985 96 492 482 3115 32 485 482 2195 58 890 482 451 30 743 2290 3710 74 485 3115 4441 79 485 3115 3739 9 273 3115 148 94 4 3317 4370 97 485 3626 2290 26 485 3626 4861 91 319 3710 4518 95 485 3710 4031 11 58 4370 4449 3 485 4370 4956 4 563 4370 3800 6 925 4441 3317 42 485 4449 3626 63 485 4449 4831 19 485 483 2903 65 91 483 4926 11 69 1617 4630 39 91 1617 1306 2 85 2899 3994 99 91 2899 4943 13 804 2899 1864 23 903 2903 2899 82 91 3568 3958 71 91 3568 4676 80 265 3568 368 89 470 3958 1617 2 91 3994 3568 45 91 3994 4698 67 91 484 930 24 667 484 1368 56 873 504 4557 5 667 504 4526 83 667 930 1228 12 667 930 134 46 698 1208 1965 21 667 1208 3324 36 250 1228 2396 49 667 1228 2148 57 84 1228 4310 100 47 1965 504 77 667 2396 1208 19 667 2396 4818 43 661 2396 2734 39 612 485 2653 69 793 806 3143 80 793 806 2430 84 292 806 4140 98 277 1868 2283 47 793 1981 1868 63 793 1981 334 29 143 2283 4825 39 793 2283 4971 73 793 2653 806 76 793 2653 523 86 727 2653 459 17 92 3143 1981 100 793 486 808 61 192 486 1234 8 729 605 2757 4 192 605 1666 13 180 808 1334 27 192 808 4553 84 192 986 2660 94 192 986 4876 64 635 1334 2389 38 192 1334 992 17 160 1334 2674 87 897 2389 2760 19 192 2660 3851 74 192 2660 1535 44 24 2660 1109 23 732 2757 986 94 192 2760 605 32 192 2760 4233 65 308 2760 1939 32 817 3851 4080 68 192 4080 4670 47 192 4080 2428 50 321 487 3862 93 631 487 2662 87 672 2275 2962 88 631 2275 1263 60 511 2962 3527 90 631 2962 4840 55 568 2962 30 37 313 3527 4892 17 631 3862 4455 86 631 3862 2891 77 680 4055 4955 45 631 4055 2275 18 631 4455 4055 61 631 4455 4452 23 503 488 3724 29 404 488 1273 40 139 488 3989 86 350 553 1989 92 404 1094 4548 54 404 1094 4568 20 404 1989 2370 65 404 1989 1907 65 885 1989 2064 20 235 2370 1094 28 404 3724 553 18 404 3724 2427 49 523 3724 2598 8 273 489 1124 21 635 507 4763 4 635 507 818 46 445 1124 1842 100 635 1124 915 74 515 1124 127 11 220 1842 3901 48 635 2556 4879 61 635 2556 3426 65 635 3426 507 28 635 3426 3730 76 572 3426 3251 23 355 3901 3970 52 635 3970 2556 67 635 3970 522 23 772 3970 3556 63 386 490 1601 85 60 1502 4174 71 60 1502 2646 67 431 1601 1502 4 60 1601 2227 62 652 2153 4407 70 60 2153 2783 47 808 2153 103 24 669 2781 4577 99 60 3766 4058 53 60 3766 158 4 916 4058 2781 81 60 4058 4795 29 60 4174 2153 24 60 4174 604 51 600 4174 3813 26 45 4407 3766 11 60 491 3953 91 252 491 202 28 44 491 2189 90 337 1282 2714 42 252 2714 4425 95 252 2714 4780 47 811 3712 4656 84 252 3712 644 1 753 3841 1282 33 252 3841 4305 5 918 3870 3841 64 252 3870 2399 11 578 3870 1084 72 711 3953 3870 4 252 4425 3712 74 252 4425 4949 43 252 492 1543 5 739 492 4164 96 549 720 4679 96 739 720 2743 81 594 1199 4746 21 739 1199 2230 7 739 1543 2742 66 739 1543 3269 33 508 2230 720 78 739 2230 1507 75 372 2742 1199 11 739 2742 440 28 422 493 539 25 117 493 345 11 946 539 1104 97 117 539 4135 56 631 765 3727 56 117 765 418 51 106 765 4865 82 943 1104 1427 39 117 1270 765 72 117 1270 3572 40 20 1427 2024 64 117 1427 1394 52 839 2024 1270 27 117 2024 3528 97 202 2629 4825 16 117 2629 4642 24 117 3727 2629 57 117 3727 2758 74 902 494 3166 22 412 494 88 34 479 595 4527 82 412 595 2959 69 973 595 292 13 391 771 2927 71 412 771 4571 63 412 834 595 29 412 1567 834 48 412 1567 2405 38 32 1567 2417 27 501 2927 3719 62 412 3040 771 1 412 3040 3488 33 468 3040 372 17 136 3166 3040 35 412 3569 1567 89 412 3569 248 33 103 3569 184 70 422 3719 3569 4 412 495 639 61 804 495 303 11 66 495 3767 42 178 639 1814 32 804 1458 3332 76 804 1458 1653 56 518 1458 99 88 693 1475 4465 60 804 1475 4752 53 804 1814 4162 65 804 2470 1475 65 804 2470 4743 20 939 2470 1129 44 475 2635 1458 32 804 3332 4916 2 804 3332 3363 89 506 3332 2003 4 734 3987 2635 97 804 4162 2470 96 804 4162 1159 51 634 4465 3987 42 804 4465 3464 65 125 496 4006 4 472 496 1569 32 916 496 3329 15 557 1644 4895 12 472 2485 3384 25 472 2485 3921 14 548 2485 4800 78 850 3144 3777 68 472 3384 1644 84 472 3384 3095 24 410 3777 2485 96 472 3777 2263 6 983 4006 3144 70 472 4006 4843 21 472 497 3652 98 672 497 1880 13 988 497 4595 38 640 1286 2373 41 672 1331 1286 46 672 1331 4069 66 114 1445 1833 90 672 1445 1802 66 201 1445 4101 31 77 1833 2862 54 672 2373 3023 51 672 2373 4652 55 672 2862 4634 48 672 2862 1806 93 847 2862 3228 48 18 3023 1445 48 672 3652 1331 25 672 3652 3832 73 64 3652 915 43 261 498 2182 23 833 1571 1847 31 833 1571 3728 39 468 1571 3669 32 943 1847 4657 100 833 2182 2836 97 833 2182 1969 77 153 2319 1571 14 833 2319 2103 83 602 2836 2319 83 833 2836 4958 78 833 499 2255 49 1251 499 2214 85 522 499 1111 8 694 1939 4556 52 1251 2179 3423 44 1251 2179 4580 54 894 2179 4216 11 716 2255 3383 7 1251 3383 4689 69 1251 3383 2179 85 1251 3423 1939 67 1251 3423 3313 38 767 500 1446 59 638 500 1573 90 877 1015 4751 77 638 1015 4618 23 638 1015 4773 27 638 1015 4723 60 638 1015 2762 17 638 1015 4857 26 638 1015 4563 46 638 1015 4997 87 638 1015 4678 29 638 1015 4899 48 638 1015 4921 8 638 1015 4632 64 638 1015 4870 55 638 1015 4859 30 638 1446 3566 64 638 1446 4521 94 638 1446 4812 86 638 1446 4927 59 638 1446 4612 74 638 1446 4818 71 638 1446 4713 28 638 1446 4918 16 638 1446 4592 57 638 1446 4756 79 638 1446 4664 67 638 1446 4871 17 638 2762 4885 22 638 2762 4562 7 638 2762 4912 7 638 2762 4819 53 638 2762 4724 24 638 2762 4964 82 638 2762 4878 87 638 2762 4711 40 638 2762 4775 66 638 2762 4262 68 638 2762 4779 20 638 2762 4814 13 638 2762 4599 86 638 3100 4943 23 638 3100 4936 90 638 3100 4933 82 638 3100 4915 64 638 3100 4501 1 638 3100 4801 45 638 3100 4732 14 638 3100 1015 10 638 3100 4832 86 638 3100 4973 10 638 3100 4813 62 638 3566 4550 61 638 3566 3100 1 638 3566 4865 19 638 3566 4808 38 638 3566 4519 65 638 3566 4772 47 638 3566 4881 1 638 3566 4636 10 638 3566 4646 62 638 3566 4555 71 638 3566 4507 51 638 3566 4673 16 638 3566 4747 87 638 4262 4613 78 638 4262 4736 26 638 4262 4539 16 638 4262 4935 8 638 4262 4699 12 638 4262 4658 50 638 4262 4978 2 638 4262 4827 12 638 4530 1476 21 514 4531 56 19 39 4532 4910 61 239 4532 214 36 426 4533 3283 38 810 4534 1362 64 724 4534 4172 77 766 4535 1271 9 530 4536 4178 2 800 4536 757 98 704 4537 506 59 323 4537 4215 37 284 4538 1386 60 797 4539 3111 15 779 4540 668 61 370 4541 783 78 874 4541 775 12 557 4542 3521 11 457 4543 2472 80 263 4543 3930 7 277 4544 170 23 980 4544 1593 74 93 4545 2985 6 259 4546 3274 64 481 4547 1709 81 666 4548 259 33 229 4548 901 98 731 4549 4598 26 141 4550 2231 59 885 4550 1429 47 367 4551 1291 54 538 4552 4147 79 76 4552 398 35 796 4553 2267 31 739 4553 1604 29 9 4554 3596 3 94 4555 2884 75 209 4556 4588 19 782 4556 4796 76 997 4557 4850 53 545 4558 367 4 458 4558 4656 100 668 4559 196 60 94 4560 3611 98 30 4560 4675 88 261 4561 1494 31 824 4562 710 92 226 4563 481 58 543 4564 984 26 659 4565 4911 44 387 4565 846 38 938 4566 1760 92 868 4567 872 31 790 4568 3739 53 196 4568 301 11 449 4569 4888 47 431 4569 268 14 788 4570 3083 40 138 4570 91 5 712 4571 3271 13 314 4571 362 10 205 4572 845 83 442 4573 793 26 928 4574 3158 67 624 4574 4123 45 540 4575 4727 91 569 4575 2996 59 101 4576 3220 19 2 4576 23 7 824 4577 1186 26 331 4577 4258 99 194 4578 22 15 156 4578 3660 66 367 4579 3687 42 346 4579 403 8 987 4580 757 26 863 4581 4975 31 95 4582 4012 93 157 4583 2694 43 200 4583 3069 58 415 4584 2502 45 867 4584 3416 9 206 4585 566 9 177 4586 2454 48 237 4586 1401 3 121 4587 2844 43 561 4587 1869 52 219 4588 4144 65 51 4589 1703 50 345 4589 778 82 168 4590 512 76 406 4591 3201 15 847 4591 955 1 540 4592 2492 97 567 4592 2478 64 798 4593 2172 81 389 4593 3337 84 257 4594 2263 20 920 4594 1987 5 598 4595 826 39 985 4596 791 9 100 4597 3801 64 604 4597 4330 12 897 4598 4946 31 141 4598 450 57 219 4599 4677 39 668 4600 3861 14 48 4600 3193 70 567 4601 2431 78 878 4602 908 78 885 4602 931 90 807 4603 928 35 687 4603 2346 82 398 4604 1361 77 767 4605 4368 58 341 4606 3018 25 667 4606 4131 4 891 4607 4968 80 853 4607 801 12 693 4608 649 55 100 4608 4917 14 459 4609 2106 60 451 4609 4257 87 530 4610 4221 1 950 4611 1513 10 483 4612 1378 12 387 4612 4696 86 789 4613 3688 90 414 4614 3393 8 853 4614 4289 94 219 4615 3009 71 645 4616 2096 44 157 4617 4446 34 754 4618 4512 85 232 4619 4659 68 690 4619 2747 26 182 4620 3659 52 938 4621 2748 95 484 4622 259 31 883 4623 4010 86 738 4623 1650 29 323 4624 3549 48 652 4624 344 42 922 4625 4212 43 812 4626 1977 55 940 4627 157 68 74 4628 127 21 198 4628 1156 80 184 4629 4639 1 114 4629 1359 34 968 4630 606 37 751 4630 2762 39 57 4631 1303 3 677 4632 3641 20 400 4632 3792 71 66 4633 3868 45 604 4633 3950 81 574 4634 1330 41 898 4634 1770 18 149 4635 2733 96 720 4636 3973 51 800 4636 3685 98 815 4637 3033 45 429 4637 3067 83 37 4638 4278 23 322 4638 2012 25 364 4639 2314 18 851 4639 1303 58 821 4640 158 4 744 4640 1313 94 834 4641 4549 80 232 4641 1553 90 353 4642 1528 16 105 4643 1986 23 206 4644 2525 19 105 4644 4116 10 627 4645 1652 81 881 4646 3973 19 873 4647 3284 18 48 4647 562 98 976 4648 592 17 734 4648 1602 52 76 4649 708 35 394 4650 2174 14 810 4650 661 67 202 4651 875 41 368 4652 4766 92 585 4653 3090 2 840 4653 956 80 765 4654 2022 92 478 4655 4912 64 315 4656 2300 88 93 4656 640 87 167 4657 841 82 826 4657 4027 42 659 4658 2266 47 550 4658 3865 18 254 4659 1332 78 781 4660 1273 6 324 4661 4463 70 610 4662 27 99 201 4663 40 54 314 4663 1533 84 600 4664 2987 44 628 4665 2752 59 163 4665 1445 78 221 4666 2649 93 248 4666 2615 4 187 4667 3098 95 522 4668 768 45 449 4669 943 46 794 4669 450 36 45 4670 3525 40 249 4671 1657 53 357 4672 2496 63 458 4672 4698 51 547 4673 1729 38 169 4673 2717 56 353 4674 555 20 770 4675 4713 50 968 4675 1729 20 182 4676 4229 90 259 4676 3097 56 125 4677 2078 41 409 4677 4510 66 743 4678 62 97 859 4679 1613 40 602 4679 2665 14 471 4680 1197 81 55 4680 1585 17 996 4681 4118 71 419 4682 665 93 696 4683 3367 2 312 4684 4905 78 879 4684 4673 60 822 4685 3405 8 157 4686 2923 46 419 4686 4925 53 484 4687 2673 25 285 4688 4256 59 627 4688 2685 53 501 4689 3476 24 92 4690 1745 90 965 4690 4879 26 795 4691 3785 3 939 4691 4372 32 981 4692 1361 4 867 4693 4351 38 142 4693 4872 5 942 4694 1620 66 846 4695 3514 57 58 4696 4376 72 479 4697 4593 2 912 4697 4013 66 270 4698 4620 87 107 4699 1924 12 818 4699 1293 36 223 4700 3705 58 592 4701 1681 65 856 4702 2754 74 76 4702 1349 4 284 4703 1967 54 853 4703 713 100 532 4704 4571 36 30 4705 3854 58 367 4706 958 9 12 4706 2074 65 640 4707 4186 46 735 4708 2015 64 891 4709 4629 50 857 4709 2016 87 929 4710 3633 45 29 4710 1341 75 764 4711 2264 100 163 4712 2292 3 987 4712 2531 9 576 4713 308 27 864 4714 4363 1 47 4715 3969 5 661 4715 3246 57 513 4716 4027 84 454 4717 3459 69 375 4718 1657 17 473 4719 582 26 625 4720 2502 95 724 4721 1072 33 296 4721 4047 98 718 4722 1161 2 925 4722 2171 80 693 4723 2188 33 899 4723 353 87 211 4724 4661 75 351 4724 149 25 52 4725 4835 98 130 4726 674 99 338 4727 747 70 312 4728 3552 20 732 4728 2710 78 146 4729 4875 52 981 4729 588 73 298 4730 488 87 867 4730 3759 95 760 4731 2213 64 499 4732 3284 79 714 4733 1977 86 728 4734 3027 17 796 4734 241 45 555 4735 3009 25 730 4735 2708 70 545 4736 4062 83 606 4737 170 87 717 4738 2673 72 291 4739 332 48 3 4739 3614 22 719 4740 2019 94 274 4741 4711 68 667 4741 2979 97 561 4742 2610 98 402 4742 3733 81 721 4743 422 89 521 4744 4840 99 191 4745 3995 39 574 4745 4820 52 213 4746 4096 63 92 4747 2232 33 341 4747 1883 91 191 4748 4742 91 354 4748 2422 52 456 4749 359 76 690 4749 2935 40 695 4750 768 34 243 4750 216 46 269 4751 2415 53 877 4752 2603 100 277 4753 444 1 457 4753 4381 54 69 4754 2049 18 806 4755 4020 3 379 4755 4025 2 812 4756 807 1 573 4757 791 29 981 4757 3051 31 335 4758 4435 92 558 4759 2508 58 623 4759 1269 10 784 4760 4458 35 194 4761 1276 1 262 4762 1933 43 865 4763 3027 35 473 4763 3357 57 763 4764 2129 33 426 4764 1779 61 492 4765 1439 69 309 4766 3735 62 481 4767 290 61 87 4768 3468 30 381 4768 4764 71 336 4769 3174 4 894 4770 1548 46 997 4770 1880 6 383 4771 3178 45 292 4771 1391 17 246 4772 1018 88 461 4772 2981 20 287 4773 2308 26 795 4774 1318 56 294 4774 2971 23 329 4775 2779 8 36 4776 4112 70 67 4777 2427 39 798 4777 4820 10 391 4778 1183 43 224 4778 3692 74 919 4779 1397 33 442 4780 1435 21 285 4780 3217 6 171 4781 4538 15 152 4781 4739 62 567 4782 2485 86 628 4782 2650 19 841 4783 4364 47 381 4784 3134 53 749 4784 2008 16 400 4785 1288 22 295 4786 4460 33 789 4786 4068 1 416 4787 4462 38 50 4788 181 3 984 4788 2182 42 137 4789 378 62 786 4790 1337 14 916 4790 3097 11 52 4791 4632 37 949 4791 1446 97 27 4792 2441 77 984 4792 2691 94 796 4793 197 81 683 4794 618 73 534 4795 2931 57 867 4796 51 98 114 4796 289 5 982 4797 4885 40 736 4797 3879 63 308 4798 3205 39 985 4798 3994 80 799 4799 3525 35 226 4799 2566 36 338 4800 116 58 761 4800 2711 88 618 4801 348 10 931 4802 3915 33 266 4803 3149 6 622 4803 2932 74 255 4804 2219 95 354 4805 2768 33 675 4806 4942 81 956 4807 4341 47 509 4808 3147 43 458 4808 421 6 614 4809 90 19 330 4810 2901 11 914 4811 4607 36 817 4811 577 92 656 4812 3498 15 785 4812 4179 24 42 4813 4925 99 249 4814 3168 4 291 4815 2198 60 673 4815 4245 42 476 4816 1425 86 9 4816 1956 98 238 4817 4399 61 937 4818 4143 69 603 4819 1506 4 932 4819 809 63 9 4820 81 84 325 4820 2783 6 812 4821 686 37 704 4821 1006 55 591 4822 3896 30 428 4822 100 25 240 4823 3868 44 964 4824 3158 8 583 4824 3442 71 117 4825 451 91 899 4826 3955 79 584 4827 3181 83 466 4827 4499 87 387 4828 3449 90 158 4829 412 41 932 4830 409 72 829 4831 1715 44 345 4831 804 98 596 4832 2219 49 790 4832 3452 29 727 4833 11 27 43 4833 2348 47 218 4834 1701 70 32 4835 2067 96 554 4836 3940 31 587 4837 3810 6 896 4837 2985 2 508 4838 471 15 118 4838 2535 21 718 4839 2030 47 497 4839 4383 28 734 4840 877 22 520 4840 95 61 522 4841 4608 1 684 4841 1219 17 479 4842 3803 20 16 4843 4026 91 311 4843 778 60 911 4844 2047 27 658 4844 332 52 591 4845 136 87 466 4845 513 92 76 4846 2925 34 333 4846 1576 14 50 4847 1221 96 708 4847 198 1 953 4847 2218 55 70 4848 4738 36 474 4848 2336 93 65 4849 1302 72 977 4849 2039 58 449 4849 1851 35 140 4849 3412 89 798 4850 1737 92 726 4850 3178 46 366 4850 4388 62 796 4851 4048 51 146 4851 4246 7 573 4851 2394 73 228 4852 1136 72 689 4852 2551 30 556 4852 3371 75 844 4852 5 46 569 4853 2347 56 658 4854 3003 31 478 4854 4619 63 621 4854 3456 77 712 4854 3418 55 826 4855 600 82 500 4855 3040 69 543 4855 2470 44 83 4856 1244 13 789 4857 2603 74 549 4857 425 23 938 4857 2308 73 966 4857 2357 77 700 4858 2377 45 310 4858 955 39 507 4858 2854 95 789 4859 2490 42 918 4860 3414 48 810 4860 4042 9 121 4860 4105 82 41 4860 4637 88 753 4861 69 35 447 4862 1121 49 519 4862 2644 57 292 4862 1437 11 816 4862 2328 33 173 4863 4654 87 291 4863 933 26 304 4864 4907 58 443 4864 3143 85 8 4865 2056 48 567 4865 3866 84 80 4865 149 57 29 4865 3558 62 665 4866 1030 100 502 4866 931 68 784 4867 955 96 177 4867 1192 65 240 4867 2857 14 317 4868 1193 26 848 4868 3474 48 852 4868 2661 93 982 4869 4909 50 958 4869 4675 44 179 4869 34 44 597 4869 343 2 128 4870 25 93 419 4870 4605 30 553 4870 3756 1 463 4870 766 45 697 4871 1745 35 595 4871 4354 54 162 4872 571 56 539 4872 1574 15 383 4872 4251 88 112 4872 990 86 229 4873 2630 63 489 4873 690 46 817 4874 3352 26 678 4875 3758 41 153 4875 2338 64 803 4875 2811 67 196 4876 4 51 78 4876 1047 34 657 4877 807 12 42 4878 1808 50 398 4878 99 90 692 4879 2263 37 849 4879 2173 9 417 4879 3324 11 568 4880 2260 59 84 4880 2951 79 557 4880 2574 81 361 4880 2068 68 19 4881 3775 8 524 4881 4055 61 900 4882 2464 29 354 4882 986 61 24 4883 1389 34 991 4883 3138 62 659 4884 1594 27 186 4884 4229 95 483 4885 4544 60 20 4886 4021 37 514 4887 4565 92 77 4887 1490 2 711 4887 4745 2 556 4887 921 62 941 4888 1724 8 672 4888 2455 99 956 4888 4649 15 762 4888 2648 21 354 4889 3691 85 169 4890 238 4 644 4890 4651 61 734 4891 2464 71 461 4892 743 13 110 4892 4523 79 687 4893 83 90 464 4893 4276 89 172 4893 4860 53 63 4893 3447 81 728 4894 4481 33 46 4894 1995 11 472 4894 496 96 240 4894 1155 25 965 4895 1904 14 702 4895 4710 42 198 4895 2039 87 985 4896 1552 100 977 4896 1266 42 340 4897 2566 88 810 4897 474 95 273 4898 2809 48 781 4898 357 40 551 4899 3353 57 595 4899 3298 77 24 4900 3997 35 433 4900 271 80 355 4900 2285 44 821 4901 1509 9 274 4901 57 16 143 4902 577 30 910 4902 3591 85 848 4903 1032 53 2 4903 4016 98 746 4903 1795 45 741 4904 1862 22 759 4905 2646 90 910 4905 4603 92 815 4905 1409 78 570 4905 4914 70 468 4906 3472 82 172 4906 4494 63 20 4906 855 100 561 4906 1629 57 333 4907 2340 14 714 4908 3718 48 58 4908 2080 97 33 4909 1858 78 536 4909 2896 44 775 4910 182 50 127 4910 2602 58 429 4911 4466 68 406 4912 745 83 897 4913 562 19 815 4913 3213 36 965 4913 3535 30 815 4913 27 26 558 4914 2822 31 151 4914 3194 72 65 4914 4473 13 979 4915 1223 32 508 4916 1225 63 722 4916 4223 68 599 4917 1295 70 704 4917 692 41 748 4917 325 45 233 4918 1433 92 515 4918 4309 70 99 4919 4251 86 969 4920 1024 59 608 4920 2922 11 146 4920 411 59 13 4921 85 29 753 4921 889 29 244 4922 4258 50 167 4923 216 56 341 4924 4834 26 515 4924 362 51 372 4925 1249 21 294 4925 3098 73 132 4925 2168 6 90 4926 377 35 347 4927 3231 97 673 4928 2125 74 457 4928 4213 75 84 4929 2515 64 761 4930 4205 21 589 4931 4782 74 946 4931 2280 86 845 4931 1942 33 971 4932 380 73 498 4932 4165 59 346 4933 2839 81 36 4933 3209 4 143 4933 4789 48 142 4934 1171 4 747 4934 4190 73 353 4934 1298 52 163 4934 3297 48 275 4935 2907 7 919 4936 1284 3 138 4936 915 60 2 4936 1454 11 712 4936 690 67 782 4937 3599 39 876 4937 347 83 985 4937 2567 29 617 4937 3596 20 21 4938 2187 66 76 4938 2619 65 787 4939 3259 12 191 4939 3160 92 836 4940 98 31 590 4940 4649 46 625 4940 4570 56 757 4941 4612 51 718 4941 2776 66 665 4942 2294 36 810 4942 831 90 593 4942 1908 83 598 4943 266 80 719 4943 621 87 218 4943 1201 87 187 4943 598 16 245 4943 2074 29 477 4943 1189 46 487 4944 2072 71 98 4944 2204 57 458 4944 328 39 765 4945 509 93 792 4946 2197 16 455 4946 12 33 649 4946 4846 9 631 4946 4762 20 130 4946 4312 14 807 4947 2045 8 508 4947 3558 15 314 4947 4308 46 280 4947 90 6 360 4948 4384 69 456 4949 2198 5 369 4949 4790 60 443 4950 254 34 92 4950 3858 55 120 4950 469 82 606 4950 2233 22 729 4950 1012 26 450 4950 200 86 760 4951 4072 45 606 4951 4852 42 191 4951 1400 50 665 4951 81 21 329 4951 4263 96 94 4951 513 84 769 4952 668 41 914 4952 148 16 48 4952 417 49 59 4952 4483 78 355 4952 2041 48 573 4952 1087 61 781 4953 3711 55 102 4953 289 70 144 4953 4938 1 934 4953 3108 59 889 4954 1348 68 754 4954 2786 18 373 4954 2458 10 259 4954 3579 27 608 4954 4277 64 926 4955 2738 87 16 4955 1487 66 337 4955 888 96 963 4955 3910 16 664 4956 291 11 676 4956 1009 70 574 4957 2057 88 702 4957 4988 46 478 4957 1831 5 313 4957 3137 98 563 4957 3857 1 257 4957 4061 53 642 4958 3582 82 675 4958 862 66 53 4958 490 25 825 4958 776 57 173 4959 512 2 456 4960 4562 32 72 4960 2771 64 256 4960 4093 49 110 4960 809 49 585 4961 2283 38 113 4961 3036 68 435 4961 2222 5 678 4961 3 7 161 4961 305 100 753 4962 237 95 664 4963 2554 37 991 4963 862 65 939 4964 4630 11 211 4964 3311 95 354 4964 3669 22 798 4964 1097 9 294 4964 1872 20 722 4965 49 87 314 4965 3264 5 516 4965 440 85 117 4965 3561 51 200 4965 358 89 720 4965 1622 16 380 4966 1161 52 826 4966 751 31 5 4966 147 35 743 4966 2193 2 107 4966 4596 20 586 4967 1489 27 205 4967 294 99 199 4968 1976 93 889 4968 3284 47 255 4968 3479 31 538 4968 2487 65 233 4968 3998 88 677 4968 3645 12 165 4969 4191 20 832 4969 3700 20 180 4970 1983 74 978 4970 1820 63 841 4970 2301 81 508 4971 356 49 767 4972 2869 97 432 4972 1779 59 440 4972 1863 30 721 4972 478 61 685 4972 2717 19 875 4973 1467 50 43 4974 694 62 123 4974 898 80 262 4974 1660 50 397 4974 2919 81 750 4974 734 28 492 4975 68 42 973 4975 1124 11 439 4975 1985 39 527 4975 3420 33 667 4975 667 38 457 4975 1827 11 189 4976 1358 99 772 4977 4229 62 554 4977 1027 99 839 4977 437 18 265 4977 4104 10 451 4977 4686 92 416 4978 1321 50 471 4979 287 42 449 4979 499 58 29 4979 3565 27 573 4979 2454 27 954 4980 1180 65 415 4980 1399 9 101 4980 2282 37 613 4981 656 71 212 4981 1529 55 440 4982 4862 49 926 4982 3493 70 577 4983 2439 45 194 4983 2931 71 379 4983 4821 15 762 4983 349 13 209 4983 4898 19 453 4984 4473 12 803 4984 2327 96 591 4984 879 11 672 4985 4141 48 942 4985 3061 56 255 4985 1479 23 900 4985 4597 37 122 4985 2493 6 900 4985 702 55 344 4985 59 84 366 4986 1167 13 640 4986 4925 10 682 4986 2740 34 475 4987 27 84 826 4987 2071 20 261 4987 651 65 562 4987 3525 48 370 4988 108 41 222 4988 1414 53 287 4988 2533 8 106 4988 1369 100 880 4989 2128 35 661 4989 2035 50 532 4989 1380 46 553 4989 124 10 647 4990 2668 50 212 4990 4813 93 3 4990 166 73 517 4990 3247 96 207 4990 3672 66 371 4990 3954 81 951 4991 442 79 689 4991 776 88 899 4991 623 31 282 4992 4697 23 803 4992 1679 31 4 4992 3837 20 240 4992 4301 52 666 4992 2450 6 941 4992 2486 31 379 4992 4039 80 902 4992 3099 41 935 4993 2788 32 140 4993 3695 41 659 4993 3818 63 850 4993 2220 29 542 4993 4947 70 422 4993 1138 18 977 4993 4527 23 350 4994 2461 87 32 4994 1994 14 205 4994 3496 51 444 4994 3272 53 103 4994 119 50 608 4994 3680 87 167 4994 1391 45 176 4994 179 80 320 4995 521 71 322 4996 2229 51 221 4997 4620 76 382 4997 2967 75 729 4997 549 28 654 4997 2696 75 399 4997 3519 52 762 4997 3261 4 562 4998 2734 61 88 4998 2788 54 78 4998 1377 33 55 4998 858 45 411 4998 2349 68 165 4998 2497 47 155 4998 3671 33 789 4998 3096 52 971 4999 1557 14 710 4999 3386 15 339 4999 659 46 813 4999 985 72 672 5000 2885 15 816 5000 4900 49 879 5000 3070 83 269 5000 273 99 25 5000 509 48 345 5000 808 90 288 5000 2694 21 249 DEMAND 4501 4 4502 150 4503 668 4504 535 4505 285 4506 740 4507 8 4508 567 4509 1283 4510 961 4511 335 4512 586 4513 1085 4514 25 4515 877 4516 1882 4517 469 4518 661 4519 11 4520 464 4521 5 4522 309 4523 248 4524 87 4525 512 4526 620 4527 1261 4528 1070 4529 211 4530 630 4531 107 4532 96 4533 486 4534 357 4535 316 4536 295 4537 564 4538 750 4539 2 4540 500 4541 375 4542 1809 4543 266 4544 1552 4545 427 4546 136 4547 19 4548 313 4549 509 4550 15 4551 312 4552 269 4553 501 4554 1145 4555 5 4556 680 4557 1303 4558 302 4559 495 4560 213 4561 83 4562 5 4563 7 4564 669 4565 18 4566 286 4567 387 4568 393 4569 451 4570 562 4571 286 4572 411 4573 974 4574 120 4575 181 4576 693 4577 204 4578 1117 4579 376 4580 755 4581 466 4582 156 4583 1187 4584 709 4585 123 4586 1242 4587 704 4588 703 4589 51 4590 319 4591 476 4592 13 4593 72 4594 120 4595 28 4596 505 4597 373 4598 243 4599 1 4600 818 4601 1175 4602 1013 4603 662 4604 1058 4605 275 4606 400 4607 537 4608 926 4609 708 4610 124 4611 372 4612 5 4613 511 4614 595 4615 240 4616 328 4617 187 4618 20 4619 1109 4620 423 4621 210 4622 24 4623 1041 4624 40 4625 1668 4626 1592 4627 373 4628 149 4629 875 4630 760 4631 1163 4632 18 4633 1372 4634 1160 4635 91 4636 13 4637 922 4638 340 4639 504 4640 1460 4641 425 4642 586 4643 690 4644 112 4645 1332 4646 20 4647 268 4648 770 4649 839 4650 11 4651 737 4652 336 4653 66 4654 1849 4655 483 4656 853 4657 1214 4658 1 4659 592 4660 1574 4661 84 4662 806 4663 606 4664 9 4665 1301 4666 605 4667 382 4668 903 4669 295 4670 44 4671 474 4672 729 4673 4 4674 174 4675 632 4676 513 4677 553 4678 27 4679 336 4680 33 4681 143 4682 561 4683 1105 4684 939 4685 441 4686 109 4687 315 4688 187 4689 791 4690 520 4691 378 4692 1028 4693 619 4694 1623 4695 310 4696 625 4697 630 4698 23 4699 10 4700 1020 4701 664 4702 326 4703 43 4704 238 4705 1654 4706 753 4707 393 4708 244 4709 1164 4710 1917 4711 18 4712 5 4713 9 4714 237 4715 1083 4716 268 4717 130 4718 154 4719 416 4720 143 4721 34 4722 694 4723 6 4724 8 4725 669 4726 996 4727 266 4728 53 4729 400 4730 829 4731 798 4732 6 4733 817 4734 298 4735 442 4736 3 4737 861 4738 769 4739 26 4740 792 4741 962 4742 557 4743 539 4744 645 4745 442 4746 795 4747 6 4748 284 4749 667 4750 587 4751 16 4752 1663 4753 296 4754 569 4755 883 4756 3 4757 450 4758 258 4759 416 4760 551 4761 532 4762 568 4763 1450 4764 158 4765 584 4766 1087 4767 84 4768 147 4769 349 4770 456 4771 626 4772 7 4773 8 4774 1255 4775 8 4776 780 4777 710 4778 13 4779 11 4780 406 4781 438 4782 415 4783 52 4784 258 4785 238 4786 201 4787 296 4788 1360 4789 762 4790 936 4791 313 4792 598 4793 576 4794 915 4795 301 4796 135 4797 1025 4798 502 4799 776 4800 897 4801 15 4802 476 4803 759 4804 46 4805 271 4806 163 4807 883 4808 4 4809 292 4810 1850 4811 600 4812 3 4813 9 4814 13 4815 653 4816 423 4817 103 4818 4 4819 8 4820 67 4821 369 4822 205 4823 197 4824 700 4825 764 4826 982 4827 7 4828 1199 4829 1588 4830 1708 4831 579 4832 15 4833 1397 4834 1131 4835 264 4836 133 4837 179 4838 381 4839 340 4840 408 4841 893 4842 6 4843 569 4844 565 4845 223 4846 264 4847 87 4848 549 4849 231 4850 256 4851 247 4852 53 4853 529 4854 276 4855 1039 4856 1348 4857 4 4858 128 4859 10 4860 325 4861 98 4862 594 4863 427 4864 543 4865 6 4866 262 4867 211 4868 995 4869 1268 4870 1 4871 2 4872 108 4873 320 4874 1013 4875 1252 4876 428 4877 510 4878 13 4879 1459 4880 594 4881 20 4882 613 4883 560 4884 251 4885 12 4886 1023 4887 116 4888 186 4889 247 4890 100 4891 98 4892 1012 4893 1292 4894 138 4895 1555 4896 157 4897 13 4898 424 4899 17 4900 157 4901 707 4902 65 4903 364 4904 881 4905 770 4906 47 4907 314 4908 244 4909 706 4910 1571 4911 539 4912 6 4913 1057 4914 1669 4915 6 4916 1703 4917 30 4918 6 4919 406 4920 774 4921 10 4922 394 4923 716 4924 1055 4925 992 4926 380 4927 8 4928 1217 4929 36 4930 251 4931 217 4932 1274 4933 568 4934 958 4935 8 4936 1 4937 538 4938 204 4939 315 4940 713 4941 261 4942 15 4943 10 4944 1 4945 298 4946 875 4947 227 4948 1229 4949 712 4950 176 4951 985 4952 332 4953 484 4954 920 4955 581 4956 881 4957 154 4958 1138 4959 6 4960 789 4961 1528 4962 415 4963 471 4964 2 4965 1008 4966 361 4967 1049 4968 885 4969 151 4970 204 4971 396 4972 477 4973 11 4974 494 4975 514 4976 1155 4977 991 4978 12 4979 576 4980 402 4981 1074 4982 226 4983 543 4984 384 4985 228 4986 299 4987 919 4988 508 4989 129 4990 98 4991 205 4992 434 4993 853 4994 769 4995 314 4996 1138 4997 20 4998 1 4999 465 5000 121 END Clp-1.15.10/examples/hello.cpp0000644000076600007660000000346511402524254014507 0ustar coincoin/* $Id: hello.cpp 1559 2010-06-05 19:42:36Z stefan $ */ /* Copyright (C) 2004, International Business Machines Corporation and others. All Rights Reserved. This sample program is designed to illustrate programming techniques using CoinLP, has not been thoroughly tested and comes without any warranty whatsoever. You may copy, modify and distribute this sample program without any restrictions whatsoever and without any payment to anyone. */ /* This shows how to provide a simple picture of a matrix. The default matrix will print Hello World */ #include "ClpSimplex.hpp" int main(int argc, const char *argv[]) { ClpSimplex model; int status; // Keep names if (argc < 2) { status = model.readMps("hello.mps", true); } else { status = model.readMps(argv[1], true); } if (status) exit(10); int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); if (numberColumns > 80 || numberRows > 80) { printf("model too large\n"); exit(11); } printf("This prints x wherever a non-zero element exists in the matrix.\n\n\n"); char x[81]; int iRow; // get row copy CoinPackedMatrix rowCopy = *model.matrix(); rowCopy.reverseOrdering(); const int * column = rowCopy.getIndices(); const int * rowLength = rowCopy.getVectorLengths(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); x[numberColumns] = '\0'; for (iRow = 0; iRow < numberRows; iRow++) { memset(x, ' ', numberColumns); for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) { int iColumn = column[k]; x[iColumn] = 'x'; } printf("%s\n", x); } printf("\n\n"); return 0; } Clp-1.15.10/LICENSE0000644000076600007660000002622711507174377012105 0ustar coincoinEclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. Clp-1.15.10/Makefile.am0000644000076600007660000000771112253625222013116 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 2010 2013-12-16 16:30:10Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # Subdirectories # ######################################################################## SUBDIRS = src # Don't do src/OsiClp recursively, since src/OsiClp/libOsiClp depends on src/libClp if COIN_HAS_OSI SUBDIRS += src/OsiClp endif # 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 if ALWAYS_FALSE SUBDIRS += test endif ######################################################################## # 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/basicmodelclasses.xml \ doc/clpexe.xml \ doc/clpuserguide.xml \ doc/doxygen.xml \ doc/faqcontent.xml \ doc/faq.xml \ doc/intro.xml \ doc/legal.xml \ doc/messages.xml \ doc/moresamples.xml \ doc/notsobasic.xml \ doc/revhist.xml \ doc/Howto/docbook4clp.xml \ examples/addBits.cpp \ examples/addColumns.cpp \ examples/addRows.cpp \ examples/decompose.cpp \ examples/defaults.cpp \ examples/driver2.cpp \ examples/driverC.c \ examples/driver.cpp \ examples/dualCuts.cpp \ examples/ekk.cpp \ examples/ekk_interface.cpp \ examples/hello.cpp \ examples/hello.mps \ examples/input.130 \ examples/INSTALL \ examples/makeDual.cpp \ examples/Makefile.in \ examples/minimum.cpp \ examples/network.cpp \ examples/piece.cpp \ examples/rowColumn.cpp \ examples/sprint2.cpp \ examples/sprint.cpp \ examples/testBarrier.cpp \ examples/testBasis.cpp \ examples/testGub2.cpp \ examples/testGub.cpp \ examples/testQP.cpp \ examples/useVolume.cpp ######################################################################## # 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 ######################################################################## # Creation of the addlibs file # ######################################################################## pkgconfiglibdir = $(libdir)/pkgconfig pkgconfiglib_DATA = clp.pc if COIN_HAS_OSI pkgconfiglib_DATA += osi-clp.pc endif addlibsdir = $(DESTDIR)$(datadir)/coin/doc/Clp install-data-hook: @$(mkdir_p) "$(addlibsdir)" if COIN_HAS_PKGCONFIG PKG_CONFIG_PATH=@COIN_PKG_CONFIG_PATH@ \ $(PKG_CONFIG) --libs clp > $(addlibsdir)/clp_addlibs.txt else if COIN_CXX_IS_CL echo "-libpath:`$(CYGPATH_W) @abs_lib_dir@` libClp.lib @CLPLIB_LIBS_INSTALLED@" > $(addlibsdir)/clp_addlibs.txt else echo -L@abs_lib_dir@ -lClp @CLPLIB_LIBS_INSTALLED@ > $(addlibsdir)/clp_addlibs.txt endif endif uninstall-hook: rm -f $(addlibsdir)/clp_addlibs.txt ######################################################################## # Maintainer Stuff # ######################################################################## CLEANFILES = # Files that are generated and should be cleaned with make distclean DISTCLEANFILES = include BuildTools/Makemain.inc Clp-1.15.10/clp.pc.in0000644000076600007660000000046011510106324012553 0ustar coincoinprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/coin Name: CLP Description: COIN-OR Linear Programming Solver URL: https://projects.coin-or.org/Clp Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lClp @CLPLIB_PCLIBS@ Cflags: -I${includedir} Requires: @CLPLIB_PCREQUIRES@ Clp-1.15.10/configure.ac0000644000076600007660000001720612377500504013352 0ustar coincoin# Copyright (C) 2006 International Business Machines. # All Rights Reserved. # This file is distributed under the Eclipse Public License. ## $Id: configure.ac 2058 2014-08-28 01:09:24Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 ############################################################################# # Names and other basic things # ############################################################################# AC_PREREQ(2.59) AC_INIT([Clp],[1.15.10],[clp@list.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/ClpSimplex.cpp) # 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(Clp,13:10:12) # Check if user wants to produce debugging code AC_COIN_DEBUG_COMPILE(Clp) # 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(CoinUtils, [coinutils], [ClpLib]) if test $coin_has_coinutils != yes ; then AC_MSG_ERROR([Required package CoinUtils not available.]) fi AC_COIN_CHECK_PACKAGE(Osi, [osi], [OsiClpLib]) AC_COIN_CHECK_PACKAGE(OsiTests, [osi-unittests]) AC_COIN_CHECK_PACKAGE(Sample, [coindatasample]) AC_COIN_CHECK_PACKAGE(Netlib, [coindatanetlib]) ############################################################################# # Aboca # ############################################################################# # 1 - build Abc serial but no inherit code # 2 - build Abc serial and inherit code # 3 - build Abc cilk parallel but no inherit code # 4 - build Abc cilk parallel and inherit code AC_ARG_ENABLE([aboca], [AC_HELP_STRING([--enable-aboca],[enables build of Aboca solver (set to 1,2,3,4)])], [use_aboca=$enableval], [use_aboca=no]) if test "$use_aboca" = yes ; then use_aboca=1 fi case "$use_aboca" in 1 | 2 | 3 | 4) AC_DEFINE_UNQUOTED([CLP_HAS_ABC], [$use_aboca], [Define to 1, 2, 3, or 4 if Aboca should be build.]) ;; no) ;; *) AC_MSG_ERROR([invalid argument for --enable-aboca: $use_aboca]) ;; esac AM_CONDITIONAL(COIN_HAS_ABC, test ! "$use_aboca" = no) ############################################################################# # Third party linear solvers # ############################################################################# # AMD from UFL AC_COIN_CHECK_USER_LIBRARY(AMD, AMD, [amd.h], [amd_defaults],,[ClpLib]) # CHOLMOD from UFL # CHOLMOD requires AMD, which can be given by AMD_LIBS # CHOLMOD requires Blas and Lapack? coin_save_LIBS="$LIBS" LIBS="$LIBS $AMD_LIBS" AC_COIN_CHECK_USER_LIBRARY(CHOLMOD, CHOLMOD, [cholmod.h], [cholmod_start],,[ClpLib]) LIBS="$coin_save_LIBS" # Glpk also brings AMD if test $coin_has_cholmod = false -a $coin_has_amd = false ; then AC_COIN_CHECK_PACKAGE(Glpk, [coinglpk], [ClpLib]) if test $coin_has_glpk = yes ; then AC_MSG_NOTICE([using AMD from GLPK package]) AC_DEFINE(COIN_HAS_AMD,[1],[Define to 1 if the AMD package is available]) fi else # for configure AM_CONDITIONAL(COIN_HAS_GLPK, [test 0 = 1]) fi # MUMPS AC_COIN_CHECK_PACKAGE(Mumps, [coinmumps], [ClpLib]) # WSMP AC_ARG_WITH([wsmp], AC_HELP_STRING([--with-wsmp], [specify WSMP library]), [use_wsmp=$withval], [use_wsmp=no]) if test "$use_wsmp" != "no"; then # Check how to link against Fortran libraries from C AC_COIN_PROG_F77 AC_COIN_F77_WRAPPERS # WSMP requires Blas AC_COIN_CHECK_PACKAGE_BLAS(ClpLib) coin_save_LIBS="$LIBS" LIBS="$LIBS $use_wsmp $BLAS_LIBS" AC_LANG_PUSH([Fortran 77]) AC_MSG_CHECKING([whether user-supplied WSMP library \"$use_wsmp\" works]) AC_TRY_LINK([],[ call WSSMP()], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_MSG_ERROR([WSMP library $use_wsmp does not seem to work])]) AC_LANG_POP([Fortran 77]) LIBS="$coin_save_LIBS" AC_DEFINE_UNQUOTED([COIN_HAS_WSMP], [1], [Define to 1 if the WSMP package is available]) CLPLIB_LIBS="$use_wsmp $CLPLIB_LIBS" CLPLIB_LIBS_INSTALLED="$use_wsmp $CLPLIB_LIBS_INSTALLED" CLPLIB_PCLIBS="$use_wsmp $CLPLIB_PCLIBS" else # to please configure AM_CONDITIONAL(COIN_HAS_BLAS, [test 0 = 1]) fi AM_CONDITIONAL(COIN_HAS_WSMP, [test "$use_wsmp" != no]) ############################################################################# # Other dependencies # ############################################################################# AC_COIN_CHECK_GNU_READLINE(ClpLib) AC_COIN_CHECK_CXX_CHEADER(math) AC_COIN_CHECK_CXX_CHEADER(float) AC_COIN_CHECK_CXX_CHEADER(ieeefp) ############################################################################## # 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/hello.mps) AC_COIN_VPATH_LINK(examples/input.130) AC_COIN_VPATH_LINK(examples/g.tiny) AC_COIN_VPATH_LINK(examples/gparm.tiny) ############################################################################# # Check for doxygen # ############################################################################# AC_COIN_DOXYGEN(CoinUtils Osi) ############################################################################## # 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/OsiClp/Makefile test/Makefile clp.pc clp-uninstalled.pc]) if test $coin_has_osi = yes ; then AC_CONFIG_FILES([osi-clp.pc:src/OsiClp/osi-clp.pc.in osi-clp-uninstalled.pc:src/OsiClp/osi-clp-uninstalled.pc.in]) fi 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_clp.h]) # Finally, we let configure write all the output... AC_COIN_FINALIZE Clp-1.15.10/src/0000755000076600007660000000000012377556130011653 5ustar coincoinClp-1.15.10/src/ClpGubMatrix.hpp0000644000076600007660000003474511510657452014737 0ustar coincoin/* $Id: ClpGubMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpGubMatrix_H #define ClpGubMatrix_H #include "CoinPragma.hpp" #include "ClpPackedMatrix.hpp" class ClpSimplex; /** This implements Gub rows plus a ClpPackedMatrix. There will be a version using ClpPlusMinusOne matrix but there is no point doing one with ClpNetworkMatrix (although an embedded network is attractive). */ class ClpGubMatrix : public ClpPackedMatrix { public: /**@name Main functions provided */ //@{ /** Returns a new matrix in reverse order without gaps (GUB wants NULL) */ virtual ClpMatrixBase * reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis(const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const ; /** Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const ; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const; /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /// Returns number of hidden rows e.g. gub virtual int hiddenRows() const; //@} /**@name Matrix times vector methods */ //@{ using ClpPackedMatrix::transposeTimes ; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex. This version uses row copy*/ virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x *A in z but just for indices in y. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const; /** expands an updated column to allow for extra rows which the main solver does not know about and returns number added if mode 0. If mode 1 deletes extra entries This active in Gub */ virtual int extendUpdated(ClpSimplex * model, CoinIndexedVector * update, int mode); /** mode=0 - Set up before "update" and "times" for primal solution using extended rows mode=1 - Cleanup primal solution after "times" using extended rows. mode=2 - Check (or report on) primal infeasibilities */ virtual void primalExpanded(ClpSimplex * model, int mode); /** mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended updates array (and may use other if dual values pass) mode=1 - Update dual solution after "transposeTimes" using extended rows. mode=2 - Compute all djs and compute key dual infeasibilities mode=3 - Report on key dual infeasibilities mode=4 - Modify before updateTranspose in partial pricing */ virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, double * other, int mode); /** mode=0 - Create list of non-key basics in pivotVariable_ using number as numberBasic in and out mode=1 - Set all key variables as basic mode=2 - return number extra rows needed, number gives maximum number basic mode=3 - before replaceColumn mode=4 - return 1 if can do primal, 2 if dual, 3 if both mode=5 - save any status stuff (when in good state) mode=6 - restore status stuff mode=7 - flag given variable (normally sequenceIn) mode=8 - unflag all variables mode=9 - synchronize costs mode=10 - return 1 if there may be changing bounds on variable (column generation) mode=11 - make sure set is clean (used when a variable rejected - but not flagged) mode=12 - after factorize but before permute stuff mode=13 - at end of simplex to delete stuff */ virtual int generalExpanded(ClpSimplex * model, int mode, int & number); /** update information for a pivot (and effective rhs) */ virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); /// Sets up an effective RHS and does gub crash if needed virtual void useEffectiveRhs(ClpSimplex * model, bool cheapest = true); /** Returns effective RHS offset if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, bool check = false); /** This is local to Gub to allow synchronization: mode=0 when status of basis is good mode=1 when variable is flagged mode=2 when all variables unflagged (returns number flagged) mode=3 just reset costs (primal) mode=4 correct number of dual infeasibilities mode=5 return 4 if time to re-factorize mode=6 - return 1 if there may be changing bounds on variable (column generation) mode=7 - do extra restores for column generation mode=8 - make sure set is clean mode=9 - adjust lower, upper on set by incoming */ virtual int synchronize(ClpSimplex * model, int mode); /// Correct sequence in and out to give true value virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpGubMatrix(); /** Destructor */ virtual ~ClpGubMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpGubMatrix(const ClpGubMatrix&); /** The copy constructor from an CoinPackedMatrix. */ ClpGubMatrix(const CoinPackedMatrix&); /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpGubMatrix (const ClpGubMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); ClpGubMatrix (const CoinPackedMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); /** This takes over ownership (for space reasons) */ ClpGubMatrix(CoinPackedMatrix * matrix); /** This takes over ownership (for space reasons) and is the real constructor*/ ClpGubMatrix(ClpPackedMatrix * matrix, int numberSets, const int * start, const int * end, const double * lower, const double * upper, const unsigned char * status = NULL); ClpGubMatrix& operator=(const ClpGubMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; /** Subset clone (without gaps). Duplicates are allowed and order is as given */ virtual ClpMatrixBase * subsetClone ( int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const ; /** redoes next_ for a set. */ void redoSet(ClpSimplex * model, int newKey, int oldKey, int iSet); //@} /**@name gets and sets */ //@{ /// Status inline ClpSimplex::Status getStatus(int sequence) const { return static_cast (status_[sequence] & 7); } inline void setStatus(int sequence, ClpSimplex::Status status) { unsigned char & st_byte = status_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | status); } /// To flag a variable inline void setFlagged( int sequence) { status_[sequence] = static_cast(status_[sequence] | 64); } inline void clearFlagged( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~64); } inline bool flagged(int sequence) const { return ((status_[sequence] & 64) != 0); } /// To say key is above ub inline void setAbove( int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast(iStat & ~24); status_[sequence] = static_cast(iStat | 16); } /// To say key is feasible inline void setFeasible( int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast(iStat & ~24); status_[sequence] = static_cast(iStat | 8); } /// To say key is below lb inline void setBelow( int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast(iStat & ~24); status_[sequence] = iStat; } inline double weight( int sequence) const { int iStat = status_[sequence] & 31; iStat = iStat >> 3; return static_cast (iStat - 1); } /// Starts inline int * start() const { return start_; } /// End inline int * end() const { return end_; } /// Lower bounds on sets inline double * lower() const { return lower_; } /// Upper bounds on sets inline double * upper() const { return upper_; } /// Key variable of set inline int * keyVariable() const { return keyVariable_; } /// Backward pointer to set number inline int * backward() const { return backward_; } /// Number of sets (gub rows) inline int numberSets() const { return numberSets_; } /// Switches off dj checking each factorization (for BIG models) void switchOffCheck(); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Sum of dual infeasibilities double sumDualInfeasibilities_; /// Sum of primal infeasibilities double sumPrimalInfeasibilities_; /// Sum of Dual infeasibilities using tolerance based on error in duals double sumOfRelaxedDualInfeasibilities_; /// Sum of Primal infeasibilities using tolerance based on error in primals double sumOfRelaxedPrimalInfeasibilities_; /// Infeasibility weight when last full pass done double infeasibilityWeight_; /// Starts int * start_; /// End int * end_; /// Lower bounds on sets double * lower_; /// Upper bounds on sets double * upper_; /// Status of slacks mutable unsigned char * status_; /// Saved status of slacks unsigned char * saveStatus_; /// Saved key variables int * savedKeyVariable_; /// Backward pointer to set number int * backward_; /// Backward pointer to pivot row !!! int * backToPivotRow_; /// Change in costs for keys double * changeCost_; /// Key variable of set mutable int * keyVariable_; /** Next basic variable in set - starts at key and end with -(set+1). Now changes to -(nonbasic+1). next_ has extra space for 2* longest set */ mutable int * next_; /// Backward pointer to index in CoinIndexedVector int * toIndex_; // Reverse pointer from index to set int * fromIndex_; /// Pointer back to model ClpSimplex * model_; /// Number of dual infeasibilities int numberDualInfeasibilities_; /// Number of primal infeasibilities int numberPrimalInfeasibilities_; /** If pricing will declare victory (i.e. no check every factorization). -1 - always check 0 - don't check 1 - in don't check mode but looks optimal */ int noCheck_; /// Number of sets (gub rows) int numberSets_; /// Number in vector without gub extension int saveNumber_; /// Pivot row of possible next key int possiblePivotKey_; /// Gub slack in (set number or -1) int gubSlackIn_; /// First gub variables (same as start_[0] at present) int firstGub_; /// last gub variable (same as end_[numberSets_-1] at present) int lastGub_; /** type of gub - 0 not contiguous, 1 contiguous add 8 bit to say no ubs on individual variables */ int gubType_; //@} }; #endif Clp-1.15.10/src/AbcPrimalColumnPivot.cpp0000644000076600007660000000450712101105055016374 0ustar coincoin/* $Id: AbcPrimalColumnPivot.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "AbcSimplex.hpp" #include "AbcPrimalColumnPivot.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcPrimalColumnPivot::AbcPrimalColumnPivot () : model_(NULL), type_(-1), looksOptimal_(false) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcPrimalColumnPivot::AbcPrimalColumnPivot (const AbcPrimalColumnPivot & source) : model_(source.model_), type_(source.type_), looksOptimal_(source.looksOptimal_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcPrimalColumnPivot::~AbcPrimalColumnPivot () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcPrimalColumnPivot & AbcPrimalColumnPivot::operator=(const AbcPrimalColumnPivot& rhs) { if (this != &rhs) { type_ = rhs.type_; model_ = rhs.model_; looksOptimal_ = rhs.looksOptimal_; } return *this; } void AbcPrimalColumnPivot::saveWeights(AbcSimplex * model, int ) { model_ = model; } // checks accuracy and may re-initialize (may be empty) void AbcPrimalColumnPivot::updateWeights(CoinIndexedVector *) { } // Gets rid of all arrays void AbcPrimalColumnPivot::clearArrays() { } /* Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ int AbcPrimalColumnPivot::numberSprintColumns(int & ) const { return 0; } // Switch off sprint idea void AbcPrimalColumnPivot::switchOffSprint() { } Clp-1.15.10/src/ClpLinearObjective.hpp0000644000076600007660000000645411510657452016076 0ustar coincoin/* $Id: ClpLinearObjective.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpLinearObjective_H #define ClpLinearObjective_H #include "ClpObjective.hpp" //############################################################################# /** Linear Objective Class */ class ClpLinearObjective : public ClpObjective { public: ///@name Stuff //@{ /** Returns objective coefficients. Offset is always set to 0.0. All other parameters unused. */ virtual double * gradient(const ClpSimplex * model, const double * solution, double & offset, bool refresh, int includeLinear = 2); /** 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 ; /// Resize objective 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) ; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpLinearObjective(); /// Constructor from objective ClpLinearObjective(const double * objective, int numberColumns); /// Copy constructor ClpLinearObjective(const ClpLinearObjective &); /** Subset constructor. Duplicates are allowed and order is as given. */ ClpLinearObjective (const ClpLinearObjective &rhs, int numberColumns, const int * whichColumns) ; /// Assignment operator ClpLinearObjective & operator=(const ClpLinearObjective& rhs); /// Destructor virtual ~ClpLinearObjective (); /// Clone virtual ClpObjective * clone() const; /** Subset clone. Duplicates are allowed and order is as given. */ virtual ClpObjective * subsetClone (int numberColumns, const int * whichColumns) const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Objective double * objective_; /// number of columns int numberColumns_; //@} }; #endif Clp-1.15.10/src/ClpHelperFunctions.cpp0000644000076600007660000002117311654457077016141 0ustar coincoin/* $Id: ClpHelperFunctions.cpp 1817 2011-11-03 09:26:23Z forrest $ */ // 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). /* Note (JJF) I have added some operations on arrays even though they may duplicate CoinDenseVector. I think the use of templates was a mistake as I don't think inline generic code can take as much advantage of parallelism or machine architectures or memory hierarchies. */ #include #include #include #include "CoinHelperFunctions.hpp" #include "CoinTypes.hpp" double maximumAbsElement(const double * region, int size) { int i; double maxValue = 0.0; for (i = 0; i < size; i++) maxValue = CoinMax(maxValue, fabs(region[i])); return maxValue; } void setElements(double * region, int size, double value) { int i; for (i = 0; i < size; i++) region[i] = value; } void multiplyAdd(const double * region1, int size, double multiplier1, double * region2, double multiplier2) { int i; if (multiplier1 == 1.0) { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = region1[i] + multiplier2 * region2[i]; } } else if (multiplier1 == -1.0) { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = -region1[i] + multiplier2 * region2[i]; } } else if (multiplier1 == 0.0) { if (multiplier2 == 1.0) { // nothing to do } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = -region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = 0.0; } else { for (i = 0; i < size; i++) region2[i] = multiplier2 * region2[i]; } } else { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] + multiplier2 * region2[i]; } } } double innerProduct(const double * region1, int size, const double * region2) { int i; double value = 0.0; for (i = 0; i < size; i++) value += region1[i] * region2[i]; return value; } void getNorms(const double * region, int size, double & norm1, double & norm2) { norm1 = 0.0; norm2 = 0.0; int i; for (i = 0; i < size; i++) { norm2 += region[i] * region[i]; norm1 = CoinMax(norm1, fabs(region[i])); } } #ifndef NDEBUG #include "ClpModel.hpp" #include "ClpMessage.hpp" ClpModel * clpTraceModel=NULL; // Set to trap messages void ClpTracePrint(std::string fileName, std::string message, int lineNumber) { if (!clpTraceModel) { std::cout<messageHandler()->message(CLP_GENERAL_WARNING, clpTraceModel->messages()) << line << CoinMessageEol; } } #endif #if COIN_LONG_WORK // For long double versions CoinWorkDouble maximumAbsElement(const CoinWorkDouble * region, int size) { int i; CoinWorkDouble maxValue = 0.0; for (i = 0; i < size; i++) maxValue = CoinMax(maxValue, CoinAbs(region[i])); return maxValue; } void setElements(CoinWorkDouble * region, int size, CoinWorkDouble value) { int i; for (i = 0; i < size; i++) region[i] = value; } void multiplyAdd(const CoinWorkDouble * region1, int size, CoinWorkDouble multiplier1, CoinWorkDouble * region2, CoinWorkDouble multiplier2) { int i; if (multiplier1 == 1.0) { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = region1[i] + multiplier2 * region2[i]; } } else if (multiplier1 == -1.0) { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = -region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = -region1[i] + multiplier2 * region2[i]; } } else if (multiplier1 == 0.0) { if (multiplier2 == 1.0) { // nothing to do } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = -region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = 0.0; } else { for (i = 0; i < size; i++) region2[i] = multiplier2 * region2[i]; } } else { if (multiplier2 == 1.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] + region2[i]; } else if (multiplier2 == -1.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] - region2[i]; } else if (multiplier2 == 0.0) { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] ; } else { for (i = 0; i < size; i++) region2[i] = multiplier1 * region1[i] + multiplier2 * region2[i]; } } } CoinWorkDouble innerProduct(const CoinWorkDouble * region1, int size, const CoinWorkDouble * region2) { int i; CoinWorkDouble value = 0.0; for (i = 0; i < size; i++) value += region1[i] * region2[i]; return value; } void getNorms(const CoinWorkDouble * region, int size, CoinWorkDouble & norm1, CoinWorkDouble & norm2) { norm1 = 0.0; norm2 = 0.0; int i; for (i = 0; i < size; i++) { norm2 += region[i] * region[i]; norm1 = CoinMax(norm1, CoinAbs(region[i])); } } #endif #ifdef DEBUG_MEMORY #include #include #include typedef void (*NEW_HANDLER)(); static NEW_HANDLER new_handler; // function to call if `new' fails (cf. ARM p. 281) // Allocate storage. void * operator new(size_t size) { void * p; for (;;) { p = malloc(size); if (p) break; // success else if (new_handler) new_handler(); // failure - try again (allow user to release some storage first) else break; // failure - no retry } if (size > 1000000) printf("Allocating memory of size %d\n", size); return p; } // Deallocate storage. void operator delete(void *p) { free(p); return; } void operator delete [] (void *p) { free(p); return; } #endif Clp-1.15.10/src/CbcOrClpParam.hpp0000644000076600007660000004051112130015370014754 0ustar coincoin /* $Id: CbcOrClpParam.hpp 1928 2013-04-06 12:54: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). #ifdef USE_CBCCONFIG # include "CbcConfig.h" #else # include "ClpConfig.h" #endif #ifndef CbcOrClpParam_H #define CbcOrClpParam_H /** This has parameter handling stuff which can be shared between Cbc and Clp (and Dylp etc). This (and .cpp) should be copied so that it is the same in Cbc/Test and Clp/Test. I know this is not elegant but it seems simplest. It uses COIN_HAS_CBC for parameters wanted by CBC It uses COIN_HAS_CLP for parameters wanted by CLP (or CBC using CLP) It could use COIN_HAS_DYLP for parameters wanted by DYLP It could use COIN_HAS_DYLP_OR_CLP for parameters wanted by DYLP or CLP etc etc */ class OsiSolverInterface; class CbcModel; 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. */ enum CbcOrClpParameterType { CBC_PARAM_GENERALQUERY = -100, CBC_PARAM_FULLGENERALQUERY, CLP_PARAM_DBL_PRIMALTOLERANCE = 1, CLP_PARAM_DBL_DUALTOLERANCE, CLP_PARAM_DBL_TIMELIMIT, CLP_PARAM_DBL_DUALBOUND, CLP_PARAM_DBL_PRIMALWEIGHT, CLP_PARAM_DBL_OBJSCALE, CLP_PARAM_DBL_RHSSCALE, CLP_PARAM_DBL_ZEROTOLERANCE, CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, CBC_PARAM_DBL_CUTOFF, CBC_PARAM_DBL_INTEGERTOLERANCE, CBC_PARAM_DBL_INCREMENT, CBC_PARAM_DBL_ALLOWABLEGAP, CBC_PARAM_DBL_TIMELIMIT_BAB, CBC_PARAM_DBL_GAPRATIO, CBC_PARAM_DBL_DJFIX = 81, CBC_PARAM_DBL_TIGHTENFACTOR, CLP_PARAM_DBL_PRESOLVETOLERANCE, CLP_PARAM_DBL_OBJSCALE2, CBC_PARAM_DBL_FAKEINCREMENT, CBC_PARAM_DBL_FAKECUTOFF, CBC_PARAM_DBL_ARTIFICIALCOST, CBC_PARAM_DBL_DEXTRA3, CBC_PARAM_DBL_SMALLBAB, CBC_PARAM_DBL_DEXTRA4, CBC_PARAM_DBL_DEXTRA5, CLP_PARAM_INT_SOLVERLOGLEVEL = 101, #ifndef COIN_HAS_CBC CLP_PARAM_INT_LOGLEVEL = 101, #endif 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_INT_SUBSTITUTION, CLP_PARAM_INT_DUALIZE, CLP_PARAM_INT_VERBOSE, CLP_PARAM_INT_CPP, CLP_PARAM_INT_PROCESSTUNE, CLP_PARAM_INT_USESOLUTION, CLP_PARAM_INT_RANDOMSEED, CLP_PARAM_INT_MORESPECIALOPTIONS, CBC_PARAM_INT_STRONGBRANCHING = 151, CBC_PARAM_INT_CUTDEPTH, CBC_PARAM_INT_MAXNODES, CBC_PARAM_INT_NUMBERBEFORE, CBC_PARAM_INT_NUMBERANALYZE, CBC_PARAM_INT_MIPOPTIONS, CBC_PARAM_INT_MOREMIPOPTIONS, CBC_PARAM_INT_MAXHOTITS, CBC_PARAM_INT_FPUMPITS, CBC_PARAM_INT_MAXSOLS, CBC_PARAM_INT_FPUMPTUNE, CBC_PARAM_INT_TESTOSI, CBC_PARAM_INT_EXTRA1, CBC_PARAM_INT_EXTRA2, CBC_PARAM_INT_EXTRA3, CBC_PARAM_INT_EXTRA4, CBC_PARAM_INT_DEPTHMINIBAB, CBC_PARAM_INT_CUTPASSINTREE, CBC_PARAM_INT_THREADS, CBC_PARAM_INT_CUTPASS, CBC_PARAM_INT_VUBTRY, CBC_PARAM_INT_DENSE, CBC_PARAM_INT_EXPERIMENT, CBC_PARAM_INT_DIVEOPT, CBC_PARAM_INT_STRATEGY, CBC_PARAM_INT_SMALLFACT, CBC_PARAM_INT_HOPTIONS, CBC_PARAM_INT_CUTLENGTH, CBC_PARAM_INT_FPUMPTUNE2, #ifdef COIN_HAS_CBC CLP_PARAM_INT_LOGLEVEL , #endif CBC_PARAM_INT_MAXSAVEDSOLS, CBC_PARAM_INT_RANDOMSEED, CBC_PARAM_INT_MULTIPLEROOTS, CBC_PARAM_INT_STRONG_STRATEGY, CBC_PARAM_INT_EXTRA_VARIABLES, CBC_PARAM_INT_MAX_SLOW_CUTS, 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_STR_INTPRINT, CLP_PARAM_STR_VECTOR, CLP_PARAM_STR_FACTORIZATION, CLP_PARAM_STR_ALLCOMMANDS, CLP_PARAM_STR_TIME_MODE, CLP_PARAM_STR_ABCWANTED, CBC_PARAM_STR_NODESTRATEGY = 251, CBC_PARAM_STR_BRANCHSTRATEGY, CBC_PARAM_STR_CUTSSTRATEGY, CBC_PARAM_STR_HEURISTICSTRATEGY, CBC_PARAM_STR_GOMORYCUTS, CBC_PARAM_STR_PROBINGCUTS, CBC_PARAM_STR_KNAPSACKCUTS, CBC_PARAM_STR_REDSPLITCUTS, 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, CBC_PARAM_STR_FPUMP, CBC_PARAM_STR_GREEDY, CBC_PARAM_STR_COMBINE, CBC_PARAM_STR_PROXIMITY, CBC_PARAM_STR_LOCALTREE, CBC_PARAM_STR_SOS, CBC_PARAM_STR_LANDPCUTS, CBC_PARAM_STR_RINS, CBC_PARAM_STR_RESIDCUTS, CBC_PARAM_STR_RENS, CBC_PARAM_STR_DIVINGS, CBC_PARAM_STR_DIVINGC, CBC_PARAM_STR_DIVINGF, CBC_PARAM_STR_DIVINGG, CBC_PARAM_STR_DIVINGL, CBC_PARAM_STR_DIVINGP, CBC_PARAM_STR_DIVINGV, CBC_PARAM_STR_DINS, CBC_PARAM_STR_PIVOTANDFIX, CBC_PARAM_STR_RANDROUND, CBC_PARAM_STR_NAIVE, CBC_PARAM_STR_ZEROHALFCUTS, CBC_PARAM_STR_CPX, CBC_PARAM_STR_CROSSOVER2, CBC_PARAM_STR_PIVOTANDCOMPLEMENT, CBC_PARAM_STR_VND, CBC_PARAM_STR_LAGOMORYCUTS, CBC_PARAM_STR_LATWOMIRCUTS, CBC_PARAM_STR_REDSPLIT2CUTS, CBC_PARAM_STR_GMICUTS, CBC_PARAM_STR_CUTOFF_CONSTRAINT, CLP_PARAM_ACTION_DIRECTORY = 301, CLP_PARAM_ACTION_DIRSAMPLE, CLP_PARAM_ACTION_DIRNETLIB, CBC_PARAM_ACTION_DIRMIPLIB, 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_EITHERSIMPLEX, CLP_PARAM_ACTION_MAXIMIZE, CLP_PARAM_ACTION_MINIMIZE, CLP_PARAM_ACTION_EXIT, CLP_PARAM_ACTION_STDIN, CLP_PARAM_ACTION_UNITTEST, CLP_PARAM_ACTION_NETLIB_EITHER, CLP_PARAM_ACTION_NETLIB_DUAL, CLP_PARAM_ACTION_NETLIB_PRIMAL, CLP_PARAM_ACTION_SOLUTION, CLP_PARAM_ACTION_SAVESOL, 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_NETLIB_TUNE, CLP_PARAM_ACTION_REALLY_SCALE, CLP_PARAM_ACTION_BASISIN, CLP_PARAM_ACTION_BASISOUT, CLP_PARAM_ACTION_SOLVECONTINUOUS, CLP_PARAM_ACTION_CLEARCUTS, CLP_PARAM_ACTION_VERSION, CLP_PARAM_ACTION_STATISTICS, CLP_PARAM_ACTION_DEBUG, CLP_PARAM_ACTION_DUMMY, CLP_PARAM_ACTION_PRINTMASK, CLP_PARAM_ACTION_OUTDUPROWS, CLP_PARAM_ACTION_USERCLP, CLP_PARAM_ACTION_MODELIN, CLP_PARAM_ACTION_CSVSTATISTICS, CLP_PARAM_ACTION_STOREDFILE, CLP_PARAM_ACTION_ENVIRONMENT, CLP_PARAM_ACTION_PARAMETRICS, CLP_PARAM_ACTION_GMPL_SOLUTION, CBC_PARAM_ACTION_BAB = 351, CBC_PARAM_ACTION_MIPLIB, CBC_PARAM_ACTION_STRENGTHEN, CBC_PARAM_ACTION_PRIORITYIN, CBC_PARAM_ACTION_MIPSTART, CBC_PARAM_ACTION_USERCBC, CBC_PARAM_ACTION_DOHEURISTIC, CLP_PARAM_ACTION_NEXTBESTSOLUTION, CBC_PARAM_NOTUSED_OSLSTUFF = 401, CBC_PARAM_NOTUSED_CBCSTUFF, CBC_PARAM_NOTUSED_INVALID = 1000 } ; #include #include /// Very simple class for setting parameters class CbcOrClpParam { public: /**@name Constructor and destructor */ //@{ /// Constructors CbcOrClpParam ( ); CbcOrClpParam (std::string name, std::string help, double lower, double upper, CbcOrClpParameterType type, int display = 2); CbcOrClpParam (std::string name, std::string help, int lower, int upper, CbcOrClpParameterType type, int display = 2); // Other strings will be added by insert CbcOrClpParam (std::string name, std::string help, std::string firstValue, CbcOrClpParameterType type, int whereUsed = 7, int display = 2); // Action CbcOrClpParam (std::string name, std::string help, CbcOrClpParameterType type, int whereUsed = 7, int display = 2); /// Copy constructor. CbcOrClpParam(const CbcOrClpParam &); /// Assignment operator. This copies the data CbcOrClpParam & operator=(const CbcOrClpParam & rhs); /// Destructor ~CbcOrClpParam ( ); //@} /**@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) ; /// Sets double parameter and returns printable string and error code const char * setDoubleParameterWithMessage ( CbcModel & model, double value , int & returnCode); /// Gets a double parameter double doubleParameter(CbcModel & model) const; /// Sets a int parameter (nonzero code if error) int setIntParameter(CbcModel & model, int value) ; /// Sets int parameter and returns printable string and error code const char * setIntParameterWithMessage ( CbcModel & model, int value , int & returnCode); /// Gets a int parameter int intParameter(CbcModel & model) const; /// Sets a double parameter (nonzero code if error) int setDoubleParameter(ClpSimplex * model, double value) ; /// Gets a double parameter double doubleParameter(ClpSimplex * model) const; /// Sets double parameter and returns printable string and error code const char * setDoubleParameterWithMessage ( ClpSimplex * model, double value , int & returnCode); /// Sets a int parameter (nonzero code if error) int setIntParameter(ClpSimplex * model, int value) ; /// Sets int parameter and returns printable string and error code const char * setIntParameterWithMessage ( ClpSimplex * model, int value , int & returnCode); /// Gets a int parameter int intParameter(ClpSimplex * model) const; /// Sets a double parameter (nonzero code if error) int setDoubleParameter(OsiSolverInterface * model, double value) ; /// Sets double parameter and returns printable string and error code const char * setDoubleParameterWithMessage ( OsiSolverInterface * model, double value , int & returnCode); /// Gets a double parameter double doubleParameter(OsiSolverInterface * model) const; /// Sets a int parameter (nonzero code if error) int setIntParameter(OsiSolverInterface * model, int value) ; /// Sets int parameter and returns printable string and error code const char * setIntParameterWithMessage ( OsiSolverInterface * model, int value , int & returnCode); /// 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 length of name for ptinting int lengthMatchName ( ) 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 void setCurrentOption ( int value , bool printIt = false); /// Sets current parameter option and returns printable string const char * setCurrentOptionWithMessage ( int value ); /// Sets current parameter option using string void setCurrentOption (const std::string value ); /// Returns current parameter option position inline int currentOptionAsInteger ( ) const { return currentKeyWord_; } /// Sets int value void setIntValue ( int value ); inline int intValue () const { return intValue_; } /// Sets double value void setDoubleValue ( double value ); inline double doubleValue () const { return doubleValue_; } /// Sets string value void setStringValue ( std::string 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 CbcOrClpParameterType type() const { return type_; } /// whether to display inline int 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; /** 7 if used everywhere, 1 - used by clp 2 - used by cbc 4 - used by ampl */ inline int whereUsed() const { return whereUsed_; } private: /// gutsOfConstructor void gutsOfConstructor(); //@} ////////////////// data ////////////////// private: /**@name data We might as well throw all type data in - could derive? */ //@{ // Type see CbcOrClpParameterType CbcOrClpParameterType 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 CbcOrClpParameterType action_; /// Current keyWord (if a keyword parameter) int currentKeyWord_; /// Display on ? int display_; /// Integer parameter - current value int intValue_; /// Double parameter - current value double doubleValue_; /// String parameter - current value std::string stringValue_; /** 7 if used everywhere, 1 - used by clp 2 - used by cbc 4 - used by ampl */ int whereUsed_; //@} }; /// Simple read stuff std::string CoinReadNextField(); std::string CoinReadGetCommand(int argc, const char *argv[]); std::string CoinReadGetString(int argc, const char *argv[]); // valid 0 - okay, 1 bad, 2 not there int CoinReadGetIntField(int argc, const char *argv[], int * valid); double CoinReadGetDoubleField(int argc, const char *argv[], int * valid); void CoinReadPrintit(const char * input); void setCbcOrClpPrinting(bool yesNo); #define CBCMAXPARAMETERS 250 /* Subroutine to establish the cbc parameter array. See the description of class CbcOrClpParam for details. Pulled from C..Main() for clarity. */ void establishParams (int &numberParameters, CbcOrClpParam *const parameters); // Given a parameter type - returns its number in list int whichParam (CbcOrClpParameterType name, int numberParameters, CbcOrClpParam *const parameters); // Dump a solution to file void saveSolution(const ClpSimplex * lpSolver, std::string fileName); #endif /* CbcOrClpParam_H */ Clp-1.15.10/src/AbcDualRowSteepest.cpp0000644000076600007660000013420712101105055016043 0ustar coincoin/* $Id: AbcDualRowSteepest.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "AbcSimplex.hpp" #include "ClpMessage.hpp" #include "AbcDualRowSteepest.hpp" #include "CoinIndexedVector.hpp" #include "AbcSimplexFactorization.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //#define CLP_DEBUG 2 //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcDualRowSteepest::AbcDualRowSteepest (int mode) : AbcDualRowPivot(), norm_(0.0), factorizationRatio_(10.0), state_(-1), mode_(mode), persistence_(normal), weights_(NULL), infeasible_(NULL), savedWeights_(NULL) { type_ = 2 + 64 * mode; //printf("XX %x AbcDualRowSteepest constructor\n",this); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcDualRowSteepest::AbcDualRowSteepest (const AbcDualRowSteepest & rhs) : AbcDualRowPivot(rhs) { //printf("XX %x AbcDualRowSteepest constructor from %x\n",this,&rhs); norm_ = rhs.norm_; factorizationRatio_ = rhs.factorizationRatio_; state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; model_ = rhs.model_; if ((model_ && model_->whatsChanged() & 1) != 0) { int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_) { weights_ = new CoinIndexedVector(rhs.weights_); } else { weights_ = NULL; } if (rhs.savedWeights_) { savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); } else { savedWeights_ = NULL; } } else { infeasible_ = NULL; weights_ = NULL; savedWeights_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcDualRowSteepest::~AbcDualRowSteepest () { //printf("XX %x AbcDualRowSteepest destructor\n",this); delete weights_; delete infeasible_; delete savedWeights_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcDualRowSteepest & AbcDualRowSteepest::operator=(const AbcDualRowSteepest& rhs) { if (this != &rhs) { AbcDualRowPivot::operator=(rhs); norm_ = rhs.norm_; factorizationRatio_ = rhs.factorizationRatio_; state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; model_ = rhs.model_; delete weights_; delete infeasible_; delete savedWeights_; assert(model_); int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_ != NULL) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_ != NULL) { weights_ = new CoinIndexedVector(rhs.weights_); } else { weights_ = NULL; } if (rhs.savedWeights_ != NULL) { savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); } else { savedWeights_ = NULL; } } return *this; } // Fill most values void AbcDualRowSteepest::fill(const AbcDualRowSteepest& rhs) { norm_ = rhs.norm_; factorizationRatio_ = rhs.factorizationRatio_; state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; assert (model_->numberRows() == rhs.model_->numberRows()); model_ = rhs.model_; assert(model_); int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_ != NULL) { if (!infeasible_) infeasible_ = new CoinIndexedVector(rhs.infeasible_); else *infeasible_ = *rhs.infeasible_; } else { delete infeasible_; infeasible_ = NULL; } if (rhs.weights_ != NULL) { if (!weights_) weights_ = new CoinIndexedVector(rhs.weights_); } else { delete weights_; weights_ = NULL; } if (rhs.savedWeights_ != NULL) { if (!savedWeights_) savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); else *savedWeights_ = *rhs.savedWeights_; } else { delete savedWeights_; savedWeights_ = NULL; } } #ifdef CHECK_NUMBER_WANTED static int xTimes=0; static int xWanted=0; #endif #if ABC_PARALLEL==2 #define DO_REDUCE 2 #ifdef DO_REDUCE #if DO_REDUCE==1 #include static void choose(int & chosenRow,double & largest, int n, const int * index, const double * infeas, const double * weights,double tolerance) { cilk::reducer_max_index maximumIndex(chosenRow,largest); #pragma cilk_grainsize=128 cilk_for (int i = 0; i < n; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > tolerance) { double thisWeight = CoinMin(weights[iRow], 1.0e50); maximumIndex.calc_max(iRow,value/thisWeight); } } chosenRow=maximumIndex.get_index(); largest=maximumIndex.get_value(); } #else static void choose(AbcDualRowSteepest * steepest, int & chosenRowSave,double & largestSave, int first, int last, double tolerance) { if (last-first>256) { int mid=(last+first)>>1; int chosenRow2=chosenRowSave; double largest2=largestSave; cilk_spawn choose(steepest,chosenRow2,largest2, first, mid, tolerance); choose(steepest,chosenRowSave,largestSave, mid, last, tolerance); cilk_sync; if (largest2>largestSave) { largestSave=largest2; chosenRowSave=chosenRow2; } } else { const int * index=steepest->infeasible()->getIndices(); const double * infeas=steepest->infeasible()->denseVector(); const double * weights=steepest->weights()->denseVector(); double largest=largestSave; int chosenRow=chosenRowSave; if ((steepest->model()->stateOfProblem()&VALUES_PASS2)==0) { for (int i = first; i < last; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > tolerance) { double thisWeight = CoinMin(weights[iRow], 1.0e50); if (value>largest*thisWeight) { largest=value/thisWeight; chosenRow=iRow; } } } } else { const double * fakeDjs = steepest->model()->fakeDjs(); const int * pivotVariable = steepest->model()->pivotVariable(); for (int i = first; i < last; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > tolerance) { int iSequence=pivotVariable[iRow]; value *=(fabs(fakeDjs[iSequence])+1.0e-6); double thisWeight = CoinMin(weights[iRow], 1.0e50); /* Ideas always use fake use fake until chosen if successful would move djs to basic region? how to switch off if cilking - easiest at saveWeights */ if (value>largest*thisWeight) { largest=value/thisWeight; chosenRow=iRow; } } } } chosenRowSave=chosenRow; largestSave=largest; } } static void choose2(AbcDualRowSteepest * steepest, int & chosenRowSave,double & largestSave, int first, int last, double tolerance) { if (last-first>256) { int mid=(last+first)>>1; int chosenRow2=chosenRowSave; double largest2=largestSave; cilk_spawn choose2(steepest,chosenRow2,largest2, first, mid, tolerance); choose2(steepest,chosenRowSave,largestSave, mid, last, tolerance); cilk_sync; if (largest2>largestSave) { largestSave=largest2; chosenRowSave=chosenRow2; } } else { const int * index=steepest->infeasible()->getIndices(); const double * infeas=steepest->infeasible()->denseVector(); double largest=largestSave; int chosenRow=chosenRowSave; for (int i = first; i < last; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > largest) { largest=value; chosenRow=iRow; } } chosenRowSave=chosenRow; largestSave=largest; } } #endif #endif #endif // Returns pivot row, -1 if none int AbcDualRowSteepest::pivotRow() { assert(model_); double * COIN_RESTRICT infeas = infeasible_->denseVector(); int * COIN_RESTRICT index = infeasible_->getIndices(); int number = infeasible_->getNumElements(); int lastPivotRow = model_->lastPivotRow(); assert (lastPivotRow < model_->numberRows()); double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error // this coding has to mimic coding in checkPrimalSolution double error = CoinMin(1.0e-2, model_->largestPrimalError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // But cap tolerance = CoinMin(1000.0, tolerance); tolerance *= tolerance; // as we are using squares bool toleranceChanged = false; const double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); // do last pivot row one here if (lastPivotRow >= 0 && lastPivotRow < model_->numberRows()) { double value = solutionBasic[lastPivotRow]; double lower = lowerBasic[lastPivotRow]; double upper = upperBasic[lastPivotRow]; if (value > upper + tolerance) { value -= upper; value *= value; // store square in list if (infeas[lastPivotRow]) infeas[lastPivotRow] = value; // already there else infeasible_->quickAdd(lastPivotRow, value); } else if (value < lower - tolerance) { value -= lower; value *= value; // store square in list if (infeas[lastPivotRow]) infeas[lastPivotRow] = value; // already there else infeasible_->add(lastPivotRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[lastPivotRow]) infeas[lastPivotRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } number = infeasible_->getNumElements(); } if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error if (model_->largestDualError() > model_->largestPrimalError()) { tolerance *= CoinMin(model_->largestDualError() / model_->largestPrimalError(), 1000.0); toleranceChanged = true; } } int numberWanted; if (mode_ < 2 ) { numberWanted = number + 1; } else { if (model_->factorization()->pivots()==0) { int numberElements = model_->factorization()->numberElements(); int numberRows = model_->numberRows(); #if 0 int numberSlacks = model_->factorization()->numberSlacks(); factorizationRatio_ = static_cast (numberElements+1) / static_cast (numberRows+1-numberSlacks); #else factorizationRatio_ = static_cast (numberElements) / static_cast (numberRows); #endif //printf("%d iterations, numberElements %d ratio %g\n", // model_->numberIterations(),numberElements,factorizationRatio_); // Bias so less likely to go to steepest if large double weights[]={1.0,2.0,5.0}; double modifier; if (numberRows<100000) modifier=weights[0]; else if (numberRows<200000) modifier=weights[1]; else modifier=weights[2]; if (mode_==2&&factorizationRatio_>modifier) { // switch from dantzig to steepest mode_=3; saveWeights(model_,5); } } #if 0 // look at this and modify numberWanted = number+1; if (factorizationRatio_ < 1.0) { numberWanted = CoinMax(2000, numberRows / 20); #if 0 } else if (factorizationRatio_ > 10.0) { double ratio = number * (factorizationRatio_ / 80.0); if (ratio > number) numberWanted = number + 1; else numberWanted = CoinMax(2000, static_cast (ratio)); #else } else { //double multiplier=CoinMin(factorizationRatio_*0.1,1.0) #endif } #else numberWanted = CoinMax(2000, number / 8); if (factorizationRatio_ < 1.5) { numberWanted = CoinMax(2000, number / 20); } else if (factorizationRatio_ > 5.0) { numberWanted = number + 1; } #endif numberWanted=CoinMin(numberWanted,number+1); } if (model_->largestPrimalError() > 1.0e-3) numberWanted = number + 1; // be safe #ifdef CHECK_NUMBER_WANTED xWanted+=numberWanted; xTimes++; if ((xTimes%1000)==0) printf("time %d average wanted %g\n",xTimes,static_cast(xWanted)/xTimes); #endif int iPass; // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; //double largestWeight=0.0; //double smallestWeight=1.0e100; const double * weights = weights_->denseVector(); const int * pivotVariable = model_->pivotVariable(); double savePivotWeight=weights_->denseVector()[lastPivotRow]; weights_->denseVector()[lastPivotRow] *= 1.0e10; double largest = 0.0; int chosenRow = -1; int saveNumberWanted=numberWanted; #ifdef DO_REDUCE bool doReduce=true; int lastChosen=-1; double lastLargest=0.0; #endif for (iPass = 0; iPass < 2; iPass++) { int endThis = start[2*iPass+1]; int startThis=start[2*iPass]; while (startThis=0); if (model_->flagged(pivotVariable[chosenRow])|| (solutionBasic[chosenRow] <= upperBasic[chosenRow] + tolerance && solutionBasic[chosenRow] >= lowerBasic[chosenRow] - tolerance)) { doReduce=false; chosenRow=lastChosen; largest=lastLargest; } else { lastChosen=chosenRow; lastLargest=largest; } } } if (!doReduce) { #endif for (int i = startThis; i < end; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > tolerance) { //#define OUT_EQ #ifdef OUT_EQ if (upper[iRow] == lower[iRow]) value *= 2.0; #endif double thisWeight = CoinMin(weights[iRow], 1.0e50); //largestWeight = CoinMax(largestWeight,weight); //smallestWeight = CoinMin(smallestWeight,weight); //double dubious = dubiousWeights_[iRow]; //weight *= dubious; //if (value>2.0*largest*weight||(value>0.5*largest*weight&&value*largestWeight>dubious*largest*weight)) { if (value > largest * thisWeight) { // make last pivot row last resort choice //if (iRow == lastPivotRow) { //if (value * 1.0e-10 < largest * thisWeight) // continue; //else // value *= 1.0e-10; //} if (!model_->flagged(pivotVariable[iRow])) { //#define CLP_DEBUG 3 #ifdef CLP_DEBUG double value2 = 0.0; if (solutionBasic[iRow] > upperBasic[iRow] + tolerance) value2 = solutionBasic[iRow] - upperBasic[iRow]; else if (solutionBasic[iRow] < lowerBasic[iRow] - tolerance) value2 = solutionBasic[iRow] - lowerBasic[iRow]; assert(fabs(value2 * value2 - infeas[iRow]) < 1.0e-8 * CoinMin(value2 * value2, infeas[iRow])); #endif if (solutionBasic[iRow] > upperBasic[iRow] + tolerance || solutionBasic[iRow] < lowerBasic[iRow] - tolerance) { chosenRow = iRow; largest = value / thisWeight; //largestWeight = dubious; } } } } } #ifdef DO_REDUCE } #endif numberWanted-=(end-startThis); if (!numberWanted) { if(chosenRow>=0) break; else numberWanted=(saveNumberWanted+1)>>1; } startThis=end; } if (!numberWanted) { if(chosenRow>=0) break; else numberWanted=(saveNumberWanted+1)>>1; } } weights_->denseVector()[lastPivotRow]=savePivotWeight; //printf("smallest %g largest %g\n",smallestWeight,largestWeight); if (chosenRow < 0 && toleranceChanged) { // won't line up with checkPrimalSolution - do again double saveError = model_->largestDualError(); model_->setLargestDualError(0.0); // can't loop chosenRow = pivotRow(); model_->setLargestDualError(saveError); } if (chosenRow < 0 && lastPivotRow < 0) { int nLeft = 0; for (int i = 0; i < number; i++) { int iRow = index[i]; if (fabs(infeas[iRow]) > 1.0e-50) { index[nLeft++] = iRow; } else { infeas[iRow] = 0.0; } } infeasible_->setNumElements(nLeft); model_->setNumberPrimalInfeasibilities(nLeft); } if (true&&(model_->stateOfProblem()&VALUES_PASS2)!=0) { if (chosenRow>=0) { double * fakeDjs = model_->fakeDjs(); //const int * pivotVariable = model_->pivotVariable(); fakeDjs[pivotVariable[chosenRow]]=0.0; } } return chosenRow; } //#define PRINT_WEIGHTS_FREQUENCY #ifdef PRINT_WEIGHTS_FREQUENCY int xweights1=0; int xweights2=0; int xweights3=0; #endif /* Updates weights and returns pivot alpha. Also does FT update */ double AbcDualRowSteepest::updateWeights(CoinIndexedVector & input, CoinIndexedVector & updateColumn) { double * COIN_RESTRICT weights = weights_->denseVector(); #if CLP_DEBUG>2 // Very expensive debug { int numberRows = model_->numberRows(); CoinIndexedVector temp; temp.reserve(numberRows); double * array = temp.denseVector(); int * which = temp.getIndices(); for (int i = 0; i < numberRows; i++) { double value = 0.0; array[i] = 1.0; which[0] = i; temp.setNumElements(1); model_->factorization()->updateColumnTranspose(temp); int number = temp.getNumElements(); for (int j = 0; j < number; j++) { int iRow = which[j]; value += array[iRow] * array[iRow]; array[iRow] = 0.0; } temp.setNumElements(0); double w = CoinMax(weights[i], value) * .1; if (fabs(weights[i] - value) > w) { printf("%d old %g, true %g\n", i, weights[i], value); weights[i] = value; // to reduce printout } } } #endif double alpha = 0.0; double norm = 0.0; int i; double * COIN_RESTRICT work2 = input.denseVector(); int numberNonZero = input.getNumElements(); int * COIN_RESTRICT which = input.getIndices(); //compute norm for (int i = 0; i < numberNonZero; i ++ ) { int iRow = which[i]; double value = work2[iRow]; norm += value * value; } // Do FT update if (true) { model_->factorization()->updateTwoColumnsFT(updateColumn,input); #if CLP_DEBUG>3 printf("REGION after %d els\n", input.getNumElements()); input.print(); #endif } else { // Leave as old way model_->factorization()->updateColumnFT(updateColumn); model_->factorization()->updateColumn(input); } //#undef CLP_DEBUG numberNonZero = input.getNumElements(); int pivotRow = model_->lastPivotRow(); assert (model_->pivotRow()==model_->lastPivotRow()); #ifdef CLP_DEBUG if ( model_->logLevel ( ) > 4 && fabs(norm - weights[pivotRow]) > 1.0e-2 * (1.0 + norm)) printf("on row %d, true weight %g, old %g\n", pivotRow, sqrt(norm), sqrt(weights[pivotRow])); #endif // could re-initialize here (could be expensive) norm /= model_->alpha() * model_->alpha(); assert(model_->alpha()); assert(norm); double multiplier = 2.0 / model_->alpha(); #ifdef PRINT_WEIGHTS_FREQUENCY xweights1++; if ((xweights1+xweights2+xweights3)%100==0) { printf("ZZ iteration %d sum weights %d - %d %d %d\n", model_->numberIterations(),xweights1+xweights2+xweights3,xweights1,xweights2,xweights3); assert(abs(model_->numberIterations()-(xweights1+xweights2+xweights3))<=1); } #endif // look at updated column double * COIN_RESTRICT work = updateColumn.denseVector(); numberNonZero = updateColumn.getNumElements(); which = updateColumn.getIndices(); // pivot element alpha=work[pivotRow]; for (i = 0; i < numberNonZero; i++) { int iRow = which[i]; double theta = work[iRow]; double devex = weights[iRow]; //work3[iRow] = devex; // save old //which3[nSave++] = iRow; double value = work2[iRow]; devex += theta * (theta * norm + value * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights[iRow] = devex; } if (norm < DEVEX_TRY_NORM) norm = DEVEX_TRY_NORM; // Try this to make less likely will happen again and stop cycling //norm *= 1.02; weights[pivotRow] = norm; input.clear(); #ifdef CLP_DEBUG input.checkClear(); #endif #ifdef CLP_DEBUG input.checkClear(); #endif return alpha; } double AbcDualRowSteepest::updateWeights1(CoinIndexedVector & input,CoinIndexedVector & updateColumn) { if (mode_==2) { abort(); // no update // Do FT update model_->factorization()->updateColumnFT(updateColumn); // pivot element double alpha = 0.0; // look at updated column double * work = updateColumn.denseVector(); int pivotRow = model_->lastPivotRow(); assert (pivotRow == model_->pivotRow()); assert (!updateColumn.packedMode()); alpha = work[pivotRow]; return alpha; } #if CLP_DEBUG>2 // Very expensive debug { double * weights = weights_->denseVector(); int numberRows = model_->numberRows(); const int * pivotVariable = model_->pivotVariable(); CoinIndexedVector temp; temp.reserve(numberRows); double * array = temp.denseVector(); int * which = temp.getIndices(); for (int i = 0; i < numberRows; i++) { double value = 0.0; array[i] = 1.0; which[0] = i; temp.setNumElements(1); model_->factorization()->updateColumnTranspose(temp); int number = temp.getNumElements(); for (int j = 0; j < number; j++) { int iRow = which[j]; value += array[iRow] * array[iRow]; array[iRow] = 0.0; } temp.setNumElements(0); double w = CoinMax(weights[i], value) * .1; if (fabs(weights[i] - value) > w) { printf("XX row %d (variable %d) old %g, true %g\n", i, pivotVariable[i], weights[i], value); weights[i] = value; // to reduce printout } } } #endif norm_ = 0.0; double * COIN_RESTRICT work2 = input.denseVector(); int numberNonZero = input.getNumElements(); int * COIN_RESTRICT which = input.getIndices(); //compute norm for (int i = 0; i < numberNonZero; i ++ ) { int iRow = which[i]; double value = work2[iRow]; norm_ += value * value; } // Do FT update if (true) { model_->factorization()->updateTwoColumnsFT(updateColumn,input); #if CLP_DEBUG>3 printf("REGION after %d els\n", input.getNumElements()); input.print(); #endif } else { // Leave as old way model_->factorization()->updateColumnFT(updateColumn); model_->factorization()->updateWeights(input); } // pivot element assert (model_->pivotRow()==model_->lastPivotRow()); return updateColumn.denseVector()[model_->lastPivotRow()]; } void AbcDualRowSteepest::updateWeightsOnly(CoinIndexedVector & input) { if (mode_==2) return; norm_ = 0.0; double * COIN_RESTRICT work2 = input.denseVector(); int numberNonZero = input.getNumElements(); int * COIN_RESTRICT which = input.getIndices(); //compute norm for (int i = 0; i < numberNonZero; i ++ ) { int iRow = which[i]; double value = work2[iRow]; norm_ += value * value; } model_->factorization()->updateWeights(input); } // Actually updates weights void AbcDualRowSteepest::updateWeights2(CoinIndexedVector & input,CoinIndexedVector & updateColumn) { if (mode_==2) return; double * COIN_RESTRICT weights = weights_->denseVector(); const double * COIN_RESTRICT work2 = input.denseVector(); int pivotRow = model_->lastPivotRow(); assert (model_->pivotRow()==model_->lastPivotRow()); #ifdef CLP_DEBUG if ( model_->logLevel ( ) > 4 && fabs(norm_ - weights[pivotRow]) > 1.0e-2 * (1.0 + norm_)) printf("on row %d, true weight %g, old %g\n", pivotRow, sqrt(norm_), sqrt(weights[pivotRow])); #endif // pivot element double alpha=model_->alpha(); // could re-initialize here (could be expensive) norm_ /= alpha * alpha; assert(alpha); assert(norm_); double multiplier = 2.0 / alpha; // look at updated column const double * COIN_RESTRICT work = updateColumn.denseVector(); int numberNonZero = updateColumn.getNumElements(); const int * which = updateColumn.getIndices(); double multiplier2=1.0; #ifdef PRINT_WEIGHTS_FREQUENCY xweights2++; if ((xweights1+xweights2+xweights3)%100==0) { printf("ZZ iteration %d sum weights %d - %d %d %d\n", model_->numberIterations(),xweights1+xweights2+xweights3,xweights1,xweights2,xweights3); assert(abs(model_->numberIterations()-(xweights1+xweights2+xweights3))<=1); } #endif if (model_->directionOut()<0) { #ifdef ABC_DEBUG printf("Minus out in %d %d, out %d %d\n",model_->sequenceIn(),model_->directionIn(), model_->sequenceOut(),model_->directionOut()); #endif multiplier2=-1.0; } for (int i = 0; i < numberNonZero; i++) { int iRow = which[i]; double theta = multiplier2*work[iRow]; double devex = weights[iRow]; double value = work2[iRow]; devex += theta * (theta * norm_ + value * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights[iRow] = devex; } if (norm_ < DEVEX_TRY_NORM) norm_ = DEVEX_TRY_NORM; // Try this to make less likely will happen again and stop cycling //norm_ *= 1.02; weights[pivotRow] = norm_; input.clear(); #ifdef CLP_DEBUG input.checkClear(); #endif } /* Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ void AbcDualRowSteepest::updatePrimalSolution( CoinIndexedVector & primalUpdate, double primalRatio) { double * COIN_RESTRICT work = primalUpdate.denseVector(); int number = primalUpdate.getNumElements(); int * COIN_RESTRICT which = primalUpdate.getIndices(); double tolerance = model_->currentPrimalTolerance(); double * COIN_RESTRICT infeas = infeasible_->denseVector(); double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); assert (!primalUpdate.packedMode()); for (int i = 0; i < number; i++) { int iRow = which[i]; double value = solutionBasic[iRow]; double change = primalRatio * work[iRow]; // no need to keep for steepest edge work[iRow] = 0.0; value -= change; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; solutionBasic[iRow] = value; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } // Do pivot row int iRow = model_->lastPivotRow(); assert (model_->pivotRow()==model_->lastPivotRow()); // feasible - was it infeasible - if so set tiny //assert (infeas[iRow]); if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; primalUpdate.setNumElements(0); } #if ABC_PARALLEL==2 static void update(int first, int last, const int * COIN_RESTRICT which, double * COIN_RESTRICT work, const double * COIN_RESTRICT work2, double * COIN_RESTRICT weights, const double * COIN_RESTRICT lowerBasic,double * COIN_RESTRICT solutionBasic, const double * COIN_RESTRICT upperBasic, double multiplier,double multiplier2, double norm,double theta,double tolerance) { if (last-first>256) { int mid=(last+first)>>1; cilk_spawn update(first,mid,which,work,work2,weights,lowerBasic,solutionBasic, upperBasic,multiplier,multiplier2,norm,theta,tolerance); update(mid,last,which,work,work2,weights,lowerBasic,solutionBasic, upperBasic,multiplier,multiplier2,norm,theta,tolerance); cilk_sync; } else { for (int i = first; i < last; i++) { int iRow = which[i]; double updateValue = work[iRow]; double thetaDevex = multiplier2*updateValue; double devex = weights[iRow]; double valueDevex = work2[iRow]; devex += thetaDevex * (thetaDevex * norm + valueDevex * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights[iRow] = devex; double value = solutionBasic[iRow]; double change = theta * updateValue; value -= change; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; solutionBasic[iRow] = value; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif } else { // feasible value=0.0; } // store square work[iRow]=value; } } } #endif void AbcDualRowSteepest::updatePrimalSolutionAndWeights(CoinIndexedVector & weightsVector, CoinIndexedVector & primalUpdate, double theta) { //printf("updatePrimal iteration %d - weightsVector has %d, primalUpdate has %d\n", // model_->numberIterations(),weightsVector.getNumElements(),primalUpdate.getNumElements()); double * COIN_RESTRICT weights = weights_->denseVector(); double * COIN_RESTRICT work2 = weightsVector.denseVector(); int pivotRow = model_->lastPivotRow(); assert (model_->pivotRow()==model_->lastPivotRow()); double * COIN_RESTRICT work = primalUpdate.denseVector(); int numberNonZero = primalUpdate.getNumElements(); int * COIN_RESTRICT which = primalUpdate.getIndices(); double tolerance = model_->currentPrimalTolerance(); double * COIN_RESTRICT infeas = infeasible_->denseVector(); double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); assert (!primalUpdate.packedMode()); #ifdef CLP_DEBUG if ( model_->logLevel ( ) > 4 && fabs(norm_ - weights[pivotRow]) > 1.0e-2 * (1.0 + norm_)) printf("on row %d, true weight %g, old %g\n", pivotRow, sqrt(norm_), sqrt(weights[pivotRow])); #endif // pivot element double alpha=model_->alpha(); // could re-initialize here (could be expensive) norm_ /= alpha * alpha; assert(alpha); assert(norm_); double multiplier = 2.0 / alpha; #ifdef PRINT_WEIGHTS_FREQUENCY // only weights3 is used? - slightly faster to just update weights if going to invert xweights3++; if ((xweights1+xweights2+xweights3)%1000==0) { printf("ZZ iteration %d sum weights %d - %d %d %d\n", model_->numberIterations(),xweights1+xweights2+xweights3,xweights1,xweights2,xweights3); assert(abs(model_->numberIterations()-(xweights1+xweights2+xweights3))<=1); } #endif // look at updated column double multiplier2=1.0; if (model_->directionOut()<0) { #ifdef ABC_DEBUG printf("Minus out in %d %d, out %d %d\n",model_->sequenceIn(),model_->directionIn(), model_->sequenceOut(),model_->directionOut()); #endif multiplier2=-1.0; } #if ABC_PARALLEL==2 update(0,numberNonZero,which,work,work2,weights, lowerBasic,solutionBasic,upperBasic, multiplier,multiplier2,norm_,theta,tolerance); for (int i = 0; i < numberNonZero; i++) { int iRow = which[i]; double infeasibility=work[iRow]; work[iRow]=0.0; if (infeasibility) { if (infeas[iRow]) infeas[iRow] = infeasibility; // already there else infeasible_->quickAdd(iRow, infeasibility); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } #else for (int i = 0; i < numberNonZero; i++) { int iRow = which[i]; double updateValue = work[iRow]; work[iRow]=0.0; double thetaDevex = multiplier2*updateValue; double devex = weights[iRow]; double valueDevex = work2[iRow]; devex += thetaDevex * (thetaDevex * norm_ + valueDevex * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights[iRow] = devex; double value = solutionBasic[iRow]; double change = theta * updateValue; value -= change; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; solutionBasic[iRow] = value; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } #endif weightsVector.clear(); primalUpdate.setNumElements(0); #ifdef CLP_DEBUG weightsVector.checkClear(); #endif // Do pivot row if (norm_ < DEVEX_TRY_NORM) norm_ = DEVEX_TRY_NORM; // Try this to make less likely will happen again and stop cycling //norm_ *= 1.02; weights[pivotRow] = norm_; // feasible - was it infeasible - if so set tiny //assert (infeas[iRow]); if (infeas[pivotRow]) infeas[pivotRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; // see 1/2 above primalUpdate.setNumElements(0); } extern void parallelDual5(AbcSimplexFactorization * factorization, CoinIndexedVector ** whichVector, int numberCpu, int whichCpu, double * weights); /* Saves any weights round factorization as pivot rows may change 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights */ void AbcDualRowSteepest::saveWeights(AbcSimplex * model, int mode) { model_ = model; int numberRows = model_->numberRows(); // faster to save indices in array numberTotal in length const int * pivotVariable = model_->pivotVariable(); double * weights = weights_ ? weights_->denseVector() : NULL; // see if we need to switch //if (mode_==2&&mode==2) { // switch //mode=5; //} if (mode == 1) { if(weights_) { // Check if size has changed if (infeasible_->capacity() == numberRows) { // change from row numbers to sequence numbers CoinAbcMemcpy(weights_->getIndices(),pivotVariable,numberRows); state_ = 1; } else { // size has changed - clear everything delete weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete savedWeights_; savedWeights_ = NULL; state_ = -1; } } } else if (mode !=3) { // restore if (!weights_ || state_ == -1 || mode == 5) { // see if crash basis??? int numberBasicSlacks=0; bool initializeNorms=false; for (int i=0;igetInternalStatus(i)==AbcSimplex::basic) numberBasicSlacks++; } if (numberBasicSlacksnumberIterations()) { char line[100]; if (numberBasicSlacks>numberRows-(numberRows>>1)&&mode_==3&& (model_->moreSpecialOptions()&256)==0) { sprintf(line,"Steep initial basis has %d structurals out of %d - initializing norms\n",numberRows-numberBasicSlacks,numberRows); initializeNorms=true; } else { sprintf(line,"Steep initial basis has %d structurals out of %d - too many\n",numberRows-numberBasicSlacks,numberRows); } model_->messageHandler()->message(CLP_GENERAL2,*model_->messagesPointer()) << line << CoinMessageEol; } // initialize weights delete weights_; delete savedWeights_; delete infeasible_; weights_ = new CoinIndexedVector(); weights_->reserve(numberRows); savedWeights_ = new CoinIndexedVector(); // allow for dense multiple of 8! savedWeights_->reserve(numberRows+((initializeNorms) ? 8 : 0)); infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberRows); weights = weights_->denseVector(); if (mode == 5||(mode_!=1&&!initializeNorms)) { // initialize to 1.0 (can we do better?) for (int i = 0; i < numberRows; i++) { weights[i] = 1.0; } } else { double * COIN_RESTRICT array = savedWeights_->denseVector(); int * COIN_RESTRICT which = savedWeights_->getIndices(); // Later look at factorization to see which can be skipped // also use threads to parallelize #if 0 // use infeasible to collect row counts int * COIN_RESTRICT counts = infeasible_->getIndices(); CoinAbcMemset0(counts,numberRows); // get matrix data pointers int maximumRows = model_->maximumAbcNumberRows(); const CoinBigIndex * columnStart = model_->abcMatrix()->getPackedMatrix()->getVectorStarts()-maximumRows; //const int * columnLength = model_->abcMatrix()->getPackedMatrix()->getVectorLengths()-maximumRows; const int * row = model_->abcMatrix()->getPackedMatrix()->getIndices(); const int * pivotVariable = model_->pivotVariable(); for (int i = 0; i < numberRows; i++) { int iSequence = pivotVariable[i]; if (iSequence>=numberRows) { for (CoinBigIndex j=columnStart[iSequence];jparallelMode()==0) { #endif for (int i = 0; i < numberRows; i++) { double value = 0.0; array[i] = 1.0; which[0] = i; savedWeights_->setNumElements(1); model_->factorization()->updateColumnTranspose(*savedWeights_); int number = savedWeights_->getNumElements(); for (int j = 0; j < number; j++) { int k= which[j]; value += array[k] * array[k]; array[k] = 0.0; } #if 0 if (!counts[i]) { assert (value==1.0); nSlack++; } #endif savedWeights_->setNumElements(0); weights[i] = value; } #if ABC_PARALLEL==2 } else { // parallel // get arrays int numberCpuMinusOne=CoinMin(model_->parallelMode(),3); int which[3]; CoinIndexedVector * whichVector[4]; for (int i=0;igetAvailableArray(); whichVector[i]=model_->usefulArray(which[i]); assert(!whichVector[i]->packedMode()); } whichVector[numberCpuMinusOne]=savedWeights_; parallelDual5(model_->factorization(),whichVector,numberCpuMinusOne+1,numberCpuMinusOne,weights); for (int i=0;iclearArrays(which[i]); } #endif #if 0 printf("Steep %d can be skipped\n",nSlack); #endif } } else { int useArray=model_->getAvailableArrayPublic(); CoinIndexedVector * usefulArray = model_->usefulArray(useArray); int * COIN_RESTRICT which = usefulArray->getIndices(); double * COIN_RESTRICT element = usefulArray->denseVector(); if (mode!=4) { CoinAbcMemcpy(which,weights_->getIndices(),numberRows); CoinAbcScatterTo(weights_->denseVector(),element,which,numberRows); } else { // restore weights CoinAbcMemcpy(which,savedWeights_->getIndices(),numberRows); CoinAbcScatterTo(savedWeights_->denseVector(),element,which,numberRows); } for (int i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; double thisWeight=element[iPivot]; if (thisWeight) { if (thisWeight < DEVEX_TRY_NORM) thisWeight = DEVEX_TRY_NORM; // may need to check more weights[i] = thisWeight; } else { // odd weights[i] = 1.0; } } if (0) { double w[1000]; int s[1000]; assert (numberRows<=1000); memcpy(w,weights,numberRows*sizeof(double)); memcpy(s,pivotVariable,numberRows*sizeof(int)); CoinSort_2(s,s+numberRows,w); printf("Weights===========\n"); for (int i=0;isetNumElements(numberRows); usefulArray->clear(); // won't be done in parallel model_->clearArraysPublic(useArray); } state_ = 0; CoinAbcMemcpy(savedWeights_->denseVector(),weights_->denseVector(),numberRows); CoinAbcMemcpy(savedWeights_->getIndices(),pivotVariable,numberRows); } if (mode >= 2) { infeasible_->clear(); double tolerance = model_->currentPrimalTolerance(); const double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); if ((model_->stateOfProblem()&VALUES_PASS2)==0) { for (int iRow = 0; iRow < numberRows; iRow++) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } } } else { // check values pass const double * fakeDjs = model_->fakeDjs(); int numberFake=0; for (int iRow = 0; iRow < numberRows; iRow++) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; if (value < lower - tolerance) { value -= lower; } else if (value > upper + tolerance) { value -= upper; } else { value=0.0; } if (value) { value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); int iSequence=pivotVariable[iRow]; double fakeDj=fakeDjs[iSequence]; if (fabs(fakeDj)>10.0*tolerance) numberFake++; } } if (numberFake) printf("%d fake basic djs\n",numberFake); else model_->setStateOfProblem(model_->stateOfProblem()&~VALUES_PASS2); } } } // Recompute infeasibilities void AbcDualRowSteepest::recomputeInfeasibilities() { int numberRows = model_->numberRows(); infeasible_->clear(); double tolerance = model_->currentPrimalTolerance(); const double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); for (int iRow = 0; iRow < numberRows; iRow++) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } } } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- AbcDualRowPivot * AbcDualRowSteepest::clone(bool CopyData) const { if (CopyData) { return new AbcDualRowSteepest(*this); } else { return new AbcDualRowSteepest(); } } // Gets rid of all arrays void AbcDualRowSteepest::clearArrays() { if (persistence_ == normal) { delete weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete savedWeights_; savedWeights_ = NULL; } state_ = -1; } // Returns true if would not find any row bool AbcDualRowSteepest::looksOptimal() const { int iRow; double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error // this coding has to mimic coding in checkPrimalSolution double error = CoinMin(1.0e-2, model_->largestPrimalError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // But cap tolerance = CoinMin(1000.0, tolerance); int numberRows = model_->numberRows(); int numberInfeasible = 0; const double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); for (iRow = 0; iRow < numberRows; iRow++) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; if (value < lower - tolerance) { numberInfeasible++; } else if (value > upper + tolerance) { numberInfeasible++; } } return (numberInfeasible == 0); } Clp-1.15.10/src/config_default.h0000644000076600007660000000145012101105055014752 0ustar coincoin /* include the COIN-OR-wide system specific configure header */ #include "configall_system.h" /* include the public project specific macros */ #include "config_clp_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_CLP_CHECKLEVEL 0 /* Define to the debug verbosity level (0 is no output) */ #define COIN_CLP_VERBOSITY 0 /* Define to 1 if the CoinUtils package is used */ #define COIN_HAS_COINUTILS 1 /* Define to 1 if Clp is used */ #define COIN_HAS_CLP 1 Clp-1.15.10/src/AbcSimplexDual.hpp0000644000076600007660000002715412101105055015207 0ustar coincoin/* $Id: AbcSimplexDual.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef AbcSimplexDual_H #define AbcSimplexDual_H #include "AbcSimplex.hpp" #if 0 #undef ABC_PARALLEL #define ABC_PARALLEL 2 #undef cilk_for #undef cilk_spawn #undef cilk_sync #include #endif typedef struct { double theta; double totalThru; double useThru; double bestEverPivot; double increaseInObjective; double tentativeTheta; double lastPivotValue; double thisPivotValue; double thruThis; double increaseInThis; int lastSequence; int sequence; int block; int numberSwapped; int numberRemaining; int numberLastSwapped; bool modifyCosts; } dualColumnResult; /** This solves LPs using the dual simplex method It inherits from AbcSimplex. It has no data of its own and is never created - only cast from a AbcSimplex object at algorithm time. */ class AbcSimplexDual : public AbcSimplex { public: /**@name Description of algorithm */ //@{ /** Dual algorithm Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of updatedDualBound_ being given to getting dual feasible. In this version I have used the idea that this weight can be thought of as a fake bound. If the distance between the lower and upper bounds on a variable is less than the feasibility weight then we are always better off flipping to other bound to make dual feasible. If the distance is greater then we make up a fake bound updatedDualBound_ away from one bound. If we end up optimal or primal infeasible, we check to see if bounds okay. If so we have finished, if not we increase updatedDualBound_ and continue (after checking if unbounded). I am undecided about free variables - there is coding but I am not sure about it. At present I put them in basis anyway. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find outgoing variable for Dantzig row choice. For steepest edge we keep an updated list of infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and some of what I think is the dual analog of Gill et al. I am still not sure of the exact details. The flow of dual is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by flipping variables so dual feasible. If looks finished check fake dual bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot row (outgoing variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot row in tableau Choose incoming column. If we don't find one then we look primal infeasible so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find incoming column, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve flipping variables to stay dual feasible. } } TODO's (or maybe not) At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot out option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. for use of exotic parameter startFinishoptions see Abcsimplex.hpp */ int dual(); /** For strong branching. On input lower and upper are new bounds while on output they are change in objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) Solutions are filled in as well - even down, odd up - also status and number of iterations */ int strongBranching(int numberVariables, const int * variables, double * newLower, double * newUpper, double ** outputSolution, int * outputStatus, int * outputIterations, bool stopOnFirstInfeasible = true, bool alwaysFinish = false, int startFinishOptions = 0); /// This does first part of StrongBranching AbcSimplexFactorization * setupForStrongBranching(char * arrays, int numberRows, int numberColumns, bool solveLp = false); /// This cleans up after strong branching void cleanupAfterStrongBranching(AbcSimplexFactorization * factorization); //@} /**@name Functions used in dual */ //@{ /** This has the flow between re-factorizations Broken out for clarity and will be used by strong branching Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations If givenPi not NULL then in values pass (copy from ClpSimplexDual) */ int whileIteratingSerial(); #if ABC_PARALLEL==1 int whileIteratingThread(); #endif #if ABC_PARALLEL==2 int whileIteratingCilk(); #endif void whileIterating2(); int whileIteratingParallel(int numberIterations); int whileIterating3(); void updatePrimalSolution(); int noPivotRow(); int noPivotColumn(); void dualPivotColumn(); /// Create dual pricing vector void createDualPricingVectorSerial(); int getTableauColumnFlipAndStartReplaceSerial(); void getTableauColumnPart1Serial(); #if ABC_PARALLEL==1 /// Create dual pricing vector void createDualPricingVectorThread(); int getTableauColumnFlipAndStartReplaceThread(); void getTableauColumnPart1Thread(); #endif #if ABC_PARALLEL==2 /// Create dual pricing vector void createDualPricingVectorCilk(); int getTableauColumnFlipAndStartReplaceCilk(); void getTableauColumnPart1Cilk(); #endif void getTableauColumnPart2(); int checkReplace(); void replaceColumnPart3(); void checkReplacePart1(); void checkReplacePart1a(); void checkReplacePart1b(); /// The duals are updated void updateDualsInDual(); /** The duals are updated by the given arrays. This is in values pass - so no changes to primal is made */ //void updateDualsInValuesPass(CoinIndexedVector * array, // double theta); /** While dualColumn gets flips this does actual flipping. returns number flipped */ int flipBounds(); /** Undo a flip */ void flipBack(int number); /** Array has tableau row (row section) Puts candidates for rows in list Returns guess at upper theta (infinite if no pivot) and may set sequenceIn_ if free Can do all (if tableauRow created) */ void dualColumn1(bool doAll=false); /** Array has tableau row (row section) Just does slack part Returns guess at upper theta (infinite if no pivot) and may set sequenceIn_ if free */ double dualColumn1A(); /// Do all given tableau row double dualColumn1B(); /** Chooses incoming Puts flipped ones in list If necessary will modify costs */ void dualColumn2(); void dualColumn2Most(dualColumnResult & result); void dualColumn2First(dualColumnResult & result); /** Chooses part of incoming Puts flipped ones in list If necessary will modify costs */ void dualColumn2(dualColumnResult & result); /** This sees what is best thing to do in branch and bound cleanup If sequenceIn_ < 0 then can't do anything */ void checkPossibleCleanup(CoinIndexedVector * array); /** Chooses dual pivot row Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first rows we look at */ void dualPivotRow(); /** Checks if any fake bounds active - if so returns number and modifies updatedDualBound_ and everything. Free variables will be left as free Returns number of bounds changed if >=0 Returns -1 if not initialize and no effect fills cost of change vector */ int changeBounds(int initialize, double & changeCost); /** As changeBounds but just changes new bounds for a single variable. Returns true if change */ bool changeBound( int iSequence); /// Restores bound to original bound void originalBound(int iSequence); /** Checks if tentative optimal actually means unbounded in dual Returns -3 if not, 2 if is unbounded */ int checkUnbounded(CoinIndexedVector & ray, double changeCost); /** Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void statusOfProblemInDual(int type); /** Fast iterations. Misses out a lot of initialization. Normally stops on maximum iterations, first re-factorization or tentative optimum. If looks interesting then continues as normal. Returns 0 if finished properly, 1 otherwise. */ /// Gets tableau column - does flips and checks what to do next /// Knows tableau column in 1, flips in 2 and gets an array for flips (as serial here) int whatNext(); /// see if cutoff reached bool checkCutoff(bool computeObjective); /// Does something about fake tolerances int bounceTolerances(int type); /// Perturbs problem void perturb(double factor); /// Perturbs problem B void perturbB(double factor,int type); /// Make non free variables dual feasible by moving to a bound int makeNonFreeVariablesDualFeasible(bool changeCosts=false); int fastDual(bool alwaysFinish = false); /** Checks number of variables at fake bounds. This is used by fastDual so can exit gracefully before end */ int numberAtFakeBound(); /** Pivot in a variable and choose an outgoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Return codes as before but -1 means no acceptable pivot */ int pivotResultPart1(); /** Get next free , -1 if none */ int nextSuperBasic(); /// Startup part of dual void startupSolve(); /// Ending part of dual void finishSolve(); void gutsOfDual(); //int dual2(int ifValuesPass,int startFinishOptions=0); int resetFakeBounds(int type); //@} }; #if ABC_PARALLEL==1 void * abc_parallelManager(void * simplex); #endif #endif Clp-1.15.10/src/ClpPdcoBase.hpp0000644000076600007660000000524511510657452014506 0ustar coincoin/* $Id: ClpPdcoBase.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpPdcoBase_H #define ClpPdcoBase_H #include "CoinPragma.hpp" #include "CoinPackedMatrix.hpp" #include "CoinDenseVector.hpp" class ClpInterior; /** Abstract base class for tailoring everything for Pcdo Since this class is abstract, no object of this type can be created. If a derived class provides all methods then all ClpPcdo algorithms should work. Eventually we should be able to use ClpObjective and ClpMatrixBase. */ class ClpPdcoBase { public: /**@name Virtual methods that the derived classes must provide */ //@{ virtual void matVecMult(ClpInterior * model, int mode, double * x, double * y) const = 0; virtual void getGrad(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &grad) const = 0; virtual void getHessian(ClpInterior * model, CoinDenseVector &x, CoinDenseVector &H) const = 0; virtual double getObj(ClpInterior * model, CoinDenseVector &x) const = 0; virtual void matPrecon(ClpInterior * model, double delta, double * x, double * y) const = 0; //@} //@{ ///@name Other /// Clone virtual ClpPdcoBase * clone() const = 0; /// Returns type inline int type() const { return type_; }; /// Sets type inline void setType(int type) { type_ = type; }; /// Returns size of d1 inline int sizeD1() const { return 1; }; /// Returns d1 as scalar inline double getD1() const { return d1_; }; /// Returns size of d2 inline int sizeD2() const { return 1; }; /// Returns d2 as scalar inline double getD2() const { return d2_; }; //@} protected: /**@name Constructors, destructor
NOTE: All constructors are protected. There's no need to expose them, after all, this is an abstract class. */ //@{ /** Default constructor. */ ClpPdcoBase(); /** Destructor (has to be public) */ public: virtual ~ClpPdcoBase(); protected: // Copy ClpPdcoBase(const ClpPdcoBase&); // Assignment ClpPdcoBase& operator=(const ClpPdcoBase&); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Should be dense vectors double d1_; double d2_; /// type (may be useful) int type_; //@} }; #endif Clp-1.15.10/src/ClpEventHandler.cpp0000644000076600007660000000673511662222261015377 0ustar coincoin/* $Id: ClpEventHandler.cpp 1825 2011-11-20 16:02:57Z 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 "CoinPragma.hpp" #include "ClpEventHandler.hpp" #include "ClpSimplex.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpEventHandler::ClpEventHandler (ClpSimplex * model) : model_(model) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpEventHandler::ClpEventHandler (const ClpEventHandler & rhs) : model_(rhs.model_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpEventHandler::~ClpEventHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpEventHandler & ClpEventHandler::operator=(const ClpEventHandler& rhs) { if (this != &rhs) { model_ = rhs.model_; } return *this; } // Clone ClpEventHandler * ClpEventHandler::clone() const { return new ClpEventHandler(*this); } // Event int ClpEventHandler::event(Event whichEvent) { if (whichEvent != theta) return -1; // do nothing else return 0; // say normal exit } /* This can do whatever it likes. Return code -1 means no action. This passes in something */ int ClpEventHandler::eventWithInfo(Event whichEvent, void * info) { return -1; } /* set model. */ void ClpEventHandler::setSimplex(ClpSimplex * model) { model_ = model; } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDisasterHandler::ClpDisasterHandler (ClpSimplex * model) : model_(model) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDisasterHandler::ClpDisasterHandler (const ClpDisasterHandler & rhs) : model_(rhs.model_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDisasterHandler::~ClpDisasterHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDisasterHandler & ClpDisasterHandler::operator=(const ClpDisasterHandler& rhs) { if (this != &rhs) { model_ = rhs.model_; } return *this; } /* set model. */ void ClpDisasterHandler::setSimplex(ClpSimplex * model) { model_ = model; } // Type of disaster 0 can fix, 1 abort int ClpDisasterHandler::typeOfDisaster() { return 0; } Clp-1.15.10/src/ClpFactorization.cpp0000644000076600007660000036375712071405372015647 0ustar coincoin/* $Id: ClpFactorization.cpp 1903 2013-01-03 22:49:30Z 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 "CoinPragma.hpp" #include "ClpFactorization.hpp" #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" #endif #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexDual.hpp" #include "ClpMatrixBase.hpp" #ifndef SLIM_CLP #include "ClpNetworkBasis.hpp" #include "ClpNetworkMatrix.hpp" //#define CHECK_NETWORK #ifdef CHECK_NETWORK const static bool doCheck = true; #else const static bool doCheck = false; #endif #endif //#define CLP_FACTORIZATION_INSTRUMENT #ifdef CLP_FACTORIZATION_INSTRUMENT #include "CoinTime.hpp" double factorization_instrument(int type) { static int times[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static double startTime = 0.0; static double totalTimes [10] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; if (type < 0) { assert (!startTime); startTime = CoinCpuTime(); return 0.0; } else if (type > 0) { times[type]++; double difference = CoinCpuTime() - startTime; totalTimes[type] += difference; startTime = 0.0; return difference; } else { // report const char * types[10] = { "", "fac=rhs_etc", "factorize", "replace", "update_FT", "update", "update_transpose", "gosparse", "getWeights!", "update2_FT" }; double total = 0.0; for (int i = 1; i < 10; i++) { if (times[i]) { printf("%s was called %d times taking %g seconds\n", types[i], times[i], totalTimes[i]); total += totalTimes[i]; times[i] = 0; totalTimes[i] = 0.0; } } return total; } } #endif //############################################################################# // Constructors / Destructor / Assignment //############################################################################# #ifndef CLP_MULTIPLE_FACTORIZATIONS //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpFactorization::ClpFactorization () : CoinFactorization() { #ifndef SLIM_CLP networkBasis_ = NULL; #endif } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpFactorization::ClpFactorization (const ClpFactorization & rhs, int dummyDenseIfSmaller) : CoinFactorization(rhs) { #ifndef SLIM_CLP if (rhs.networkBasis_) networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_)); else networkBasis_ = NULL; #endif } ClpFactorization::ClpFactorization (const CoinFactorization & rhs) : CoinFactorization(rhs) { #ifndef SLIM_CLP networkBasis_ = NULL; #endif } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpFactorization::~ClpFactorization () { #ifndef SLIM_CLP delete networkBasis_; #endif } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpFactorization & ClpFactorization::operator=(const ClpFactorization& rhs) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif if (this != &rhs) { CoinFactorization::operator=(rhs); #ifndef SLIM_CLP delete networkBasis_; if (rhs.networkBasis_) networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_)); else networkBasis_ = NULL; #endif } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(1); #endif return *this; } #if 0 static unsigned int saveList[10000]; int numberSave = -1; inline bool isDense(int i) { return ((saveList[i>>5] >> (i & 31)) & 1) != 0; } inline void setDense(int i) { unsigned int & value = saveList[i>>5]; int bit = i & 31; value |= (1 << bit); } #endif int ClpFactorization::factorize ( ClpSimplex * model, int solveType, bool valuesPass) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif ClpMatrixBase * matrix = model->clpMatrix(); int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); if (!numberRows) return 0; // If too many compressions increase area if (numberPivots_ > 1 && numberCompressions_ * 10 > numberPivots_ + 10) { areaFactor_ *= 1.1; } //int numberPivots=numberPivots_; #if 0 if (model->algorithm() > 0) numberSave = -1; #endif #ifndef SLIM_CLP if (!networkBasis_ || doCheck) { #endif status_ = -99; int * pivotVariable = model->pivotVariable(); //returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ while (status_ < -98) { int i; int numberBasic = 0; int numberRowBasic; // Move pivot variables across if they look good int * pivotTemp = model->rowArray(0)->getIndices(); assert (!model->rowArray(0)->getNumElements()); if (!matrix->rhsOffset(model)) { #if 0 if (numberSave > 0) { int nStill = 0; int nAtBound = 0; int nZeroDual = 0; CoinIndexedVector * array = model->rowArray(3); CoinIndexedVector * objArray = model->columnArray(1); array->clear(); objArray->clear(); double * cost = model->costRegion(); double tolerance = model->primalTolerance(); double offset = 0.0; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns && isDense(iPivot)) { if (model->getColumnStatus(iPivot) == ClpSimplex::basic) { nStill++; double value = model->solutionRegion()[iPivot]; double dual = model->dualRowSolution()[i]; double lower = model->lowerRegion()[iPivot]; double upper = model->upperRegion()[iPivot]; ClpSimplex::Status status; if (fabs(value - lower) < tolerance) { status = ClpSimplex::atLowerBound; nAtBound++; } else if (fabs(value - upper) < tolerance) { nAtBound++; status = ClpSimplex::atUpperBound; } else if (value > lower && value < upper) { status = ClpSimplex::superBasic; } else { status = ClpSimplex::basic; } if (status != ClpSimplex::basic) { if (model->getRowStatus(i) != ClpSimplex::basic) { model->setColumnStatus(iPivot, ClpSimplex::atLowerBound); model->setRowStatus(i, ClpSimplex::basic); pivotVariable[i] = i + numberColumns; model->dualRowSolution()[i] = 0.0; model->djRegion(0)[i] = 0.0; array->add(i, dual); offset += dual * model->solutionRegion(0)[i]; } } if (fabs(dual) < 1.0e-5) nZeroDual++; } } } printf("out of %d dense, %d still in basis, %d at bound, %d with zero dual - offset %g\n", numberSave, nStill, nAtBound, nZeroDual, offset); if (array->getNumElements()) { // modify costs model->clpMatrix()->transposeTimes(model, 1.0, array, model->columnArray(0), objArray); array->clear(); int n = objArray->getNumElements(); int * indices = objArray->getIndices(); double * elements = objArray->denseVector(); for (i = 0; i < n; i++) { int iColumn = indices[i]; cost[iColumn] -= elements[iColumn]; elements[iColumn] = 0.0; } objArray->setNumElements(0); } } #endif // Seems to prefer things in order so quickest // way is to go though like this for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } else { // Long matrix - do a different way bool fullSearch = false; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot >= numberColumns) { pivotTemp[numberBasic++] = iPivot - numberColumns; } } numberRowBasic = numberBasic; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns) { if (iPivot >= 0) { pivotTemp[numberBasic++] = iPivot; } else { // not full basis fullSearch = true; break; } } } if (fullSearch) { // do slow way numberBasic = 0; for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } } if (numberBasic > model->maximumBasic()) { #if 0 // ndef NDEBUG printf("%d basic - should only be %d\n", numberBasic, numberRows); #endif // Take out some numberBasic = numberRowBasic; for (int i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { if (numberBasic < numberRows) numberBasic++; else model->setColumnStatus(i, ClpSimplex::superBasic); } } numberBasic = numberRowBasic; matrix->generalExpanded(model, 0, numberBasic); } #ifndef SLIM_CLP // see if matrix a network #ifndef NO_RTTI ClpNetworkMatrix* networkMatrix = dynamic_cast< ClpNetworkMatrix*>(model->clpMatrix()); #else ClpNetworkMatrix* networkMatrix = NULL; if (model->clpMatrix()->type() == 11) networkMatrix = static_cast< ClpNetworkMatrix*>(model->clpMatrix()); #endif // If network - still allow ordinary factorization first time for laziness if (networkMatrix) biasLU_ = 0; // All to U if network //int saveMaximumPivots = maximumPivots(); delete networkBasis_; networkBasis_ = NULL; if (networkMatrix && !doCheck) maximumPivots(1); #endif //printf("L, U, R %d %d %d\n",numberElementsL(),numberElementsU(),numberElementsR()); while (status_ == -99) { // maybe for speed will be better to leave as many regions as possible gutsOfDestructor(); gutsOfInitialize(2); CoinBigIndex numberElements = numberRowBasic; // compute how much in basis int i; // can change for gub int numberColumnBasic = numberBasic - numberRowBasic; numberElements += matrix->countBasis(model, pivotTemp + numberRowBasic, numberRowBasic, numberColumnBasic); // and recompute as network side say different if (model->numberIterations()) numberRowBasic = numberBasic - numberColumnBasic; numberElements = 3 * numberBasic + 3 * numberElements + 20000; #if 0 // If iteration not zero then may be compressed getAreas ( !model->numberIterations() ? numberRows : numberBasic, numberRowBasic + numberColumnBasic, numberElements, 2 * numberElements ); #else getAreas ( numberRows, numberRowBasic + numberColumnBasic, numberElements, 2 * numberElements ); #endif //fill // Fill in counts so we can skip part of preProcess int * numberInRow = numberInRow_.array(); int * numberInColumn = numberInColumn_.array(); CoinZeroN ( numberInRow, numberRows_ + 1 ); CoinZeroN ( numberInColumn, maximumColumnsExtra_ + 1 ); double * elementU = elementU_.array(); int * indexRowU = indexRowU_.array(); CoinBigIndex * startColumnU = startColumnU_.array(); for (i = 0; i < numberRowBasic; i++) { int iRow = pivotTemp[i]; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = slackValue_; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberRowBasic] = numberRowBasic; // can change for gub so redo numberColumnBasic = numberBasic - numberRowBasic; matrix->fillBasis(model, pivotTemp + numberRowBasic, numberColumnBasic, indexRowU, startColumnU + numberRowBasic, numberInRow, numberInColumn + numberRowBasic, elementU); #if 0 { printf("%d row basic, %d column basic\n", numberRowBasic, numberColumnBasic); for (int i = 0; i < numberElements; i++) printf("row %d col %d value %g\n", indexRowU_.array()[i], indexColumnU_[i], elementU_.array()[i]); } #endif // recompute number basic numberBasic = numberRowBasic + numberColumnBasic; if (numberBasic) numberElements = startColumnU[numberBasic-1] + numberInColumn[numberBasic-1]; else numberElements = 0; lengthU_ = numberElements; //saveFactorization("dump.d"); if (biasLU_ >= 3 || numberRows_ != numberColumns_) preProcess ( 2 ); else preProcess ( 3 ); // no row copy factor ( ); if (status_ == -99) { // get more memory areaFactor(2.0 * areaFactor()); } else if (status_ == -1 && model->numberIterations() == 0 && denseThreshold_) { // Round again without dense denseThreshold_ = 0; status_ = -99; } } // If we get here status is 0 or -1 if (status_ == 0) { // We may need to tamper with order and redo - e.g. network with side int useNumberRows = numberRows; // **** we will also need to add test in dual steepest to do // as we do for network matrix->generalExpanded(model, 12, useNumberRows); const int * permuteBack = permuteBack_.array(); const int * back = pivotColumnBack_.array(); //int * pivotTemp = pivotColumn_.array(); //ClpDisjointCopyN ( pivotVariable, numberRows , pivotTemp ); // Redo pivot order for (i = 0; i < numberRowBasic; i++) { int k = pivotTemp[i]; // so rowIsBasic[k] would be permuteBack[back[i]] pivotVariable[permuteBack[back[i]]] = k + numberColumns; } for (; i < useNumberRows; i++) { int k = pivotTemp[i]; // so rowIsBasic[k] would be permuteBack[back[i]] pivotVariable[permuteBack[back[i]]] = k; } #if 0 if (numberSave >= 0) { numberSave = numberDense_; memset(saveList, 0, ((numberRows_ + 31) >> 5)*sizeof(int)); for (i = numberRows_ - numberSave; i < numberRows_; i++) { int k = pivotTemp[pivotColumn_.array()[i]]; setDense(k); } } #endif // Set up permutation vector // these arrays start off as copies of permute // (and we could use permute_ instead of pivotColumn (not back though)) ClpDisjointCopyN ( permute_.array(), useNumberRows , pivotColumn_.array() ); ClpDisjointCopyN ( permuteBack_.array(), useNumberRows , pivotColumnBack_.array() ); #ifndef SLIM_CLP if (networkMatrix) { maximumPivots(CoinMax(2000, maximumPivots())); // redo arrays for (int iRow = 0; iRow < 4; iRow++) { int length = model->numberRows() + maximumPivots(); if (iRow == 3 || model->objectiveAsObject()->type() > 1) length += model->numberColumns(); model->rowArray(iRow)->reserve(length); } // create network factorization if (doCheck) delete networkBasis_; // temp networkBasis_ = new ClpNetworkBasis(model, numberRows_, pivotRegion_.array(), permuteBack_.array(), startColumnU_.array(), numberInColumn_.array(), indexRowU_.array(), elementU_.array()); // kill off arrays in ordinary factorization if (!doCheck) { gutsOfDestructor(); // but make sure numberRows_ set numberRows_ = model->numberRows(); status_ = 0; #if 0 // but put back permute arrays so odd things will work int numberRows = model->numberRows(); pivotColumnBack_ = new int [numberRows]; permute_ = new int [numberRows]; int i; for (i = 0; i < numberRows; i++) { pivotColumnBack_[i] = i; permute_[i] = i; } #endif } } else { #endif // See if worth going sparse and when if (numberFtranCounts_ > 100) { ftranCountInput_ = CoinMax(ftranCountInput_, 1.0); ftranAverageAfterL_ = CoinMax(ftranCountAfterL_ / ftranCountInput_, 1.0); ftranAverageAfterR_ = CoinMax(ftranCountAfterR_ / ftranCountAfterL_, 1.0); ftranAverageAfterU_ = CoinMax(ftranCountAfterU_ / ftranCountAfterR_, 1.0); if (btranCountInput_ && btranCountAfterU_ && btranCountAfterR_) { btranAverageAfterU_ = CoinMax(btranCountAfterU_ / btranCountInput_, 1.0); btranAverageAfterR_ = CoinMax(btranCountAfterR_ / btranCountAfterU_, 1.0); btranAverageAfterL_ = CoinMax(btranCountAfterL_ / btranCountAfterR_, 1.0); } else { // we have not done any useful btrans (values pass?) btranAverageAfterU_ = 1.0; btranAverageAfterR_ = 1.0; btranAverageAfterL_ = 1.0; } } // scale back ftranCountInput_ *= 0.8; ftranCountAfterL_ *= 0.8; ftranCountAfterR_ *= 0.8; ftranCountAfterU_ *= 0.8; btranCountInput_ *= 0.8; btranCountAfterU_ *= 0.8; btranCountAfterR_ *= 0.8; btranCountAfterL_ *= 0.8; #ifndef SLIM_CLP } #endif } else if (status_ == -1 && (solveType == 0 || solveType == 2)) { // This needs redoing as it was merged coding - does not need array int numberTotal = numberRows + numberColumns; int * isBasic = new int [numberTotal]; int * rowIsBasic = isBasic + numberColumns; int * columnIsBasic = isBasic; for (i = 0; i < numberTotal; i++) isBasic[i] = -1; for (i = 0; i < numberRowBasic; i++) { int iRow = pivotTemp[i]; rowIsBasic[iRow] = 1; } for (; i < numberBasic; i++) { int iColumn = pivotTemp[i]; columnIsBasic[iColumn] = 1; } numberBasic = 0; for (i = 0; i < numberRows; i++) pivotVariable[i] = -1; // mark as basic or non basic const int * pivotColumn = pivotColumn_.array(); for (i = 0; i < numberRows; i++) { if (rowIsBasic[i] >= 0) { if (pivotColumn[numberBasic] >= 0) { rowIsBasic[i] = pivotColumn[numberBasic]; } else { rowIsBasic[i] = -1; model->setRowStatus(i, ClpSimplex::superBasic); } numberBasic++; } } for (i = 0; i < numberColumns; i++) { if (columnIsBasic[i] >= 0) { if (pivotColumn[numberBasic] >= 0) columnIsBasic[i] = pivotColumn[numberBasic]; else columnIsBasic[i] = -1; numberBasic++; } } // leave pivotVariable in useful form for cleaning basis int * pivotVariable = model->pivotVariable(); for (i = 0; i < numberRows; i++) { pivotVariable[i] = -1; } for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) { int iPivot = rowIsBasic[i]; if (iPivot >= 0) pivotVariable[iPivot] = i + numberColumns; } } for (i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { int iPivot = columnIsBasic[i]; if (iPivot >= 0) pivotVariable[iPivot] = i; } } delete [] isBasic; double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * columnActivity = model->solutionRegion(); double * rowLower = model->lowerRegion(0); double * rowUpper = model->upperRegion(0); double * rowActivity = model->solutionRegion(0); //redo basis - first take ALL columns out int iColumn; double largeValue = model->largeValue(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) { // take out if (!valuesPass) { double lower = columnLower[iColumn]; double upper = columnUpper[iColumn]; double value = columnActivity[iColumn]; if (lower > -largeValue || upper < largeValue) { if (fabs(value - lower) < fabs(value - upper)) { model->setColumnStatus(iColumn, ClpSimplex::atLowerBound); columnActivity[iColumn] = lower; } else { model->setColumnStatus(iColumn, ClpSimplex::atUpperBound); columnActivity[iColumn] = upper; } } else { model->setColumnStatus(iColumn, ClpSimplex::isFree); } } else { model->setColumnStatus(iColumn, ClpSimplex::superBasic); } } } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { int iSequence = pivotVariable[iRow]; if (iSequence >= 0) { // basic if (iSequence >= numberColumns) { // slack in - leave //assert (iSequence-numberColumns==iRow); } else { assert(model->getRowStatus(iRow) != ClpSimplex::basic); // put back structural model->setColumnStatus(iSequence, ClpSimplex::basic); } } else { // put in slack model->setRowStatus(iRow, ClpSimplex::basic); } } // Put back any key variables for gub (status_ not touched) matrix->generalExpanded(model, 1, status_); // signal repeat status_ = -99; // set fixed if they are for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic ) { if (rowLower[iRow] == rowUpper[iRow]) { rowActivity[iRow] = rowLower[iRow]; model->setRowStatus(iRow, ClpSimplex::isFixed); } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) != ClpSimplex::basic ) { if (columnLower[iColumn] == columnUpper[iColumn]) { columnActivity[iColumn] = columnLower[iColumn]; model->setColumnStatus(iColumn, ClpSimplex::isFixed); } } } } } #ifndef SLIM_CLP } else { // network - fake factorization - do nothing status_ = 0; numberPivots_ = 0; } #endif #ifndef SLIM_CLP if (!status_) { // take out part if quadratic if (model->algorithm() == 2) { ClpObjective * obj = model->objectiveAsObject(); #ifndef NDEBUG ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj)); assert (quadraticObj); #else ClpQuadraticObjective * quadraticObj = (static_cast< ClpQuadraticObjective*>(obj)); #endif CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); int numberXColumns = quadratic->getNumCols(); assert (numberXColumns < numberColumns); int base = numberColumns - numberXColumns; int * which = new int [numberXColumns]; int * pivotVariable = model->pivotVariable(); int * permute = pivotColumn(); int i; int n = 0; for (i = 0; i < numberRows; i++) { int iSj = pivotVariable[i] - base; if (iSj >= 0 && iSj < numberXColumns) which[n++] = permute[i]; } if (n) emptyRows(n, which); delete [] which; } } #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(2); #endif return status_; } /* Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If checkBeforeModifying is true will do all accuracy checks before modifying factorization. Whether to set this depends on speed considerations. You could just do this on first iteration after factorization and thereafter re-factorize partial update already in U */ int ClpFactorization::replaceColumn ( const ClpSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, double pivotCheck , bool checkBeforeModifying, double acceptablePivot) { int returnCode; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif // see if FT if (doForrestTomlin_) { returnCode = CoinFactorization::replaceColumn(regionSparse, pivotRow, pivotCheck, checkBeforeModifying, acceptablePivot); } else { returnCode = CoinFactorization::replaceColumnPFI(tableauColumn, pivotRow, pivotCheck); // Note array } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(3); #endif #ifndef SLIM_CLP } else { if (doCheck) { returnCode = CoinFactorization::replaceColumn(regionSparse, pivotRow, pivotCheck, checkBeforeModifying, acceptablePivot); networkBasis_->replaceColumn(regionSparse, pivotRow); } else { // increase number of pivots numberPivots_++; returnCode = networkBasis_->replaceColumn(regionSparse, pivotRow); } } #endif return returnCode; } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnFT ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) { #ifdef CLP_DEBUG regionSparse->checkClear(); #endif if (!numberRows_) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif collectStatistics_ = true; int returnCode = CoinFactorization::updateColumnFT(regionSparse, regionSparse2); collectStatistics_ = false; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(4); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[numberRows_]; int returnCode = CoinFactorization::updateColumnFT(regionSparse, regionSparse2); networkBasis_->updateColumn(regionSparse, save, -1); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, numberRows_ * sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { for (i = 0; i < numberRows_; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else networkBasis_->updateColumn(regionSparse, regionSparse2, -1); return 1; #endif } #endif } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute) const { #ifdef CLP_DEBUG if (!noPermute) regionSparse->checkClear(); #endif if (!numberRows_) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif collectStatistics_ = true; int returnCode = CoinFactorization::updateColumn(regionSparse, regionSparse2, noPermute); collectStatistics_ = false; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(5); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[numberRows_]; int returnCode = CoinFactorization::updateColumn(regionSparse, regionSparse2, noPermute); networkBasis_->updateColumn(regionSparse, save, -1); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, numberRows_ * sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { for (i = 0; i < numberRows_; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else networkBasis_->updateColumn(regionSparse, regionSparse2, -1); return 1; #endif } #endif } /* Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ int ClpFactorization::updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, CoinIndexedVector * regionSparse2, CoinIndexedVector * regionSparse3, bool noPermuteRegion3) { int returnCode = updateColumnFT(regionSparse1, regionSparse2); updateColumn(regionSparse1, regionSparse3, noPermuteRegion3); return returnCode; } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnForDebug ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute) const { if (!noPermute) regionSparse->checkClear(); if (!numberRows_) return 0; collectStatistics_ = false; int returnCode = CoinFactorization::updateColumn(regionSparse, regionSparse2, noPermute); return returnCode; } /* Updates one column (BTRAN) from region2 region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const { if (!numberRows_) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif collectStatistics_ = true; int returnCode = CoinFactorization::updateColumnTranspose(regionSparse, regionSparse2); collectStatistics_ = false; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(6); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[numberRows_]; int returnCode = CoinFactorization::updateColumnTranspose(regionSparse, regionSparse2); networkBasis_->updateColumnTranspose(regionSparse, save); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, numberRows_ * sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { for (i = 0; i < numberRows_; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else return networkBasis_->updateColumnTranspose(regionSparse, regionSparse2); #endif } #endif } /* makes a row copy of L for speed and to allow very sparse problems */ void ClpFactorization::goSparse() { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP if (!networkBasis_) #endif CoinFactorization::goSparse(); #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(7); #endif } // Cleans up i.e. gets rid of network basis void ClpFactorization::cleanUp() { #ifndef SLIM_CLP delete networkBasis_; networkBasis_ = NULL; #endif resetStatistics(); } /// Says whether to redo pivot order bool ClpFactorization::needToReorder() const { #ifdef CHECK_NETWORK return true; #endif #ifndef SLIM_CLP if (!networkBasis_) #endif return true; #ifndef SLIM_CLP else return false; #endif } // Get weighted row list void ClpFactorization::getWeights(int * weights) const { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP if (networkBasis_) { // Network - just unit for (int i = 0; i < numberRows_; i++) weights[i] = 1; return; } #endif int * numberInRow = numberInRow_.array(); int * numberInColumn = numberInColumn_.array(); int * permuteBack = pivotColumnBack_.array(); int * indexRowU = indexRowU_.array(); const CoinBigIndex * startColumnU = startColumnU_.array(); const CoinBigIndex * startRowL = startRowL_.array(); if (!startRowL || !numberInRow_.array()) { int * temp = new int[numberRows_]; memset(temp, 0, numberRows_ * sizeof(int)); int i; for (i = 0; i < numberRows_; i++) { // one for pivot temp[i]++; CoinBigIndex j; for (j = startColumnU[i]; j < startColumnU[i] + numberInColumn[i]; j++) { int iRow = indexRowU[j]; temp[iRow]++; } } CoinBigIndex * startColumnL = startColumnL_.array(); int * indexRowL = indexRowL_.array(); for (i = baseL_; i < baseL_ + numberL_; i++) { CoinBigIndex j; for (j = startColumnL[i]; j < startColumnL[i+1]; j++) { int iRow = indexRowL[j]; temp[iRow]++; } } for (i = 0; i < numberRows_; i++) { int number = temp[i]; int iPermute = permuteBack[i]; weights[iPermute] = number; } delete [] temp; } else { int i; for (i = 0; i < numberRows_; i++) { int number = startRowL[i+1] - startRowL[i] + numberInRow[i] + 1; //number = startRowL[i+1]-startRowL[i]+1; //number = numberInRow[i]+1; int iPermute = permuteBack[i]; weights[iPermute] = number; } } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(8); #endif } #else // This one allows multiple factorizations #if CLP_MULTIPLE_FACTORIZATIONS == 1 typedef CoinDenseFactorization CoinOtherFactorization; typedef CoinOslFactorization CoinOtherFactorization; #elif CLP_MULTIPLE_FACTORIZATIONS == 2 #include "CoinSimpFactorization.hpp" typedef CoinSimpFactorization CoinOtherFactorization; typedef CoinOslFactorization CoinOtherFactorization; #elif CLP_MULTIPLE_FACTORIZATIONS == 3 #include "CoinSimpFactorization.hpp" #define CoinOslFactorization CoinDenseFactorization #elif CLP_MULTIPLE_FACTORIZATIONS == 4 #include "CoinSimpFactorization.hpp" //#define CoinOslFactorization CoinDenseFactorization #include "CoinOslFactorization.hpp" #endif //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpFactorization::ClpFactorization () { #ifndef SLIM_CLP networkBasis_ = NULL; #endif //coinFactorizationA_ = NULL; coinFactorizationA_ = new CoinFactorization() ; coinFactorizationB_ = NULL; //coinFactorizationB_ = new CoinOtherFactorization(); forceB_ = 0; goOslThreshold_ = -1; goDenseThreshold_ = -1; goSmallThreshold_ = -1; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpFactorization::ClpFactorization (const ClpFactorization & rhs, int denseIfSmaller) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP if (rhs.networkBasis_) networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_)); else networkBasis_ = NULL; #endif forceB_ = rhs.forceB_; goOslThreshold_ = rhs.goOslThreshold_; goDenseThreshold_ = rhs.goDenseThreshold_; goSmallThreshold_ = rhs.goSmallThreshold_; int goDense = 0; #ifdef CLP_REUSE_ETAS model_=rhs.model_; #endif if (denseIfSmaller > 0 && denseIfSmaller <= goDenseThreshold_) { CoinDenseFactorization * denseR = dynamic_cast(rhs.coinFactorizationB_); if (!denseR) goDense = 1; } if (denseIfSmaller > 0 && !rhs.coinFactorizationB_) { if (denseIfSmaller <= goDenseThreshold_) goDense = 1; else if (denseIfSmaller <= goSmallThreshold_) goDense = 2; else if (denseIfSmaller <= goOslThreshold_) goDense = 3; } else if (denseIfSmaller < 0) { if (-denseIfSmaller <= goDenseThreshold_) goDense = 1; else if (-denseIfSmaller <= goSmallThreshold_) goDense = 2; else if (-denseIfSmaller <= goOslThreshold_) goDense = 3; } if (rhs.coinFactorizationA_ && !goDense) coinFactorizationA_ = new CoinFactorization(*(rhs.coinFactorizationA_)); else coinFactorizationA_ = NULL; if (rhs.coinFactorizationB_ && (denseIfSmaller >= 0 || !goDense)) coinFactorizationB_ = rhs.coinFactorizationB_->clone(); else coinFactorizationB_ = NULL; if (goDense) { delete coinFactorizationB_; if (goDense == 1) coinFactorizationB_ = new CoinDenseFactorization(); else if (goDense == 2) coinFactorizationB_ = new CoinSimpFactorization(); else coinFactorizationB_ = new CoinOslFactorization(); if (rhs.coinFactorizationA_) { coinFactorizationB_->maximumPivots(rhs.coinFactorizationA_->maximumPivots()); coinFactorizationB_->pivotTolerance(rhs.coinFactorizationA_->pivotTolerance()); coinFactorizationB_->zeroTolerance(rhs.coinFactorizationA_->zeroTolerance()); } else { assert (coinFactorizationB_); coinFactorizationB_->maximumPivots(rhs.coinFactorizationB_->maximumPivots()); coinFactorizationB_->pivotTolerance(rhs.coinFactorizationB_->pivotTolerance()); coinFactorizationB_->zeroTolerance(rhs.coinFactorizationB_->zeroTolerance()); } } assert (!coinFactorizationA_ || !coinFactorizationB_); #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(1); #endif } ClpFactorization::ClpFactorization (const CoinFactorization & rhs) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP networkBasis_ = NULL; #endif coinFactorizationA_ = new CoinFactorization(rhs); coinFactorizationB_ = NULL; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(1); #endif forceB_ = 0; goOslThreshold_ = -1; goDenseThreshold_ = -1; goSmallThreshold_ = -1; assert (!coinFactorizationA_ || !coinFactorizationB_); } ClpFactorization::ClpFactorization (const CoinOtherFactorization & rhs) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP networkBasis_ = NULL; #endif coinFactorizationA_ = NULL; coinFactorizationB_ = rhs.clone(); //coinFactorizationB_ = new CoinOtherFactorization(rhs); forceB_ = 0; goOslThreshold_ = -1; goDenseThreshold_ = -1; goSmallThreshold_ = -1; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(1); #endif assert (!coinFactorizationA_ || !coinFactorizationB_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpFactorization::~ClpFactorization () { #ifndef SLIM_CLP delete networkBasis_; #endif delete coinFactorizationA_; delete coinFactorizationB_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpFactorization & ClpFactorization::operator=(const ClpFactorization& rhs) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif if (this != &rhs) { #ifndef SLIM_CLP delete networkBasis_; if (rhs.networkBasis_) networkBasis_ = new ClpNetworkBasis(*(rhs.networkBasis_)); else networkBasis_ = NULL; #endif forceB_ = rhs.forceB_; #ifdef CLP_REUSE_ETAS model_=rhs.model_; #endif goOslThreshold_ = rhs.goOslThreshold_; goDenseThreshold_ = rhs.goDenseThreshold_; goSmallThreshold_ = rhs.goSmallThreshold_; if (rhs.coinFactorizationA_) { if (coinFactorizationA_) *coinFactorizationA_ = *(rhs.coinFactorizationA_); else coinFactorizationA_ = new CoinFactorization(*rhs.coinFactorizationA_); } else { delete coinFactorizationA_; coinFactorizationA_ = NULL; } if (rhs.coinFactorizationB_) { if (coinFactorizationB_) { CoinDenseFactorization * denseR = dynamic_cast(rhs.coinFactorizationB_); CoinDenseFactorization * dense = dynamic_cast(coinFactorizationB_); CoinOslFactorization * oslR = dynamic_cast(rhs.coinFactorizationB_); CoinOslFactorization * osl = dynamic_cast(coinFactorizationB_); CoinSimpFactorization * simpR = dynamic_cast(rhs.coinFactorizationB_); CoinSimpFactorization * simp = dynamic_cast(coinFactorizationB_); if (dense && denseR) { *dense = *denseR; } else if (osl && oslR) { *osl = *oslR; } else if (simp && simpR) { *simp = *simpR; } else { delete coinFactorizationB_; coinFactorizationB_ = rhs.coinFactorizationB_->clone(); } } else { coinFactorizationB_ = rhs.coinFactorizationB_->clone(); } } else { delete coinFactorizationB_; coinFactorizationB_ = NULL; } } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(1); #endif assert (!coinFactorizationA_ || !coinFactorizationB_); return *this; } // Go over to dense code void ClpFactorization::goDenseOrSmall(int numberRows) { if (!forceB_) { if (numberRows <= goDenseThreshold_) { delete coinFactorizationA_; delete coinFactorizationB_; coinFactorizationA_ = NULL; coinFactorizationB_ = new CoinDenseFactorization(); //printf("going dense\n"); } else if (numberRows <= goSmallThreshold_) { delete coinFactorizationA_; delete coinFactorizationB_; coinFactorizationA_ = NULL; coinFactorizationB_ = new CoinSimpFactorization(); //printf("going small\n"); } else if (numberRows <= goOslThreshold_) { delete coinFactorizationA_; delete coinFactorizationB_; coinFactorizationA_ = NULL; coinFactorizationB_ = new CoinOslFactorization(); //printf("going small\n"); } } assert (!coinFactorizationA_ || !coinFactorizationB_); } // If nonzero force use of 1,dense 2,small 3,osl void ClpFactorization::forceOtherFactorization(int which) { delete coinFactorizationB_; forceB_ = 0; coinFactorizationB_ = NULL; if (which > 0 && which < 4) { delete coinFactorizationA_; coinFactorizationA_ = NULL; forceB_ = which; switch (which) { case 1: coinFactorizationB_ = new CoinDenseFactorization(); goDenseThreshold_ = COIN_INT_MAX; break; case 2: coinFactorizationB_ = new CoinSimpFactorization(); goSmallThreshold_ = COIN_INT_MAX; break; case 3: coinFactorizationB_ = new CoinOslFactorization(); goOslThreshold_ = COIN_INT_MAX; break; } } else if (!coinFactorizationA_) { coinFactorizationA_ = new CoinFactorization(); goOslThreshold_ = -1; goDenseThreshold_ = -1; goSmallThreshold_ = -1; } } int ClpFactorization::factorize ( ClpSimplex * model, int solveType, bool valuesPass) { #ifdef CLP_REUSE_ETAS model_= model; #endif //if ((model->specialOptions()&16384)) //printf("factor at %d iterations\n",model->numberIterations()); ClpMatrixBase * matrix = model->clpMatrix(); int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); if (!numberRows) return 0; #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif bool anyChanged = false; if (coinFactorizationB_) { coinFactorizationB_->setStatus(-99); int * pivotVariable = model->pivotVariable(); //returns 0 -okay, -1 singular, -2 too many in basis */ // allow dense int solveMode = 2; if (model->numberIterations()) solveMode += 8; if (valuesPass) solveMode += 4; coinFactorizationB_->setSolveMode(solveMode); while (status() < -98) { int i; int numberBasic = 0; int numberRowBasic; // Move pivot variables across if they look good int * pivotTemp = model->rowArray(0)->getIndices(); assert (!model->rowArray(0)->getNumElements()); if (!matrix->rhsOffset(model)) { // Seems to prefer things in order so quickest // way is to go though like this for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } else { // Long matrix - do a different way bool fullSearch = false; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot >= numberColumns) { pivotTemp[numberBasic++] = iPivot - numberColumns; } } numberRowBasic = numberBasic; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns) { if (iPivot >= 0) { pivotTemp[numberBasic++] = iPivot; } else { // not full basis fullSearch = true; break; } } } if (fullSearch) { // do slow way numberBasic = 0; for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } } if (numberBasic > model->maximumBasic()) { // Take out some numberBasic = numberRowBasic; for (int i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { if (numberBasic < numberRows) numberBasic++; else model->setColumnStatus(i, ClpSimplex::superBasic); } } numberBasic = numberRowBasic; matrix->generalExpanded(model, 0, numberBasic); } else if (numberBasic < numberRows) { // add in some int needed = numberRows - numberBasic; // move up columns for (i = numberBasic - 1; i >= numberRowBasic; i--) pivotTemp[i+needed] = pivotTemp[i]; numberRowBasic = 0; numberBasic = numberRows; for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) { pivotTemp[numberRowBasic++] = i; } else if (needed) { needed--; model->setRowStatus(i, ClpSimplex::basic); pivotTemp[numberRowBasic++] = i; } } } CoinBigIndex numberElements = numberRowBasic; // compute how much in basis // can change for gub int numberColumnBasic = numberBasic - numberRowBasic; numberElements += matrix->countBasis(pivotTemp + numberRowBasic, numberColumnBasic); #ifndef NDEBUG //#define CHECK_CLEAN_BASIS #ifdef CHECK_CLEAN_BASIS int saveNumberElements = numberElements; #endif #endif // Not needed for dense numberElements = 3 * numberBasic + 3 * numberElements + 20000; int numberIterations = model->numberIterations(); coinFactorizationB_->setUsefulInformation(&numberIterations, 0); coinFactorizationB_->getAreas ( numberRows, numberRowBasic + numberColumnBasic, numberElements, 2 * numberElements ); // Fill in counts so we can skip part of preProcess // This is NOT needed for dense but would be needed for later versions CoinFactorizationDouble * elementU; int * indexRowU; CoinBigIndex * startColumnU; int * numberInRow; int * numberInColumn; elementU = coinFactorizationB_->elements(); indexRowU = coinFactorizationB_->indices(); startColumnU = coinFactorizationB_->starts(); #ifdef CHECK_CLEAN_BASIS for (int i=0;islackValue(); #else #define slackValue -1.0 #endif numberInRow = coinFactorizationB_->numberInRow(); numberInColumn = coinFactorizationB_->numberInColumn(); CoinZeroN ( numberInRow, numberRows ); CoinZeroN ( numberInColumn, numberRows ); for (i = 0; i < numberRowBasic; i++) { int iRow = pivotTemp[i]; // Change pivotTemp to correct sequence pivotTemp[i] = iRow + numberColumns; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = slackValue; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberRowBasic] = numberRowBasic; // can change for gub so redo numberColumnBasic = numberBasic - numberRowBasic; matrix->fillBasis(model, pivotTemp + numberRowBasic, numberColumnBasic, indexRowU, startColumnU + numberRowBasic, numberInRow, numberInColumn + numberRowBasic, elementU); // recompute number basic numberBasic = numberRowBasic + numberColumnBasic; for (i = numberBasic; i < numberRows; i++) pivotTemp[i] = -1; // mark not there if (numberBasic) numberElements = startColumnU[numberBasic-1] + numberInColumn[numberBasic-1]; else numberElements = 0; #ifdef CHECK_CLEAN_BASIS assert (!startColumnU[0]); int lastStart=0; for (int i=0;ilastStart); lastStart=startColumnU[i+1]; } assert (lastStart==saveNumberElements); for (int i=0;i=0&&indexRowU[i]preProcess ( ); coinFactorizationB_->factor ( ); if (coinFactorizationB_->status() == -1 && (coinFactorizationB_->solveMode() % 3) != 0) { int solveMode = coinFactorizationB_->solveMode(); solveMode -= solveMode % 3; // so bottom will be 0 coinFactorizationB_->setSolveMode(solveMode); coinFactorizationB_->setStatus(-99); } if (coinFactorizationB_->status() == -99) continue; // If we get here status is 0 or -1 if (coinFactorizationB_->status() == 0 && numberBasic == numberRows) { coinFactorizationB_->postProcess(pivotTemp, pivotVariable); } else if (solveType == 0 || solveType == 2/*||solveType==1*/) { // Change pivotTemp to be correct list anyChanged = true; coinFactorizationB_->makeNonSingular(pivotTemp, numberColumns); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * columnActivity = model->solutionRegion(); double * rowLower = model->lowerRegion(0); double * rowUpper = model->upperRegion(0); double * rowActivity = model->solutionRegion(0); //redo basis - first take ALL out int iColumn; double largeValue = model->largeValue(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) { // take out if (!valuesPass) { double lower = columnLower[iColumn]; double upper = columnUpper[iColumn]; double value = columnActivity[iColumn]; if (lower > -largeValue || upper < largeValue) { if (fabs(value - lower) < fabs(value - upper)) { model->setColumnStatus(iColumn, ClpSimplex::atLowerBound); columnActivity[iColumn] = lower; } else { model->setColumnStatus(iColumn, ClpSimplex::atUpperBound); columnActivity[iColumn] = upper; } } else { model->setColumnStatus(iColumn, ClpSimplex::isFree); } } else { model->setColumnStatus(iColumn, ClpSimplex::superBasic); } } } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) == ClpSimplex::basic) { // take out if (!valuesPass) { double lower = columnLower[iRow]; double upper = columnUpper[iRow]; double value = columnActivity[iRow]; if (lower > -largeValue || upper < largeValue) { if (fabs(value - lower) < fabs(value - upper)) { model->setRowStatus(iRow, ClpSimplex::atLowerBound); columnActivity[iRow] = lower; } else { model->setRowStatus(iRow, ClpSimplex::atUpperBound); columnActivity[iRow] = upper; } } else { model->setRowStatus(iRow, ClpSimplex::isFree); } } else { model->setRowStatus(iRow, ClpSimplex::superBasic); } } } for (iRow = 0; iRow < numberRows; iRow++) { int iSequence = pivotTemp[iRow]; assert (iSequence >= 0); // basic model->setColumnStatus(iSequence, ClpSimplex::basic); } // signal repeat coinFactorizationB_->setStatus(-99); // set fixed if they are for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic ) { if (rowLower[iRow] == rowUpper[iRow]) { rowActivity[iRow] = rowLower[iRow]; model->setRowStatus(iRow, ClpSimplex::isFixed); } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) != ClpSimplex::basic ) { if (columnLower[iColumn] == columnUpper[iColumn]) { columnActivity[iColumn] = columnLower[iColumn]; model->setColumnStatus(iColumn, ClpSimplex::isFixed); } } } } } #ifdef CLP_DEBUG // check basic CoinIndexedVector region1(2 * numberRows); CoinIndexedVector region2B(2 * numberRows); int iPivot; double * arrayB = region2B.denseVector(); int i; for (iPivot = 0; iPivot < numberRows; iPivot++) { int iSequence = pivotVariable[iPivot]; model->unpack(®ion2B, iSequence); coinFactorizationB_->updateColumn(®ion1, ®ion2B); if (fabs(arrayB[iPivot] - 1.0) < 1.0e-4) { // OK? arrayB[iPivot] = 0.0; } else { assert (fabs(arrayB[iPivot]) < 1.0e-4); for (i = 0; i < numberRows; i++) { if (fabs(arrayB[i] - 1.0) < 1.0e-4) break; } assert (i < numberRows); printf("variable on row %d landed up on row %d\n", iPivot, i); arrayB[i] = 0.0; } for (i = 0; i < numberRows; i++) assert (fabs(arrayB[i]) < 1.0e-4); region2B.clear(); } #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(2); #endif if ( anyChanged && model->algorithm() < 0 && solveType > 0) { double dummyCost; static_cast (model)->changeBounds(3, NULL, dummyCost); } return coinFactorizationB_->status(); } // If too many compressions increase area if (coinFactorizationA_->pivots() > 1 && coinFactorizationA_->numberCompressions() * 10 > coinFactorizationA_->pivots() + 10) { coinFactorizationA_->areaFactor( coinFactorizationA_->areaFactor() * 1.1); } //int numberPivots=coinFactorizationA_->pivots(); #if 0 if (model->algorithm() > 0) numberSave = -1; #endif #ifndef SLIM_CLP if (!networkBasis_ || doCheck) { #endif coinFactorizationA_->setStatus(-99); int * pivotVariable = model->pivotVariable(); int nTimesRound = 0; //returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ while (coinFactorizationA_->status() < -98) { nTimesRound++; int i; int numberBasic = 0; int numberRowBasic; // Move pivot variables across if they look good int * pivotTemp = model->rowArray(0)->getIndices(); assert (!model->rowArray(0)->getNumElements()); if (!matrix->rhsOffset(model)) { #if 0 if (numberSave > 0) { int nStill = 0; int nAtBound = 0; int nZeroDual = 0; CoinIndexedVector * array = model->rowArray(3); CoinIndexedVector * objArray = model->columnArray(1); array->clear(); objArray->clear(); double * cost = model->costRegion(); double tolerance = model->primalTolerance(); double offset = 0.0; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns && isDense(iPivot)) { if (model->getColumnStatus(iPivot) == ClpSimplex::basic) { nStill++; double value = model->solutionRegion()[iPivot]; double dual = model->dualRowSolution()[i]; double lower = model->lowerRegion()[iPivot]; double upper = model->upperRegion()[iPivot]; ClpSimplex::Status status; if (fabs(value - lower) < tolerance) { status = ClpSimplex::atLowerBound; nAtBound++; } else if (fabs(value - upper) < tolerance) { nAtBound++; status = ClpSimplex::atUpperBound; } else if (value > lower && value < upper) { status = ClpSimplex::superBasic; } else { status = ClpSimplex::basic; } if (status != ClpSimplex::basic) { if (model->getRowStatus(i) != ClpSimplex::basic) { model->setColumnStatus(iPivot, ClpSimplex::atLowerBound); model->setRowStatus(i, ClpSimplex::basic); pivotVariable[i] = i + numberColumns; model->dualRowSolution()[i] = 0.0; model->djRegion(0)[i] = 0.0; array->add(i, dual); offset += dual * model->solutionRegion(0)[i]; } } if (fabs(dual) < 1.0e-5) nZeroDual++; } } } printf("out of %d dense, %d still in basis, %d at bound, %d with zero dual - offset %g\n", numberSave, nStill, nAtBound, nZeroDual, offset); if (array->getNumElements()) { // modify costs model->clpMatrix()->transposeTimes(model, 1.0, array, model->columnArray(0), objArray); array->clear(); int n = objArray->getNumElements(); int * indices = objArray->getIndices(); double * elements = objArray->denseVector(); for (i = 0; i < n; i++) { int iColumn = indices[i]; cost[iColumn] -= elements[iColumn]; elements[iColumn] = 0.0; } objArray->setNumElements(0); } } #endif // Seems to prefer things in order so quickest // way is to go though like this for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } else { // Long matrix - do a different way bool fullSearch = false; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot >= numberColumns) { pivotTemp[numberBasic++] = iPivot - numberColumns; } } numberRowBasic = numberBasic; for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns) { if (iPivot >= 0) { pivotTemp[numberBasic++] = iPivot; } else { // not full basis fullSearch = true; break; } } } if (fullSearch) { // do slow way numberBasic = 0; for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) pivotTemp[numberBasic++] = i; } numberRowBasic = numberBasic; /* Put column basic variables into pivotVariable This is done by ClpMatrixBase to allow override for gub */ matrix->generalExpanded(model, 0, numberBasic); } } if (numberBasic > model->maximumBasic()) { #if 0 // ndef NDEBUG printf("%d basic - should only be %d\n", numberBasic, numberRows); #endif // Take out some numberBasic = numberRowBasic; for (int i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { if (numberBasic < numberRows) numberBasic++; else model->setColumnStatus(i, ClpSimplex::superBasic); } } numberBasic = numberRowBasic; matrix->generalExpanded(model, 0, numberBasic); } #ifndef SLIM_CLP // see if matrix a network #ifndef NO_RTTI ClpNetworkMatrix* networkMatrix = dynamic_cast< ClpNetworkMatrix*>(model->clpMatrix()); #else ClpNetworkMatrix* networkMatrix = NULL; if (model->clpMatrix()->type() == 11) networkMatrix = static_cast< ClpNetworkMatrix*>(model->clpMatrix()); #endif // If network - still allow ordinary factorization first time for laziness if (networkMatrix) coinFactorizationA_->setBiasLU(0); // All to U if network //int saveMaximumPivots = maximumPivots(); delete networkBasis_; networkBasis_ = NULL; if (networkMatrix && !doCheck) maximumPivots(1); #endif //printf("L, U, R %d %d %d\n",numberElementsL(),numberElementsU(),numberElementsR()); while (coinFactorizationA_->status() == -99) { // maybe for speed will be better to leave as many regions as possible coinFactorizationA_->gutsOfDestructor(); coinFactorizationA_->gutsOfInitialize(2); CoinBigIndex numberElements = numberRowBasic; // compute how much in basis int i; // can change for gub int numberColumnBasic = numberBasic - numberRowBasic; numberElements += matrix->countBasis( pivotTemp + numberRowBasic, numberColumnBasic); // and recompute as network side say different if (model->numberIterations()) numberRowBasic = numberBasic - numberColumnBasic; numberElements = 3 * numberBasic + 3 * numberElements + 20000; coinFactorizationA_->getAreas ( numberRows, numberRowBasic + numberColumnBasic, numberElements, 2 * numberElements ); //fill // Fill in counts so we can skip part of preProcess int * numberInRow = coinFactorizationA_->numberInRow(); int * numberInColumn = coinFactorizationA_->numberInColumn(); CoinZeroN ( numberInRow, coinFactorizationA_->numberRows() + 1 ); CoinZeroN ( numberInColumn, coinFactorizationA_->maximumColumnsExtra() + 1 ); CoinFactorizationDouble * elementU = coinFactorizationA_->elementU(); int * indexRowU = coinFactorizationA_->indexRowU(); CoinBigIndex * startColumnU = coinFactorizationA_->startColumnU(); #ifndef COIN_FAST_CODE double slackValue = coinFactorizationA_->slackValue(); #endif for (i = 0; i < numberRowBasic; i++) { int iRow = pivotTemp[i]; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = slackValue; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberRowBasic] = numberRowBasic; // can change for gub so redo numberColumnBasic = numberBasic - numberRowBasic; matrix->fillBasis(model, pivotTemp + numberRowBasic, numberColumnBasic, indexRowU, startColumnU + numberRowBasic, numberInRow, numberInColumn + numberRowBasic, elementU); #if 0 { printf("%d row basic, %d column basic\n", numberRowBasic, numberColumnBasic); for (int i = 0; i < numberElements; i++) printf("row %d col %d value %g\n", indexRowU[i], indexColumnU_[i], elementU[i]); } #endif // recompute number basic numberBasic = numberRowBasic + numberColumnBasic; if (numberBasic) numberElements = startColumnU[numberBasic-1] + numberInColumn[numberBasic-1]; else numberElements = 0; coinFactorizationA_->setNumberElementsU(numberElements); //saveFactorization("dump.d"); if (coinFactorizationA_->biasLU() >= 3 || coinFactorizationA_->numberRows() != coinFactorizationA_->numberColumns()) coinFactorizationA_->preProcess ( 2 ); else coinFactorizationA_->preProcess ( 3 ); // no row copy coinFactorizationA_->factor ( ); if (coinFactorizationA_->status() == -99) { // get more memory coinFactorizationA_->areaFactor(2.0 * coinFactorizationA_->areaFactor()); } else if (coinFactorizationA_->status() == -1 && (model->numberIterations() == 0 || nTimesRound > 2) && coinFactorizationA_->denseThreshold()) { // Round again without dense coinFactorizationA_->setDenseThreshold(0); coinFactorizationA_->setStatus(-99); } } // If we get here status is 0 or -1 if (coinFactorizationA_->status() == 0) { // We may need to tamper with order and redo - e.g. network with side int useNumberRows = numberRows; // **** we will also need to add test in dual steepest to do // as we do for network matrix->generalExpanded(model, 12, useNumberRows); const int * permuteBack = coinFactorizationA_->permuteBack(); const int * back = coinFactorizationA_->pivotColumnBack(); //int * pivotTemp = pivotColumn_.array(); //ClpDisjointCopyN ( pivotVariable, numberRows , pivotTemp ); #ifndef NDEBUG CoinFillN(pivotVariable, numberRows, -1); #endif // Redo pivot order for (i = 0; i < numberRowBasic; i++) { int k = pivotTemp[i]; // so rowIsBasic[k] would be permuteBack[back[i]] int j = permuteBack[back[i]]; assert (pivotVariable[j] == -1); pivotVariable[j] = k + numberColumns; } for (; i < useNumberRows; i++) { int k = pivotTemp[i]; // so rowIsBasic[k] would be permuteBack[back[i]] int j = permuteBack[back[i]]; assert (pivotVariable[j] == -1); pivotVariable[j] = k; } #if 0 if (numberSave >= 0) { numberSave = numberDense_; memset(saveList, 0, ((coinFactorizationA_->numberRows() + 31) >> 5)*sizeof(int)); for (i = coinFactorizationA_->numberRows() - numberSave; i < coinFactorizationA_->numberRows(); i++) { int k = pivotTemp[pivotColumn_.array()[i]]; setDense(k); } } #endif // Set up permutation vector // these arrays start off as copies of permute // (and we could use permute_ instead of pivotColumn (not back though)) ClpDisjointCopyN ( coinFactorizationA_->permute(), useNumberRows , coinFactorizationA_->pivotColumn() ); ClpDisjointCopyN ( coinFactorizationA_->permuteBack(), useNumberRows , coinFactorizationA_->pivotColumnBack() ); #ifndef SLIM_CLP if (networkMatrix) { maximumPivots(CoinMax(2000, maximumPivots())); // redo arrays for (int iRow = 0; iRow < 4; iRow++) { int length = model->numberRows() + maximumPivots(); if (iRow == 3 || model->objectiveAsObject()->type() > 1) length += model->numberColumns(); model->rowArray(iRow)->reserve(length); } // create network factorization if (doCheck) delete networkBasis_; // temp networkBasis_ = new ClpNetworkBasis(model, coinFactorizationA_->numberRows(), coinFactorizationA_->pivotRegion(), coinFactorizationA_->permuteBack(), coinFactorizationA_->startColumnU(), coinFactorizationA_->numberInColumn(), coinFactorizationA_->indexRowU(), coinFactorizationA_->elementU()); // kill off arrays in ordinary factorization if (!doCheck) { coinFactorizationA_->gutsOfDestructor(); // but make sure coinFactorizationA_->numberRows() set coinFactorizationA_->setNumberRows(model->numberRows()); coinFactorizationA_->setStatus(0); #if 0 // but put back permute arrays so odd things will work int numberRows = model->numberRows(); pivotColumnBack_ = new int [numberRows]; permute_ = new int [numberRows]; int i; for (i = 0; i < numberRows; i++) { pivotColumnBack_[i] = i; permute_[i] = i; } #endif } } else { #endif // See if worth going sparse and when coinFactorizationA_->checkSparse(); #ifndef SLIM_CLP } #endif } else if (coinFactorizationA_->status() == -1 && (solveType == 0 || solveType == 2)) { // This needs redoing as it was merged coding - does not need array int numberTotal = numberRows + numberColumns; int * isBasic = new int [numberTotal]; int * rowIsBasic = isBasic + numberColumns; int * columnIsBasic = isBasic; for (i = 0; i < numberTotal; i++) isBasic[i] = -1; for (i = 0; i < numberRowBasic; i++) { int iRow = pivotTemp[i]; rowIsBasic[iRow] = 1; } for (; i < numberBasic; i++) { int iColumn = pivotTemp[i]; columnIsBasic[iColumn] = 1; } numberBasic = 0; for (i = 0; i < numberRows; i++) pivotVariable[i] = -1; // mark as basic or non basic const int * pivotColumn = coinFactorizationA_->pivotColumn(); for (i = 0; i < numberRows; i++) { if (rowIsBasic[i] >= 0) { if (pivotColumn[numberBasic] >= 0) { rowIsBasic[i] = pivotColumn[numberBasic]; } else { rowIsBasic[i] = -1; model->setRowStatus(i, ClpSimplex::superBasic); } numberBasic++; } } for (i = 0; i < numberColumns; i++) { if (columnIsBasic[i] >= 0) { if (pivotColumn[numberBasic] >= 0) columnIsBasic[i] = pivotColumn[numberBasic]; else columnIsBasic[i] = -1; numberBasic++; } } // leave pivotVariable in useful form for cleaning basis int * pivotVariable = model->pivotVariable(); for (i = 0; i < numberRows; i++) { pivotVariable[i] = -1; } for (i = 0; i < numberRows; i++) { if (model->getRowStatus(i) == ClpSimplex::basic) { int iPivot = rowIsBasic[i]; if (iPivot >= 0) pivotVariable[iPivot] = i + numberColumns; } } for (i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { int iPivot = columnIsBasic[i]; if (iPivot >= 0) pivotVariable[iPivot] = i; } } delete [] isBasic; double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * columnActivity = model->solutionRegion(); double * rowLower = model->lowerRegion(0); double * rowUpper = model->upperRegion(0); double * rowActivity = model->solutionRegion(0); //redo basis - first take ALL columns out int iColumn; double largeValue = model->largeValue(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) { // take out if (!valuesPass) { double lower = columnLower[iColumn]; double upper = columnUpper[iColumn]; double value = columnActivity[iColumn]; if (lower > -largeValue || upper < largeValue) { if (fabs(value - lower) < fabs(value - upper)) { model->setColumnStatus(iColumn, ClpSimplex::atLowerBound); columnActivity[iColumn] = lower; } else { model->setColumnStatus(iColumn, ClpSimplex::atUpperBound); columnActivity[iColumn] = upper; } } else { model->setColumnStatus(iColumn, ClpSimplex::isFree); } } else { model->setColumnStatus(iColumn, ClpSimplex::superBasic); } } } int iRow; for (iRow = 0; iRow < numberRows; iRow++) { int iSequence = pivotVariable[iRow]; if (iSequence >= 0) { // basic if (iSequence >= numberColumns) { // slack in - leave //assert (iSequence-numberColumns==iRow); } else { assert(model->getRowStatus(iRow) != ClpSimplex::basic); // put back structural model->setColumnStatus(iSequence, ClpSimplex::basic); } } else { // put in slack model->setRowStatus(iRow, ClpSimplex::basic); } } // Put back any key variables for gub int dummy; matrix->generalExpanded(model, 1, dummy); // signal repeat coinFactorizationA_->setStatus(-99); // set fixed if they are for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic ) { if (rowLower[iRow] == rowUpper[iRow]) { rowActivity[iRow] = rowLower[iRow]; model->setRowStatus(iRow, ClpSimplex::isFixed); } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) != ClpSimplex::basic ) { if (columnLower[iColumn] == columnUpper[iColumn]) { columnActivity[iColumn] = columnLower[iColumn]; model->setColumnStatus(iColumn, ClpSimplex::isFixed); } } } } } #ifndef SLIM_CLP } else { // network - fake factorization - do nothing coinFactorizationA_->setStatus(0); coinFactorizationA_->setPivots(0); } #endif #ifndef SLIM_CLP if (!coinFactorizationA_->status()) { // take out part if quadratic if (model->algorithm() == 2) { ClpObjective * obj = model->objectiveAsObject(); #ifndef NDEBUG ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj)); assert (quadraticObj); #else ClpQuadraticObjective * quadraticObj = (static_cast< ClpQuadraticObjective*>(obj)); #endif CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); int numberXColumns = quadratic->getNumCols(); assert (numberXColumns < numberColumns); int base = numberColumns - numberXColumns; int * which = new int [numberXColumns]; int * pivotVariable = model->pivotVariable(); int * permute = pivotColumn(); int i; int n = 0; for (i = 0; i < numberRows; i++) { int iSj = pivotVariable[i] - base; if (iSj >= 0 && iSj < numberXColumns) which[n++] = permute[i]; } if (n) coinFactorizationA_->emptyRows(n, which); delete [] which; } } #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(2); #endif return coinFactorizationA_->status(); } /* Replaces one Column in basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If checkBeforeModifying is true will do all accuracy checks before modifying factorization. Whether to set this depends on speed considerations. You could just do this on first iteration after factorization and thereafter re-factorize partial update already in U */ int ClpFactorization::replaceColumn ( const ClpSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, double pivotCheck , bool checkBeforeModifying, double acceptablePivot) { #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif int returnCode; // see if FT if (!coinFactorizationA_ || coinFactorizationA_->forrestTomlin()) { if (coinFactorizationA_) { returnCode = coinFactorizationA_->replaceColumn(regionSparse, pivotRow, pivotCheck, checkBeforeModifying, acceptablePivot); } else { bool tab = coinFactorizationB_->wantsTableauColumn(); #ifdef CLP_REUSE_ETAS int tempInfo[2]; tempInfo[1] = model_->sequenceOut(); #else int tempInfo[1]; #endif tempInfo[0] = model->numberIterations(); coinFactorizationB_->setUsefulInformation(tempInfo, 1); returnCode = coinFactorizationB_->replaceColumn(tab ? tableauColumn : regionSparse, pivotRow, pivotCheck, checkBeforeModifying, acceptablePivot); #ifdef CLP_DEBUG // check basic int numberRows = coinFactorizationB_->numberRows(); CoinIndexedVector region1(2 * numberRows); CoinIndexedVector region2A(2 * numberRows); CoinIndexedVector region2B(2 * numberRows); int iPivot; double * arrayB = region2B.denseVector(); int * pivotVariable = model->pivotVariable(); int i; for (iPivot = 0; iPivot < numberRows; iPivot++) { int iSequence = pivotVariable[iPivot]; if (iPivot == pivotRow) iSequence = model->sequenceIn(); model->unpack(®ion2B, iSequence); coinFactorizationB_->updateColumn(®ion1, ®ion2B); assert (fabs(arrayB[iPivot] - 1.0) < 1.0e-4); arrayB[iPivot] = 0.0; for (i = 0; i < numberRows; i++) assert (fabs(arrayB[i]) < 1.0e-4); region2B.clear(); } #endif } } else { returnCode = coinFactorizationA_->replaceColumnPFI(tableauColumn, pivotRow, pivotCheck); // Note array } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(3); #endif return returnCode; #ifndef SLIM_CLP } else { if (doCheck) { int returnCode = coinFactorizationA_->replaceColumn(regionSparse, pivotRow, pivotCheck, checkBeforeModifying, acceptablePivot); networkBasis_->replaceColumn(regionSparse, pivotRow); return returnCode; } else { // increase number of pivots coinFactorizationA_->setPivots(coinFactorizationA_->pivots() + 1); return networkBasis_->replaceColumn(regionSparse, pivotRow); } } #endif } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnFT ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) { #ifdef CLP_DEBUG regionSparse->checkClear(); #endif if (!numberRows()) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif int returnCode; if (coinFactorizationA_) { coinFactorizationA_->setCollectStatistics(true); returnCode = coinFactorizationA_->updateColumnFT(regionSparse, regionSparse2); coinFactorizationA_->setCollectStatistics(false); } else { #ifdef CLP_REUSE_ETAS int tempInfo[2]; tempInfo[0] = model_->numberIterations(); tempInfo[1] = model_->sequenceIn(); coinFactorizationB_->setUsefulInformation(tempInfo, 2); #endif returnCode = coinFactorizationB_->updateColumnFT(regionSparse, regionSparse2); } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(4); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[coinFactorizationA_->numberRows()]; int returnCode = coinFactorizationA_->updateColumnFT(regionSparse, regionSparse2); networkBasis_->updateColumn(regionSparse, save, -1); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, coinFactorizationA_->numberRows()*sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { int numberRows = coinFactorizationA_->numberRows(); for (i = 0; i < numberRows; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else networkBasis_->updateColumn(regionSparse, regionSparse2, -1); return 1; #endif } #endif } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute) const { #ifdef CLP_DEBUG if (!noPermute) regionSparse->checkClear(); #endif if (!numberRows()) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif int returnCode; if (coinFactorizationA_) { coinFactorizationA_->setCollectStatistics(true); returnCode = coinFactorizationA_->updateColumn(regionSparse, regionSparse2, noPermute); coinFactorizationA_->setCollectStatistics(false); } else { returnCode = coinFactorizationB_->updateColumn(regionSparse, regionSparse2, noPermute); } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(5); #endif //#define PRINT_VECTOR #ifdef PRINT_VECTOR printf("Update\n"); regionSparse2->print(); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[coinFactorizationA_->numberRows()]; int returnCode = coinFactorizationA_->updateColumn(regionSparse, regionSparse2, noPermute); networkBasis_->updateColumn(regionSparse, save, -1); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, coinFactorizationA_->numberRows()*sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { int numberRows = coinFactorizationA_->numberRows(); for (i = 0; i < numberRows; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else networkBasis_->updateColumn(regionSparse, regionSparse2, -1); return 1; #endif } #endif } /* Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ int ClpFactorization::updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, CoinIndexedVector * regionSparse2, CoinIndexedVector * regionSparse3, bool noPermuteRegion3) { #ifdef CLP_DEBUG regionSparse1->checkClear(); #endif if (!numberRows()) return 0; int returnCode = 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif if (coinFactorizationA_) { coinFactorizationA_->setCollectStatistics(true); if (coinFactorizationA_->spaceForForrestTomlin()) { assert (regionSparse2->packedMode()); assert (!regionSparse3->packedMode()); returnCode = coinFactorizationA_->updateTwoColumnsFT(regionSparse1, regionSparse2, regionSparse3, noPermuteRegion3); } else { returnCode = coinFactorizationA_->updateColumnFT(regionSparse1, regionSparse2); coinFactorizationA_->updateColumn(regionSparse1, regionSparse3, noPermuteRegion3); } coinFactorizationA_->setCollectStatistics(false); } else { #if 0 CoinSimpFactorization * fact = dynamic_cast< CoinSimpFactorization*>(coinFactorizationB_); if (!fact) { returnCode = coinFactorizationB_->updateColumnFT(regionSparse1, regionSparse2); coinFactorizationB_->updateColumn(regionSparse1, regionSparse3, noPermuteRegion3); } else { returnCode = fact->updateTwoColumnsFT(regionSparse1, regionSparse2, regionSparse3, noPermuteRegion3); } #else #ifdef CLP_REUSE_ETAS int tempInfo[2]; tempInfo[0] = model_->numberIterations(); tempInfo[1] = model_->sequenceIn(); coinFactorizationB_->setUsefulInformation(tempInfo, 3); #endif returnCode = coinFactorizationB_->updateTwoColumnsFT( regionSparse1, regionSparse2, regionSparse3, noPermuteRegion3); #endif } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(9); #endif #ifdef PRINT_VECTOR printf("UpdateTwoFT\n"); regionSparse2->print(); regionSparse3->print(); #endif return returnCode; #ifndef SLIM_CLP } else { returnCode = updateColumnFT(regionSparse1, regionSparse2); updateColumn(regionSparse1, regionSparse3, noPermuteRegion3); } #endif return returnCode; } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnForDebug ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute) const { if (!noPermute) regionSparse->checkClear(); if (!coinFactorizationA_->numberRows()) return 0; coinFactorizationA_->setCollectStatistics(false); int returnCode = coinFactorizationA_->updateColumn(regionSparse, regionSparse2, noPermute); return returnCode; } /* Updates one column (BTRAN) from region2 region1 starts as zero and is zero at end */ int ClpFactorization::updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const { if (!numberRows()) return 0; #ifndef SLIM_CLP if (!networkBasis_) { #endif #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif int returnCode; if (coinFactorizationA_) { coinFactorizationA_->setCollectStatistics(true); returnCode = coinFactorizationA_->updateColumnTranspose(regionSparse, regionSparse2); coinFactorizationA_->setCollectStatistics(false); } else { returnCode = coinFactorizationB_->updateColumnTranspose(regionSparse, regionSparse2); } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(6); #endif #ifdef PRINT_VECTOR printf("UpdateTranspose\n"); regionSparse2->print(); #endif return returnCode; #ifndef SLIM_CLP } else { #ifdef CHECK_NETWORK CoinIndexedVector * save = new CoinIndexedVector(*regionSparse2); double * check = new double[coinFactorizationA_->numberRows()]; int returnCode = coinFactorizationA_->updateColumnTranspose(regionSparse, regionSparse2); networkBasis_->updateColumnTranspose(regionSparse, save); int i; double * array = regionSparse2->denseVector(); int * indices = regionSparse2->getIndices(); int n = regionSparse2->getNumElements(); memset(check, 0, coinFactorizationA_->numberRows()*sizeof(double)); double * array2 = save->denseVector(); int * indices2 = save->getIndices(); int n2 = save->getNumElements(); assert (n == n2); if (save->packedMode()) { for (i = 0; i < n; i++) { check[indices[i]] = array[i]; } for (i = 0; i < n; i++) { double value2 = array2[i]; assert (check[indices2[i]] == value2); } } else { int numberRows = coinFactorizationA_->numberRows(); for (i = 0; i < numberRows; i++) { double value1 = array[i]; double value2 = array2[i]; assert (value1 == value2); } } delete save; delete [] check; return returnCode; #else return networkBasis_->updateColumnTranspose(regionSparse, regionSparse2); #endif } #endif } /* makes a row copy of L for speed and to allow very sparse problems */ void ClpFactorization::goSparse() { #ifndef SLIM_CLP if (!networkBasis_) { #endif if (coinFactorizationA_) { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif coinFactorizationA_->goSparse(); #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(7); #endif } } } // Cleans up i.e. gets rid of network basis void ClpFactorization::cleanUp() { #ifndef SLIM_CLP delete networkBasis_; networkBasis_ = NULL; #endif if (coinFactorizationA_) coinFactorizationA_->resetStatistics(); } /// Says whether to redo pivot order bool ClpFactorization::needToReorder() const { #ifdef CHECK_NETWORK return true; #endif #ifndef SLIM_CLP if (!networkBasis_) #endif return true; #ifndef SLIM_CLP else return false; #endif } // Get weighted row list void ClpFactorization::getWeights(int * weights) const { #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(-1); #endif #ifndef SLIM_CLP if (networkBasis_) { // Network - just unit int numberRows = coinFactorizationA_->numberRows(); for (int i = 0; i < numberRows; i++) weights[i] = 1; return; } #endif int * numberInRow = coinFactorizationA_->numberInRow(); int * numberInColumn = coinFactorizationA_->numberInColumn(); int * permuteBack = coinFactorizationA_->pivotColumnBack(); int * indexRowU = coinFactorizationA_->indexRowU(); const CoinBigIndex * startColumnU = coinFactorizationA_->startColumnU(); const CoinBigIndex * startRowL = coinFactorizationA_->startRowL(); int numberRows = coinFactorizationA_->numberRows(); if (!startRowL || !coinFactorizationA_->numberInRow()) { int * temp = new int[numberRows]; memset(temp, 0, numberRows * sizeof(int)); int i; for (i = 0; i < numberRows; i++) { // one for pivot temp[i]++; CoinBigIndex j; for (j = startColumnU[i]; j < startColumnU[i] + numberInColumn[i]; j++) { int iRow = indexRowU[j]; temp[iRow]++; } } CoinBigIndex * startColumnL = coinFactorizationA_->startColumnL(); int * indexRowL = coinFactorizationA_->indexRowL(); int numberL = coinFactorizationA_->numberL(); CoinBigIndex baseL = coinFactorizationA_->baseL(); for (i = baseL; i < baseL + numberL; i++) { CoinBigIndex j; for (j = startColumnL[i]; j < startColumnL[i+1]; j++) { int iRow = indexRowL[j]; temp[iRow]++; } } for (i = 0; i < numberRows; i++) { int number = temp[i]; int iPermute = permuteBack[i]; weights[iPermute] = number; } delete [] temp; } else { int i; for (i = 0; i < numberRows; i++) { int number = startRowL[i+1] - startRowL[i] + numberInRow[i] + 1; //number = startRowL[i+1]-startRowL[i]+1; //number = numberInRow[i]+1; int iPermute = permuteBack[i]; weights[iPermute] = number; } } #ifdef CLP_FACTORIZATION_INSTRUMENT factorization_instrument(8); #endif } // Set tolerances to safer of existing and given void ClpFactorization::saferTolerances ( double zeroValue, double pivotValue) { double newValue; // better to have small tolerance even if slower if (zeroValue > 0.0) newValue = zeroValue; else newValue = -zeroTolerance() * zeroValue; zeroTolerance(CoinMin(zeroTolerance(), zeroValue)); // better to have large tolerance even if slower if (pivotValue > 0.0) newValue = pivotValue; else newValue = -pivotTolerance() * pivotValue; pivotTolerance(CoinMin(CoinMax(pivotTolerance(), newValue), 0.999)); } // Sets factorization void ClpFactorization::setFactorization(ClpFactorization & rhs) { ClpFactorization::operator=(rhs); } #endif Clp-1.15.10/src/ClpDynamicMatrix.hpp0000644000076600007660000003337011602416137015572 0ustar coincoin/* $Id: ClpDynamicMatrix.hpp 1755 2011-06-28 18:24:31Z 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 ClpDynamicMatrix_H #define ClpDynamicMatrix_H #include "CoinPragma.hpp" #include "ClpPackedMatrix.hpp" class ClpSimplex; /** This implements a dynamic matrix when we have a limit on the number of "interesting rows". This version inherits from ClpPackedMatrix and knows that the real matrix is gub. A later version could use shortest path to generate columns. */ class ClpDynamicMatrix : public ClpPackedMatrix { public: /// enums for status of various sorts enum DynamicStatus { soloKey = 0x00, inSmall = 0x01, atUpperBound = 0x02, atLowerBound = 0x03 }; /**@name Main functions provided */ //@{ /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /** update information for a pivot (and effective rhs) */ virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); /** Returns effective RHS offset if it is being used. This is used for long problems or big dynamic or anywhere where going through full columns is expensive. This may re-compute */ virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, bool check = false); using ClpPackedMatrix::times ; /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /// Modifies rhs offset void modifyOffset(int sequence, double amount); /// Gets key value when none in small double keyValue(int iSet) const; /** mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended updates array (and may use other if dual values pass) mode=1 - Update dual solution after "transposeTimes" using extended rows. mode=2 - Compute all djs and compute key dual infeasibilities mode=3 - Report on key dual infeasibilities mode=4 - Modify before updateTranspose in partial pricing */ virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, double * other, int mode); /** mode=0 - Create list of non-key basics in pivotVariable_ using number as numberBasic in and out mode=1 - Set all key variables as basic mode=2 - return number extra rows needed, number gives maximum number basic mode=3 - before replaceColumn mode=4 - return 1 if can do primal, 2 if dual, 3 if both mode=5 - save any status stuff (when in good state) mode=6 - restore status stuff mode=7 - flag given variable (normally sequenceIn) mode=8 - unflag all variables mode=9 - synchronize costs mode=10 - return 1 if there may be changing bounds on variable (column generation) mode=11 - make sure set is clean (used when a variable rejected - but not flagged) mode=12 - after factorize but before permute stuff mode=13 - at end of simplex to delete stuff */ virtual int generalExpanded(ClpSimplex * model, int mode, int & number); /** Purely for column generation and similar ideas. Allows matrix and any bounds or costs to be updated (sensibly). Returns non-zero if any changes. */ virtual int refresh(ClpSimplex * model); /** Creates a variable. This is called after partial pricing and will modify matrix. Will update bestSequence. */ virtual void createVariable(ClpSimplex * model, int & bestSequence); /// Returns reduced cost of a variable virtual double reducedCost( ClpSimplex * model, int sequence) const; /// Does gub crash void gubCrash(); /// Writes out model (without names) void writeMps(const char * name); /// Populates initial matrix from dynamic status void initialProblem(); /** Adds in a column to gub structure (called from descendant) and returns sequence */ int addColumn(int numberEntries, const int * row, const double * element, double cost, double lower, double upper, int iSet, DynamicStatus status); /** If addColumn forces compression then this allows descendant to know what to do. If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. Entries at upper bound (really nonzero) never go out (at present). */ virtual void packDown(const int * , int ) {} /// Gets lower bound (to simplify coding) inline double columnLower(int sequence) const { if (columnLower_) return columnLower_[sequence]; else return 0.0; } /// Gets upper bound (to simplify coding) inline double columnUpper(int sequence) const { if (columnUpper_) return columnUpper_[sequence]; else return COIN_DBL_MAX; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpDynamicMatrix(); /** This is the real constructor. It assumes factorization frequency will not be changed. This resizes model !!!! The contents of original matrix in model will be taken over and original matrix will be sanitized so can be deleted (to avoid a very small memory leak) */ ClpDynamicMatrix(ClpSimplex * model, int numberSets, int numberColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * columnLower = NULL, const double * columnUpper = NULL, const unsigned char * status = NULL, const unsigned char * dynamicStatus = NULL); /** Destructor */ virtual ~ClpDynamicMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpDynamicMatrix(const ClpDynamicMatrix&); /** The copy constructor from an CoinPackedMatrix. */ ClpDynamicMatrix(const CoinPackedMatrix&); ClpDynamicMatrix& operator=(const ClpDynamicMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; //@} /**@name gets and sets */ //@{ /// Status of row slacks inline ClpSimplex::Status getStatus(int sequence) const { return static_cast (status_[sequence] & 7); } inline void setStatus(int sequence, ClpSimplex::Status status) { unsigned char & st_byte = status_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | status); } /// Whether flagged slack inline bool flaggedSlack(int i) const { return (status_[i] & 8) != 0; } inline void setFlaggedSlack(int i) { status_[i] = static_cast(status_[i] | 8); } inline void unsetFlaggedSlack(int i) { status_[i] = static_cast(status_[i] & ~8); } /// Number of sets (dynamic rows) inline int numberSets() const { return numberSets_; } /// Number of possible gub variables inline int numberGubEntries() const { return startSet_[numberSets_];} /// Sets inline int * startSets() const { return startSet_;} /// Whether flagged inline bool flagged(int i) const { return (dynamicStatus_[i] & 8) != 0; } inline void setFlagged(int i) { dynamicStatus_[i] = static_cast(dynamicStatus_[i] | 8); } inline void unsetFlagged(int i) { dynamicStatus_[i] = static_cast(dynamicStatus_[i] & ~8); } inline void setDynamicStatus(int sequence, DynamicStatus status) { unsigned char & st_byte = dynamicStatus_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | status); } inline DynamicStatus getDynamicStatus(int sequence) const { return static_cast (dynamicStatus_[sequence] & 7); } /// Saved value of objective offset inline double objectiveOffset() const { return objectiveOffset_; } /// Starts of each column inline CoinBigIndex * startColumn() const { return startColumn_; } /// rows inline int * row() const { return row_; } /// elements inline double * element() const { return element_; } /// costs inline double * cost() const { return cost_; } /// ids of active columns (just index here) inline int * id() const { return id_; } /// Optional lower bounds on columns inline double * columnLower() const { return columnLower_; } /// Optional upper bounds on columns inline double * columnUpper() const { return columnUpper_; } /// Lower bounds on sets inline double * lowerSet() const { return lowerSet_; } /// Upper bounds on sets inline double * upperSet() const { return upperSet_; } /// size inline int numberGubColumns() const { return numberGubColumns_; } /// first free inline int firstAvailable() const { return firstAvailable_; } /// first dynamic inline int firstDynamic() const { return firstDynamic_; } /// number of columns in dynamic model inline int lastDynamic() const { return lastDynamic_; } /// number of rows in original model inline int numberStaticRows() const { return numberStaticRows_; } /// size of working matrix (max) inline int numberElements() const { return numberElements_; } inline int * keyVariable() const { return keyVariable_; } /// Switches off dj checking each factorization (for BIG models) void switchOffCheck(); /// Status region for gub slacks inline unsigned char * gubRowStatus() const { return status_; } /// Status region for gub variables inline unsigned char * dynamicStatus() const { return dynamicStatus_; } /// Returns which set a variable is in int whichSet (int sequence) const; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Sum of dual infeasibilities double sumDualInfeasibilities_; /// Sum of primal infeasibilities double sumPrimalInfeasibilities_; /// Sum of Dual infeasibilities using tolerance based on error in duals double sumOfRelaxedDualInfeasibilities_; /// Sum of Primal infeasibilities using tolerance based on error in primals double sumOfRelaxedPrimalInfeasibilities_; /// Saved best dual on gub row in pricing double savedBestGubDual_; /// Saved best set in pricing int savedBestSet_; /// Backward pointer to pivot row !!! int * backToPivotRow_; /// Key variable of set (only accurate if none in small problem) mutable int * keyVariable_; /// Backward pointer to extra row int * toIndex_; // Reverse pointer from index to set int * fromIndex_; /// Number of sets (dynamic rows) int numberSets_; /// Number of active sets int numberActiveSets_; /// Saved value of objective offset double objectiveOffset_; /// Lower bounds on sets double * lowerSet_; /// Upper bounds on sets double * upperSet_; /// Status of slack on set unsigned char * status_; /// Pointer back to model ClpSimplex * model_; /// first free int firstAvailable_; /// first free when iteration started int firstAvailableBefore_; /// first dynamic int firstDynamic_; /// number of columns in dynamic model int lastDynamic_; /// number of rows in original model int numberStaticRows_; /// size of working matrix (max) int numberElements_; /// Number of dual infeasibilities int numberDualInfeasibilities_; /// Number of primal infeasibilities int numberPrimalInfeasibilities_; /** If pricing will declare victory (i.e. no check every factorization). -1 - always check 0 - don't check 1 - in don't check mode but looks optimal */ int noCheck_; /// Infeasibility weight when last full pass done double infeasibilityWeight_; /// size int numberGubColumns_; /// current maximum number of columns (then compress) int maximumGubColumns_; /// current maximum number of elemnts (then compress) int maximumElements_; /// Start of each set int * startSet_; /// next in chain int * next_; /// Starts of each column CoinBigIndex * startColumn_; /// rows int * row_; /// elements double * element_; /// costs double * cost_; /// ids of active columns (just index here) int * id_; /// for status and which bound unsigned char * dynamicStatus_; /// Optional lower bounds on columns double * columnLower_; /// Optional upper bounds on columns double * columnUpper_; //@} }; #endif Clp-1.15.10/src/ClpMessage.cpp0000644000076600007660000002252712130015370014371 0ustar coincoin/* $Id: ClpMessage.cpp 1928 2013-04-06 12:54: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). #include "CoinPragma.hpp" #include "ClpMessage.hpp" /// Structure for use by ClpMessage.cpp typedef struct { CLP_Message internalNumber; int externalNumber; // or continuation char detail; const char * message; } Clp_message; static Clp_message clp_us_english[] = { {CLP_SIMPLEX_FINISHED, 0, 1, "Optimal - objective value %g"}, {CLP_SIMPLEX_INFEASIBLE, 1, 1, "Primal infeasible - objective value %g"}, {CLP_SIMPLEX_UNBOUNDED, 2, 1, "Dual infeasible - objective value %g"}, {CLP_SIMPLEX_STOPPED, 3, 1, "Stopped - objective value %g"}, {CLP_SIMPLEX_ERROR, 4, 1, "Stopped due to errors - objective value %g"}, {CLP_SIMPLEX_INTERRUPT, 5, 1, "Stopped by event handler - objective value %g"}, {CLP_SIMPLEX_STATUS, 6, 1, "%d Obj %g%? Primal inf %g (%d)%? Dual inf %g (%d)%? w.o. free dual inf (%d)"}, {CLP_DUAL_BOUNDS, 25, 3, "Looking optimal checking bounds with %g"}, #if ABC_NORMAL_DEBUG>1 {CLP_SIMPLEX_ACCURACY, 60, 1, "Primal error %g, dual error %g"}, #else {CLP_SIMPLEX_ACCURACY, 60, 3, "Primal error %g, dual error %g"}, #endif {CLP_SIMPLEX_BADFACTOR, 7, 2, "Singular factorization of basis - status %d"}, {CLP_SIMPLEX_BOUNDTIGHTEN, 8, 3, "Bounds were tightened %d times"}, {CLP_SIMPLEX_INFEASIBILITIES, 9, 1, "%d infeasibilities"}, {CLP_SIMPLEX_FLAG, 10, 3, "Flagging variable %c%d"}, {CLP_SIMPLEX_GIVINGUP, 11, 2, "Stopping as close enough"}, {CLP_DUAL_CHECKB, 12, 2, "New dual bound of %g"}, {CLP_DUAL_ORIGINAL, 13, 3, "Going back to original objective"}, {CLP_SIMPLEX_PERTURB, 14, 1, "Perturbing problem by %g %% of %g - largest nonzero change %g (%% %g) - largest zero change %g"}, {CLP_PRIMAL_ORIGINAL, 15, 2, "Going back to original tolerance"}, {CLP_PRIMAL_WEIGHT, 16, 2, "New infeasibility weight of %g"}, {CLP_PRIMAL_OPTIMAL, 17, 2, "Looking optimal with tolerance of %g"}, {CLP_SINGULARITIES, 18, 2, "%d total structurals rejected in initial factorization"}, {CLP_MODIFIEDBOUNDS, 19, 1, "%d variables/rows fixed as scaled bounds too close"}, {CLP_RIMSTATISTICS1, 20, 2, "Absolute values of scaled objective range from %g to %g"}, {CLP_RIMSTATISTICS2, 21, 2, "Absolute values of scaled bounds range from %g to %g, minimum gap %g"}, {CLP_RIMSTATISTICS3, 22, 2, "Absolute values of scaled rhs range from %g to %g, minimum gap %g"}, {CLP_POSSIBLELOOP, 23, 2, "Possible loop - %d matches (%x) after %d checks"}, {CLP_SMALLELEMENTS, 24, 1, "Matrix will be packed to eliminate %d small elements"}, {CLP_DUPLICATEELEMENTS, 26, 1, "Matrix will be packed to eliminate %d duplicate elements"}, {CLP_SIMPLEX_HOUSE1, 101, 32, "dirOut %d, dirIn %d, theta %g, out %g, dj %g, alpha %g"}, {CLP_SIMPLEX_HOUSE2, 102, 4, "%d %g In: %c%d Out: %c%d%? dj ratio %g distance %g%? dj %g distance %g"}, {CLP_SIMPLEX_NONLINEAR, 103, 4, "Primal nonlinear change %g (%d)"}, {CLP_SIMPLEX_FREEIN, 104, 32, "Free column in %d"}, {CLP_SIMPLEX_PIVOTROW, 105, 32, "Pivot row %d"}, {CLP_DUAL_CHECK, 106, 4, "Btran alpha %g, ftran alpha %g"}, {CLP_PRIMAL_DJ, 107, 4, "For %c%d btran dj %g, ftran dj %g"}, {CLP_PACKEDSCALE_INITIAL, 1001, 2, "Initial range of elements is %g to %g"}, {CLP_PACKEDSCALE_WHILE, 1002, 3, "Range of elements is %g to %g"}, {CLP_PACKEDSCALE_FINAL, 1003, 2, "Final range of elements is %g to %g"}, {CLP_PACKEDSCALE_FORGET, 1004, 2, "Not bothering to scale as good enough"}, {CLP_INITIALIZE_STEEP, 1005, 3, "Initializing steepest edge weights - old %g, new %g"}, {CLP_UNABLE_OPEN, 6001, 0, "Unable to open file %s for reading"}, {CLP_BAD_BOUNDS, 6002, 1, "%d bad bound pairs or bad objectives were found - first at %c%d"}, {CLP_BAD_MATRIX, 6003, 1, "Matrix has %d large values, first at column %d, row %d is %g"}, {CLP_LOOP, 6004, 1, "Can't get out of loop - stopping"}, {CLP_IMPORT_RESULT, 27, 1, "Model was imported from %s in %g seconds"}, {CLP_IMPORT_ERRORS, 3001, 1, " There were %d errors when importing model from %s"}, {CLP_EMPTY_PROBLEM, 3002, 1, "Empty problem - %d rows, %d columns and %d elements"}, {CLP_CRASH, 28, 1, "Crash put %d variables in basis, %d dual infeasibilities"}, {CLP_END_VALUES_PASS, 29, 1, "End of values pass after %d iterations"}, {CLP_QUADRATIC_BOTH, 108, 32, "%s %d (%g) and %d (%g) both basic"}, {CLP_QUADRATIC_PRIMAL_DETAILS, 109, 32, "coeff %g, %g, %g - dj %g - deriv zero at %g, sj at %g"}, {CLP_IDIOT_ITERATION, 30, 1, "%d infeas %g, obj %g - mu %g, its %d, %d interior"}, {CLP_INFEASIBLE, 3003, 1, "Analysis indicates model infeasible or unbounded"}, {CLP_MATRIX_CHANGE, 31, 2, "Matrix can not be converted into %s"}, {CLP_TIMING, 32, 1, "%s objective %.10g - %d iterations time %.2f2%?, Presolve %.2f%?, Idiot %.2f%?"}, {CLP_INTERVAL_TIMING, 33, 2, "%s took %.2f seconds (total %.2f)"}, {CLP_SPRINT, 34, 1, "Pass %d took %d iterations, objective %g, dual infeasibilities %g( %d)"}, {CLP_BARRIER_ITERATION, 35, 1, "%d Primal %g Dual %g Complementarity %g - %d fixed, rank %d"}, {CLP_BARRIER_OBJECTIVE_GAP, 36, 3, "Feasible - objective gap %g"}, {CLP_BARRIER_GONE_INFEASIBLE, 37, 2, "Infeasible"}, {CLP_BARRIER_CLOSE_TO_OPTIMAL, 38, 2, "Close to optimal after %d iterations with complementarity %g"}, {CLP_BARRIER_COMPLEMENTARITY, 39, 2, "Complementarity %g - %s"}, {CLP_BARRIER_EXIT2, 40, 1, "Exiting - using solution from iteration %d"}, {CLP_BARRIER_STOPPING, 41, 1, "Exiting on iterations"}, {CLP_BARRIER_EXIT, 42, 1, "Optimal %s"}, {CLP_BARRIER_SCALING, 43, 3, "Scaling %s by %g"}, {CLP_BARRIER_MU, 44, 3, "Changing mu from %g to %g"}, {CLP_BARRIER_INFO, 45, 3, "Detail - %s"}, {CLP_BARRIER_END, 46, 1, "At end primal/dual infeasibilities %g/%g, complementarity gap %g, objective %g"}, {CLP_BARRIER_ACCURACY, 47, 2, "Relative error in phase %d, %d passes %g => %g"}, {CLP_BARRIER_SAFE, 48, 2, "Initial safe primal value %g, objective norm %g"}, {CLP_BARRIER_NEGATIVE_GAPS, 49, 3, "%d negative gaps summing to %g"}, {CLP_BARRIER_REDUCING, 50, 2, "Reducing %s step from %g to %g"}, {CLP_BARRIER_DIAGONAL, 51, 3, "Range of diagonal values is %g to %g"}, {CLP_BARRIER_SLACKS, 52, 3, "%d slacks increased, %d decreased this iteration"}, {CLP_BARRIER_DUALINF, 53, 3, "Maximum dual infeasibility on fixed is %g"}, {CLP_BARRIER_KILLED, 54, 3, "%d variables killed this iteration"}, {CLP_BARRIER_ABS_DROPPED, 55, 2, "Absolute error on dropped rows is %g"}, {CLP_BARRIER_ABS_ERROR, 56, 2, "Primal error is %g and dual error is %g"}, {CLP_BARRIER_FEASIBLE, 57, 2, "Infeasibilities - bound %g , primal %g ,dual %g"}, {CLP_BARRIER_STEP, 58, 2, "Steps - primal %g ,dual %g , mu %g"}, {CLP_BARRIER_KKT, 6005, 0, "Quadratic barrier needs a KKT factorization"}, {CLP_RIM_SCALE, 59, 1, "Automatic rim scaling gives objective scale of %g and rhs/bounds scale of %g"}, {CLP_SLP_ITER, 58, 1, "Pass %d objective %g - drop %g, largest delta %g"}, {CLP_COMPLICATED_MODEL, 3004, 1, "Can not use addRows or addColumns on CoinModel as mixed, %d rows, %d columns"}, {CLP_BAD_STRING_VALUES, 3005, 1, "%d string elements had no values associated with them"}, {CLP_CRUNCH_STATS, 61, 2, "Crunch %d (%d) rows, %d (%d) columns and %d (%d) elements"}, {CLP_PARAMETRICS_STATS, 62, 1, "Theta %g - objective %g"}, {CLP_PARAMETRICS_STATS2, 63, 2, "Theta %g - objective %g, %s in, %s out"}, #ifndef NO_FATHOM_PRINT {CLP_FATHOM_STATUS, 63, 2, "Fathoming node %d - %d nodes (%d iterations) - current depth %d"}, {CLP_FATHOM_SOLUTION, 64, 1, "Fathoming node %d - solution of %g after %d nodes at depth %d"}, {CLP_FATHOM_FINISH, 65, 1, "Fathoming node %d (depth %d) took %d nodes (%d iterations) - maximum depth %d"}, #endif {CLP_GENERAL, 1000, 1, "%s"}, {CLP_GENERAL2, 1001, 2, "%s"}, {CLP_GENERAL_WARNING, 3006, 1, "%s"}, {CLP_DUMMY_END, 999999, 0, ""} }; static Clp_message uk_english[] = { { CLP_SIMPLEX_FINISHED, 0, 1, "Optimal - objective value %g,\ okay CLP can solve some LPs but you really need Xpress from Dash Associates :-)" }, {CLP_DUMMY_END, 999999, 0, ""} }; /* Constructor */ ClpMessage::ClpMessage(Language language) : CoinMessages(sizeof(clp_us_english) / sizeof(Clp_message)) { language_ = language; strcpy(source_, "Clp"); class_ = 1; //solver Clp_message * message = clp_us_english; while (message->internalNumber != CLP_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) { case uk_en: message = uk_english; break; default: message = NULL; break; } // replace if any found if (message) { while (message->internalNumber != CLP_DUMMY_END) { replaceMessage(message->internalNumber, message->message); message ++; } } } Clp-1.15.10/src/ClpGubDynamicMatrix.cpp0000644000076600007660000030537711571121105016225 0ustar coincoin/* $Id: ClpGubDynamicMatrix.cpp 1732 2011-05-31 08:09: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). #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpNonLinearCost.hpp" // at end to get min/max! #include "ClpGubDynamicMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpGubDynamicMatrix::ClpGubDynamicMatrix () : ClpGubMatrix(), objectiveOffset_(0.0), startColumn_(NULL), row_(NULL), element_(NULL), cost_(NULL), fullStart_(NULL), id_(NULL), dynamicStatus_(NULL), lowerColumn_(NULL), upperColumn_(NULL), lowerSet_(NULL), upperSet_(NULL), numberGubColumns_(0), firstAvailable_(0), savedFirstAvailable_(0), firstDynamic_(0), lastDynamic_(0), numberElements_(0) { setType(13); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpGubDynamicMatrix::ClpGubDynamicMatrix (const ClpGubDynamicMatrix & rhs) : ClpGubMatrix(rhs) { objectiveOffset_ = rhs.objectiveOffset_; numberGubColumns_ = rhs.numberGubColumns_; firstAvailable_ = rhs.firstAvailable_; savedFirstAvailable_ = rhs.savedFirstAvailable_; firstDynamic_ = rhs.firstDynamic_; lastDynamic_ = rhs.lastDynamic_; numberElements_ = rhs.numberElements_; startColumn_ = ClpCopyOfArray(rhs.startColumn_, numberGubColumns_ + 1); CoinBigIndex numberElements = startColumn_[numberGubColumns_]; row_ = ClpCopyOfArray(rhs.row_, numberElements);; element_ = ClpCopyOfArray(rhs.element_, numberElements);; cost_ = ClpCopyOfArray(rhs.cost_, numberGubColumns_); fullStart_ = ClpCopyOfArray(rhs.fullStart_, numberSets_ + 1); id_ = ClpCopyOfArray(rhs.id_, lastDynamic_ - firstDynamic_); lowerColumn_ = ClpCopyOfArray(rhs.lowerColumn_, numberGubColumns_); upperColumn_ = ClpCopyOfArray(rhs.upperColumn_, numberGubColumns_); dynamicStatus_ = ClpCopyOfArray(rhs.dynamicStatus_, numberGubColumns_); lowerSet_ = ClpCopyOfArray(rhs.lowerSet_, numberSets_); upperSet_ = ClpCopyOfArray(rhs.upperSet_, numberSets_); } /* This is the real constructor*/ ClpGubDynamicMatrix::ClpGubDynamicMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * lowerColumn, const double * upperColumn, const unsigned char * status) : ClpGubMatrix() { objectiveOffset_ = model->objectiveOffset(); model_ = model; numberSets_ = numberSets; numberGubColumns_ = numberGubColumns; fullStart_ = ClpCopyOfArray(starts, numberSets_ + 1); lower_ = ClpCopyOfArray(lower, numberSets_); upper_ = ClpCopyOfArray(upper, numberSets_); int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); // Number of columns needed int numberGubInSmall = numberSets_ + numberRows + 2 * model->factorizationFrequency() + 2; // for small problems this could be too big //numberGubInSmall = CoinMin(numberGubInSmall,numberGubColumns_); int numberNeeded = numberGubInSmall + numberColumns; firstAvailable_ = numberColumns; savedFirstAvailable_ = numberColumns; firstDynamic_ = numberColumns; lastDynamic_ = numberNeeded; startColumn_ = ClpCopyOfArray(startColumn, numberGubColumns_ + 1); CoinBigIndex numberElements = startColumn_[numberGubColumns_]; row_ = ClpCopyOfArray(row, numberElements); element_ = new double[numberElements]; CoinBigIndex i; for (i = 0; i < numberElements; i++) element_[i] = element[i]; cost_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) { cost_[i] = cost[i]; // need sorted CoinSort_2(row_ + startColumn_[i], row_ + startColumn_[i+1], element_ + startColumn_[i]); } if (lowerColumn) { lowerColumn_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) lowerColumn_[i] = lowerColumn[i]; } else { lowerColumn_ = NULL; } if (upperColumn) { upperColumn_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) upperColumn_[i] = upperColumn[i]; } else { upperColumn_ = NULL; } if (upperColumn || lowerColumn) { lowerSet_ = new double[numberSets_]; for (i = 0; i < numberSets_; i++) { if (lower[i] > -1.0e20) lowerSet_[i] = lower[i]; else lowerSet_[i] = -1.0e30; } upperSet_ = new double[numberSets_]; for (i = 0; i < numberSets_; i++) { if (upper[i] < 1.0e20) upperSet_[i] = upper[i]; else upperSet_[i] = 1.0e30; } } else { lowerSet_ = NULL; upperSet_ = NULL; } start_ = NULL; end_ = NULL; dynamicStatus_ = NULL; id_ = new int[numberGubInSmall]; for (i = 0; i < numberGubInSmall; i++) id_[i] = -1; ClpPackedMatrix* originalMatrixA = dynamic_cast< ClpPackedMatrix*>(model->clpMatrix()); assert (originalMatrixA); CoinPackedMatrix * originalMatrix = originalMatrixA->getPackedMatrix(); originalMatrixA->setMatrixNull(); // so can be deleted safely // guess how much space needed double guess = originalMatrix->getNumElements() + 10; guess /= static_cast (numberColumns); guess *= 2 * numberGubColumns_; numberElements_ = static_cast (CoinMin(guess, 10000000.0)); numberElements_ = CoinMin(numberElements_, numberElements) + originalMatrix->getNumElements(); matrix_ = originalMatrix; flags_ &= ~1; // resize model (matrix stays same) model->resize(numberRows, numberNeeded); if (upperColumn_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i = firstDynamic_; i < lastDynamic_; i++) columnUpper[i] = 1.0e10; } // resize matrix // extra 1 is so can keep number of elements handy originalMatrix->reserve(numberNeeded, numberElements_, true); originalMatrix->reserve(numberNeeded + 1, numberElements_, false); originalMatrix->getMutableVectorStarts()[numberColumns] = originalMatrix->getNumElements(); // redo number of columns numberColumns = matrix_->getNumCols(); backward_ = new int[numberNeeded]; backToPivotRow_ = new int[numberNeeded]; // We know a bit better delete [] changeCost_; changeCost_ = new double [numberRows+numberSets_]; keyVariable_ = new int[numberSets_]; // signal to need new ordering next_ = NULL; for (int iColumn = 0; iColumn < numberNeeded; iColumn++) backward_[iColumn] = -1; firstGub_ = firstDynamic_; lastGub_ = lastDynamic_; if (!lowerColumn_ && !upperColumn_) gubType_ = 8; if (status) { status_ = ClpCopyOfArray(status, numberSets_); } else { status_ = new unsigned char [numberSets_]; memset(status_, 0, numberSets_); int i; for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } } saveStatus_ = new unsigned char [numberSets_]; memset(saveStatus_, 0, numberSets_); savedKeyVariable_ = new int [numberSets_]; memset(savedKeyVariable_, 0, numberSets_ * sizeof(int)); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpGubDynamicMatrix::~ClpGubDynamicMatrix () { delete [] startColumn_; delete [] row_; delete [] element_; delete [] cost_; delete [] fullStart_; delete [] id_; delete [] dynamicStatus_; delete [] lowerColumn_; delete [] upperColumn_; delete [] lowerSet_; delete [] upperSet_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpGubDynamicMatrix & ClpGubDynamicMatrix::operator=(const ClpGubDynamicMatrix& rhs) { if (this != &rhs) { ClpGubMatrix::operator=(rhs); delete [] startColumn_; delete [] row_; delete [] element_; delete [] cost_; delete [] fullStart_; delete [] id_; delete [] dynamicStatus_; delete [] lowerColumn_; delete [] upperColumn_; delete [] lowerSet_; delete [] upperSet_; objectiveOffset_ = rhs.objectiveOffset_; numberGubColumns_ = rhs.numberGubColumns_; firstAvailable_ = rhs.firstAvailable_; savedFirstAvailable_ = rhs.savedFirstAvailable_; firstDynamic_ = rhs.firstDynamic_; lastDynamic_ = rhs.lastDynamic_; numberElements_ = rhs.numberElements_; startColumn_ = ClpCopyOfArray(rhs.startColumn_, numberGubColumns_ + 1); int numberElements = startColumn_[numberGubColumns_]; row_ = ClpCopyOfArray(rhs.row_, numberElements);; element_ = ClpCopyOfArray(rhs.element_, numberElements);; cost_ = ClpCopyOfArray(rhs.cost_, numberGubColumns_); fullStart_ = ClpCopyOfArray(rhs.fullStart_, numberSets_ + 1); id_ = ClpCopyOfArray(rhs.id_, lastDynamic_ - firstDynamic_); lowerColumn_ = ClpCopyOfArray(rhs.lowerColumn_, numberGubColumns_); upperColumn_ = ClpCopyOfArray(rhs.upperColumn_, numberGubColumns_); dynamicStatus_ = ClpCopyOfArray(rhs.dynamicStatus_, numberGubColumns_); lowerSet_ = ClpCopyOfArray(rhs.lowerSet_, numberSets_); upperSet_ = ClpCopyOfArray(rhs.upperSet_, numberSets_); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpGubDynamicMatrix::clone() const { return new ClpGubDynamicMatrix(*this); } // Partial pricing void ClpGubDynamicMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { assert(!model->rowScale()); numberWanted = currentWanted_; if (!numberSets_) { // no gub ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); return; } else { // and do some proportion of full set int startG2 = static_cast (startFraction * numberSets_); int endG2 = static_cast (endFraction * numberSets_ + 0.1); endG2 = CoinMin(endG2, numberSets_); //printf("gub price - set start %d end %d\n", // startG2,endG2); double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); double * cost = model->costRegion(); double bestDj; int numberRows = model->numberRows(); int numberColumns = lastDynamic_; // If nothing found yet can go all the way to end int endAll = endG2; if (bestSequence < 0 && !startG2) endAll = numberSets_; if (bestSequence >= 0) bestDj = fabs(reducedCost[bestSequence]); else bestDj = tolerance; int saveSequence = bestSequence; double djMod = 0.0; double infeasibilityCost = model->infeasibilityCost(); double bestDjMod = 0.0; //printf("iteration %d start %d end %d - wanted %d\n",model->numberIterations(), // startG2,endG2,numberWanted); int bestType = -1; int bestSet = -1; const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); int * length = matrix_->getMutableVectorLengths(); #if 0 // make sure first available is clean (in case last iteration rejected) cost[firstAvailable_] = 0.0; length[firstAvailable_] = 0; model->nonLinearCost()->setOne(firstAvailable_, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); { for (int i = firstAvailable_; i < lastDynamic_; i++) assert(!cost[i]); } #endif #ifdef CLP_DEBUG { for (int i = firstDynamic_; i < firstAvailable_; i++) { assert (getDynamicStatus(id_[i-firstDynamic_]) == inSmall); } } #endif int minSet = minimumObjectsScan_ < 0 ? 5 : minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ < 0 ? 5 : minimumGoodReducedCosts_; for (int iSet = startG2; iSet < endAll; iSet++) { if (numberWanted + minNeg < originalWanted_ && iSet > startG2 + minSet) { // give up numberWanted = 0; break; } else if (iSet == endG2 && bestSequence >= 0) { break; } CoinBigIndex j; int iBasic = keyVariable_[iSet]; if (iBasic >= numberColumns) { djMod = - weight(iSet) * infeasibilityCost; } else { // get dj without assert (model->getStatus(iBasic) == ClpSimplex::basic); djMod = 0.0; for (j = startColumn[iBasic]; j < startColumn[iBasic] + length[iBasic]; j++) { int jRow = row[j]; djMod -= duals[jRow] * element[j]; } djMod += cost[iBasic]; // See if gub slack possible - dj is djMod if (getStatus(iSet) == ClpSimplex::atLowerBound) { double value = -djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; bestType = 0; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet) == ClpSimplex::atUpperBound) { double value = djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; bestType = 0; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } for (int iSequence = fullStart_[iSet]; iSequence < fullStart_[iSet+1]; iSequence++) { DynamicStatus status = getDynamicStatus(iSequence); if (status != inSmall) { double value = cost_[iSequence] - djMod; for (j = startColumn_[iSequence]; j < startColumn_[iSequence+1]; j++) { int jRow = row_[j]; value -= duals[jRow] * element_[j]; } // change sign if at lower bound if (status == atLowerBound) value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; bestType = 1; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; } } } } } if (numberWanted <= 0) { numberWanted = 0; break; } } // Do packed part before gub and small gub - but lightly int saveMinNeg = minimumGoodReducedCosts_; int saveSequence2 = bestSequence; if (bestSequence >= 0) minimumGoodReducedCosts_ = -2; int saveLast = lastGub_; lastGub_ = firstAvailable_; currentWanted_ = numberWanted; ClpGubMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); minimumGoodReducedCosts_ = saveMinNeg; lastGub_ = saveLast; if (bestSequence != saveSequence2) { bestType = -1; // in normal or small gub part saveSequence = bestSequence; } if (bestSequence != saveSequence || bestType >= 0) { double * lowerColumn = model->lowerRegion(); double * upperColumn = model->upperRegion(); double * solution = model->solutionRegion(); if (bestType > 0) { // recompute dj and create double value = cost_[bestSequence] - bestDjMod; for (CoinBigIndex jBigIndex = startColumn_[bestSequence]; jBigIndex < startColumn_[bestSequence+1]; jBigIndex++) { int jRow = row_[jBigIndex]; value -= duals[jRow] * element_[jBigIndex]; } double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[bestSequence+1] - startColumn_[bestSequence]; if (numberElements + numberThis > numberElements_) { // need to redo numberElements_ = CoinMax(3 * numberElements_ / 2, numberElements + numberThis); matrix_->reserve(numberColumns, numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } // already set startColumn[firstAvailable_]=numberElements; length[firstAvailable_] = numberThis; model->costRegion()[firstAvailable_] = cost_[bestSequence]; CoinBigIndex base = startColumn_[bestSequence]; for (int j = 0; j < numberThis; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } id_[firstAvailable_-firstDynamic_] = bestSequence; //printf("best %d\n",bestSequence); backward_[firstAvailable_] = bestSet; model->solutionRegion()[firstAvailable_] = 0.0; if (!lowerColumn_ && !upperColumn_) { model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); lowerColumn[firstAvailable_] = 0.0; upperColumn[firstAvailable_] = COIN_DBL_MAX; } else { DynamicStatus status = getDynamicStatus(bestSequence); if (lowerColumn_) lowerColumn[firstAvailable_] = lowerColumn_[bestSequence]; else lowerColumn[firstAvailable_] = 0.0; if (upperColumn_) upperColumn[firstAvailable_] = upperColumn_[bestSequence]; else upperColumn[firstAvailable_] = COIN_DBL_MAX; if (status == atLowerBound) { solution[firstAvailable_] = lowerColumn[firstAvailable_]; model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); } else { solution[firstAvailable_] = upperColumn[firstAvailable_]; model->setStatus(firstAvailable_, ClpSimplex::atUpperBound); } } model->nonLinearCost()->setOne(firstAvailable_, solution[firstAvailable_], lowerColumn[firstAvailable_], upperColumn[firstAvailable_], cost_[bestSequence]); bestSequence = firstAvailable_; // firstAvailable_ only updated if good pivot (in updatePivot) startColumn[firstAvailable_+1] = numberElements; //printf("price struct %d - dj %g gubpi %g\n",bestSequence,value,bestDjMod); reducedCost[bestSequence] = value; gubSlackIn_ = -1; } else { // slack - make last column gubSlackIn_ = bestSequence - numberRows - numberColumns; bestSequence = numberColumns + 2 * numberRows; reducedCost[bestSequence] = bestDjMod; //printf("price slack %d - gubpi %g\n",gubSlackIn_,bestDjMod); model->setStatus(bestSequence, getStatus(gubSlackIn_)); if (getStatus(gubSlackIn_) == ClpSimplex::atUpperBound) solution[bestSequence] = upper_[gubSlackIn_]; else solution[bestSequence] = lower_[gubSlackIn_]; lowerColumn[bestSequence] = lower_[gubSlackIn_]; upperColumn[bestSequence] = upper_[gubSlackIn_]; model->costRegion()[bestSequence] = 0.0; model->nonLinearCost()->setOne(bestSequence, solution[bestSequence], lowerColumn[bestSequence], upperColumn[bestSequence], 0.0); } savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } // See if may be finished if (!startG2 && bestSequence < 0) infeasibilityWeight_ = model_->infeasibilityCost(); else if (bestSequence >= 0) infeasibilityWeight_ = -1.0; } currentWanted_ = numberWanted; } // This is local to Gub to allow synchronization when status is good int ClpGubDynamicMatrix::synchronize(ClpSimplex * model, int mode) { int returnNumber = 0; switch (mode) { case 0: { #ifdef CLP_DEBUG { for (int i = 0; i < numberSets_; i++) assert(toIndex_[i] == -1); } #endif // lookup array int * lookup = new int[lastDynamic_]; int iColumn; int numberColumns = model->numberColumns(); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double * cost = model->costRegion(); double * lowerColumn = model->lowerRegion(); double * upperColumn = model->upperRegion(); int * pivotVariable = model->pivotVariable(); CoinBigIndex numberElements = startColumn[firstDynamic_]; // first just do lookup and basic stuff int currentNumber = firstAvailable_; firstAvailable_ = firstDynamic_; int numberToDo = 0; double objectiveChange = 0.0; double * solution = model->solutionRegion(); for (iColumn = firstDynamic_; iColumn < currentNumber; iColumn++) { int iSet = backward_[iColumn]; if (toIndex_[iSet] < 0) { toIndex_[iSet] = 0; fromIndex_[numberToDo++] = iSet; } if (model->getStatus(iColumn) == ClpSimplex::basic || iColumn == keyVariable_[iSet]) { lookup[iColumn] = firstAvailable_; if (iColumn != keyVariable_[iSet]) { int iPivot = backToPivotRow_[iColumn]; backToPivotRow_[firstAvailable_] = iPivot; pivotVariable[iPivot] = firstAvailable_; } firstAvailable_++; } else { int jColumn = id_[iColumn-firstDynamic_]; setDynamicStatus(jColumn, atLowerBound); if (lowerColumn_ || upperColumn_) { if (model->getStatus(iColumn) == ClpSimplex::atUpperBound) setDynamicStatus(jColumn, atUpperBound); // treat solution as if exactly at a bound double value = solution[iColumn]; if (fabs(value - lowerColumn[iColumn]) < fabs(value - upperColumn[iColumn])) value = lowerColumn[iColumn]; else value = upperColumn[iColumn]; objectiveChange += cost[iColumn] * value; // redo lower and upper on sets double shift = value; if (lowerSet_[iSet] > -1.0e20) lower_[iSet] = lowerSet_[iSet] - shift; if (upperSet_[iSet] < 1.0e20) upper_[iSet] = upperSet_[iSet] - shift; } lookup[iColumn] = -1; } } model->setObjectiveOffset(model->objectiveOffset() + objectiveChange); firstAvailable_ = firstDynamic_; for (iColumn = firstDynamic_; iColumn < currentNumber; iColumn++) { if (lookup[iColumn] >= 0) { // move int jColumn = id_[iColumn-firstDynamic_]; id_[firstAvailable_-firstDynamic_] = jColumn; int numberThis = startColumn_[jColumn+1] - startColumn_[jColumn]; length[firstAvailable_] = numberThis; cost[firstAvailable_] = cost[iColumn]; lowerColumn[firstAvailable_] = lowerColumn[iColumn]; upperColumn[firstAvailable_] = upperColumn[iColumn]; double originalLower = lowerColumn_ ? lowerColumn_[jColumn] : 0.0; double originalUpper = upperColumn_ ? upperColumn_[jColumn] : COIN_DBL_MAX; if (originalUpper > 1.0e30) originalUpper = COIN_DBL_MAX; model->nonLinearCost()->setOne(firstAvailable_, solution[iColumn], originalLower, originalUpper, cost_[jColumn]); CoinBigIndex base = startColumn_[jColumn]; for (int j = 0; j < numberThis; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } model->setStatus(firstAvailable_, model->getStatus(iColumn)); backward_[firstAvailable_] = backward_[iColumn]; solution[firstAvailable_] = solution[iColumn]; firstAvailable_++; startColumn[firstAvailable_] = numberElements; } } // clean up next_ int * temp = new int [firstAvailable_]; for (int jSet = 0; jSet < numberToDo; jSet++) { int iSet = fromIndex_[jSet]; toIndex_[iSet] = -1; int last = keyVariable_[iSet]; int j = next_[last]; bool setTemp = true; if (last < lastDynamic_) { last = lookup[last]; assert (last >= 0); keyVariable_[iSet] = last; } else if (j >= 0) { int newJ = lookup[j]; assert (newJ >= 0); j = next_[j]; next_[last] = newJ; last = newJ; } else { next_[last] = -(iSet + numberColumns + 1); setTemp = false; } while (j >= 0) { int newJ = lookup[j]; assert (newJ >= 0); temp[last] = newJ; last = newJ; j = next_[j]; } if (setTemp) temp[last] = -(keyVariable_[iSet] + 1); if (lowerSet_) { // we only need to get lower_ and upper_ correct double shift = 0.0; for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) if (getDynamicStatus(j) == atUpperBound) shift += upperColumn_[j]; else if (getDynamicStatus(j) == atLowerBound && lowerColumn_) shift += lowerColumn_[j]; if (lowerSet_[iSet] > -1.0e20) lower_[iSet] = lowerSet_[iSet] - shift; if (upperSet_[iSet] < 1.0e20) upper_[iSet] = upperSet_[iSet] - shift; } } // move to next_ CoinMemcpyN(temp + firstDynamic_, (firstAvailable_ - firstDynamic_), next_ + firstDynamic_); // if odd iterations may be one out so adjust currentNumber currentNumber = CoinMin(currentNumber + 1, lastDynamic_); // zero solution CoinZeroN(solution + firstAvailable_, currentNumber - firstAvailable_); // zero cost CoinZeroN(cost + firstAvailable_, currentNumber - firstAvailable_); // zero lengths CoinZeroN(length + firstAvailable_, currentNumber - firstAvailable_); for ( iColumn = firstAvailable_; iColumn < currentNumber; iColumn++) { model->nonLinearCost()->setOne(iColumn, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(iColumn, ClpSimplex::atLowerBound); backward_[iColumn] = -1; } delete [] lookup; delete [] temp; // make sure fromIndex clean fromIndex_[0] = -1; //#define CLP_DEBUG #ifdef CLP_DEBUG // debug { int i; int numberRows = model->numberRows(); char * xxxx = new char[numberColumns]; memset(xxxx, 0, numberColumns); for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; assert (model->getStatus(iPivot) == ClpSimplex::basic); if (iPivot < numberColumns && backward_[iPivot] >= 0) xxxx[iPivot] = 1; } for (i = 0; i < numberSets_; i++) { int key = keyVariable_[i]; int iColumn = next_[key]; int k = 0; while(iColumn >= 0) { k++; assert (k < 100); assert (backward_[iColumn] == i); iColumn = next_[iColumn]; } int stop = -(key + 1); while (iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; k++; assert (k < 100); assert (backward_[iColumn] == i); iColumn = next_[iColumn]; } iColumn = next_[key]; while (iColumn >= 0) { assert (xxxx[iColumn]); xxxx[iColumn] = 0; iColumn = next_[iColumn]; } } for (i = 0; i < numberColumns; i++) { if (i < numberColumns && backward_[i] >= 0) { assert (!xxxx[i] || i == keyVariable_[backward_[i]]); } } delete [] xxxx; } { for (int i = 0; i < numberSets_; i++) assert(toIndex_[i] == -1); } #endif savedFirstAvailable_ = firstAvailable_; } break; // flag a variable case 1: { // id will be sitting at firstAvailable int sequence = id_[firstAvailable_-firstDynamic_]; assert (!flagged(sequence)); setFlagged(sequence); model->clearFlagged(firstAvailable_); } break; // unflag all variables case 2: { for (int i = 0; i < numberGubColumns_; i++) { if (flagged(i)) { unsetFlagged(i); returnNumber++; } } } break; // just reset costs and bounds (primal) case 3: { double * cost = model->costRegion(); double * solution = model->solutionRegion(); double * lowerColumn = model->columnLower(); double * upperColumn = model->columnUpper(); for (int i = firstDynamic_; i < firstAvailable_; i++) { int jColumn = id_[i-firstDynamic_]; cost[i] = cost_[jColumn]; if (!lowerColumn_ && !upperColumn_) { lowerColumn[i] = 0.0; upperColumn[i] = COIN_DBL_MAX; } else { if (lowerColumn_) lowerColumn[i] = lowerColumn_[jColumn]; else lowerColumn[i] = 0.0; if (upperColumn_) upperColumn[i] = upperColumn_[jColumn]; else upperColumn[i] = COIN_DBL_MAX; } if (model->nonLinearCost()) model->nonLinearCost()->setOne(i, solution[i], lowerColumn[i], upperColumn[i], cost_[jColumn]); } if (!model->numberIterations() && rhsOffset_) { lastRefresh_ = - refreshFrequency_; // force refresh } } break; // and get statistics for column generation case 4: { // In theory we should subtract out ones we have done but .... // If key slack then dual 0.0 // If not then slack could be dual infeasible // dj for key is zero so that defines dual on set int i; int numberColumns = model->numberColumns(); double * dual = model->dualRowSolution(); double infeasibilityCost = model->infeasibilityCost(); double dualTolerance = model->dualTolerance(); double relaxedTolerance = dualTolerance; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, model->largestDualError()); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; // but we will be using difference relaxedTolerance -= dualTolerance; double objectiveOffset = 0.0; for (i = 0; i < numberSets_; i++) { int kColumn = keyVariable_[i]; double value = 0.0; if (kColumn < numberColumns) { kColumn = id_[kColumn-firstDynamic_]; // dj without set value = cost_[kColumn]; for (CoinBigIndex j = startColumn_[kColumn]; j < startColumn_[kColumn+1]; j++) { int iRow = row_[j]; value -= dual[iRow] * element_[j]; } double infeasibility = 0.0; if (getStatus(i) == ClpSimplex::atLowerBound) { if (-value > dualTolerance) infeasibility = -value - dualTolerance; } else if (getStatus(i) == ClpSimplex::atUpperBound) { if (value > dualTolerance) infeasibility = value - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } else { // slack key - may not be feasible assert (getStatus(i) == ClpSimplex::basic); // negative as -1.0 for slack value = -weight(i) * infeasibilityCost; } // Now subtract out from all for (CoinBigIndex k = fullStart_[i]; k < fullStart_[i+1]; k++) { if (getDynamicStatus(k) != inSmall) { double djValue = cost_[k] - value; for (CoinBigIndex j = startColumn_[k]; j < startColumn_[k+1]; j++) { int iRow = row_[j]; djValue -= dual[iRow] * element_[j]; } double infeasibility = 0.0; double shift = 0.0; if (getDynamicStatus(k) == atLowerBound) { if (lowerColumn_) shift = lowerColumn_[k]; if (djValue < -dualTolerance) infeasibility = -djValue - dualTolerance; } else { // at upper bound shift = upperColumn_[k]; if (djValue > dualTolerance) infeasibility = djValue - dualTolerance; } objectiveOffset += shift * cost_[k]; if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } } } model->setObjectiveOffset(objectiveOffset_ - objectiveOffset); } break; // see if time to re-factorize case 5: { if (firstAvailable_ > numberSets_ + model->numberRows() + model->factorizationFrequency()) returnNumber = 4; } break; // return 1 if there may be changing bounds on variable (column generation) case 6: { returnNumber = (lowerColumn_ != NULL || upperColumn_ != NULL) ? 1 : 0; #if 0 if (!returnNumber) { // may be gub slacks for (int i = 0; i < numberSets_; i++) { if (upper_[i] > lower_[i]) { returnNumber = 1; break; } } } #endif } break; // restore firstAvailable_ case 7: { int iColumn; int * length = matrix_->getMutableVectorLengths(); double * cost = model->costRegion(); double * solution = model->solutionRegion(); int currentNumber = firstAvailable_; firstAvailable_ = savedFirstAvailable_; // zero solution CoinZeroN(solution + firstAvailable_, currentNumber - firstAvailable_); // zero cost CoinZeroN(cost + firstAvailable_, currentNumber - firstAvailable_); // zero lengths CoinZeroN(length + firstAvailable_, currentNumber - firstAvailable_); for ( iColumn = firstAvailable_; iColumn < currentNumber; iColumn++) { model->nonLinearCost()->setOne(iColumn, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(iColumn, ClpSimplex::atLowerBound); backward_[iColumn] = -1; } } break; // make sure set is clean case 8: { int sequenceIn = model->sequenceIn(); if (sequenceIn < model->numberColumns()) { int iSet = backward_[sequenceIn]; if (iSet >= 0 && lowerSet_) { // we only need to get lower_ and upper_ correct double shift = 0.0; for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) if (getDynamicStatus(j) == atUpperBound) shift += upperColumn_[j]; else if (getDynamicStatus(j) == atLowerBound && lowerColumn_) shift += lowerColumn_[j]; if (lowerSet_[iSet] > -1.0e20) lower_[iSet] = lowerSet_[iSet] - shift; if (upperSet_[iSet] < 1.0e20) upper_[iSet] = upperSet_[iSet] - shift; } if (sequenceIn == firstAvailable_) { // not really in small problem int iBig = id_[sequenceIn-firstDynamic_]; if (model->getStatus(sequenceIn) == ClpSimplex::atLowerBound) setDynamicStatus(iBig, atLowerBound); else setDynamicStatus(iBig, atUpperBound); } } } break; // adjust lower,upper case 9: { int sequenceIn = model->sequenceIn(); if (sequenceIn >= firstDynamic_ && sequenceIn < lastDynamic_ && lowerSet_) { int iSet = backward_[sequenceIn]; assert (iSet >= 0); int inBig = id_[sequenceIn-firstDynamic_]; const double * solution = model->solutionRegion(); setDynamicStatus(inBig, inSmall); if (lowerSet_[iSet] > -1.0e20) lower_[iSet] += solution[sequenceIn]; if (upperSet_[iSet] < 1.0e20) upper_[iSet] += solution[sequenceIn]; model->setObjectiveOffset(model->objectiveOffset() - solution[sequenceIn]*cost_[inBig]); } } } return returnNumber; } // Add a new variable to a set void ClpGubDynamicMatrix::insertNonBasic(int sequence, int iSet) { int last = keyVariable_[iSet]; int j = next_[last]; while (j >= 0) { last = j; j = next_[j]; } next_[last] = -(sequence + 1); next_[sequence] = j; } // Sets up an effective RHS and does gub crash if needed void ClpGubDynamicMatrix::useEffectiveRhs(ClpSimplex * model, bool cheapest) { // Do basis - cheapest or slack if feasible (unless cheapest set) int longestSet = 0; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) longestSet = CoinMax(longestSet, fullStart_[iSet+1] - fullStart_[iSet]); double * upper = new double[longestSet+1]; double * cost = new double[longestSet+1]; double * lower = new double[longestSet+1]; double * solution = new double[longestSet+1]; assert (!next_); delete [] next_; int numberColumns = model->numberColumns(); next_ = new int[numberColumns+numberSets_+CoinMax(2*longestSet, lastDynamic_-firstDynamic_)]; char * mark = new char[numberColumns]; memset(mark, 0, numberColumns); for (int iColumn = 0; iColumn < numberColumns; iColumn++) next_[iColumn] = COIN_INT_MAX; int i; int * keys = new int[numberSets_]; int * back = new int[numberGubColumns_]; CoinFillN(back, numberGubColumns_, -1); for (i = 0; i < numberSets_; i++) keys[i] = COIN_INT_MAX; delete [] dynamicStatus_; dynamicStatus_ = new unsigned char [numberGubColumns_]; memset(dynamicStatus_, 0, numberGubColumns_); // for clarity for (i = 0; i < numberGubColumns_; i++) setDynamicStatus(i, atLowerBound); // set up chains for (i = firstDynamic_; i < lastDynamic_; i++) { if (id_[i-firstDynamic_] >= 0) { if (model->getStatus(i) == ClpSimplex::basic) mark[i] = 1; int iSet = backward_[i]; assert (iSet >= 0); int iNext = keys[iSet]; next_[i] = iNext; keys[iSet] = i; back[id_[i-firstDynamic_]] = i; } else { model->setStatus(i, ClpSimplex::atLowerBound); backward_[i] = -1; } } double * columnSolution = model->solutionRegion(); int numberRows = getNumRows(); toIndex_ = new int[numberSets_]; for (iSet = 0; iSet < numberSets_; iSet++) toIndex_[iSet] = -1; fromIndex_ = new int [numberRows+numberSets_]; double tolerance = model->primalTolerance(); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double objectiveOffset = 0.0; for (iSet = 0; iSet < numberSets_; iSet++) { int j; int numberBasic = 0; int iBasic = -1; int iStart = fullStart_[iSet]; int iEnd = fullStart_[iSet+1]; // find one with smallest length int smallest = numberRows + 1; double value = 0.0; j = keys[iSet]; while (j != COIN_INT_MAX) { if (model->getStatus(j) == ClpSimplex::basic) { if (length[j] < smallest) { smallest = length[j]; iBasic = j; } numberBasic++; } value += columnSolution[j]; j = next_[j]; } bool done = false; if (numberBasic > 1 || (numberBasic == 1 && getStatus(iSet) == ClpSimplex::basic)) { if (getStatus(iSet) == ClpSimplex::basic) iBasic = iSet + numberColumns; // slack key - use done = true; } else if (numberBasic == 1) { // see if can be key double thisSolution = columnSolution[iBasic]; if (thisSolution < 0.0) { value -= thisSolution; thisSolution = 0.0; columnSolution[iBasic] = thisSolution; } // try setting slack to a bound assert (upper_[iSet] < 1.0e20 || lower_[iSet] > -1.0e20); double cost1 = COIN_DBL_MAX; int whichBound = -1; if (upper_[iSet] < 1.0e20) { // try slack at ub double newBasic = thisSolution + upper_[iSet] - value; if (newBasic >= -tolerance) { // can go whichBound = 1; cost1 = newBasic * cost_[iBasic]; // But if exact then may be good solution if (fabs(upper_[iSet] - value) < tolerance) cost1 = -COIN_DBL_MAX; } } if (lower_[iSet] > -1.0e20) { // try slack at lb double newBasic = thisSolution + lower_[iSet] - value; if (newBasic >= -tolerance) { // can go but is it cheaper double cost2 = newBasic * cost_[iBasic]; // But if exact then may be good solution if (fabs(lower_[iSet] - value) < tolerance) cost2 = -COIN_DBL_MAX; if (cost2 < cost1) whichBound = 0; } } if (whichBound != -1) { // key done = true; if (whichBound) { // slack to upper columnSolution[iBasic] = thisSolution + upper_[iSet] - value; setStatus(iSet, ClpSimplex::atUpperBound); } else { // slack to lower columnSolution[iBasic] = thisSolution + lower_[iSet] - value; setStatus(iSet, ClpSimplex::atLowerBound); } } } if (!done) { if (!cheapest) { // see if slack can be key if (value >= lower_[iSet] - tolerance && value <= upper_[iSet] + tolerance) { done = true; setStatus(iSet, ClpSimplex::basic); iBasic = iSet + numberColumns; } } if (!done) { // set non basic if there was one if (iBasic >= 0) model->setStatus(iBasic, ClpSimplex::atLowerBound); // find cheapest int numberInSet = iEnd - iStart; if (!lowerColumn_) { CoinZeroN(lower, numberInSet); } else { for (int j = 0; j < numberInSet; j++) lower[j] = lowerColumn_[j+iStart]; } if (!upperColumn_) { CoinFillN(upper, numberInSet, COIN_DBL_MAX); } else { for (int j = 0; j < numberInSet; j++) upper[j] = upperColumn_[j+iStart]; } CoinFillN(solution, numberInSet, 0.0); // and slack iBasic = numberInSet; solution[iBasic] = -value; lower[iBasic] = -upper_[iSet]; upper[iBasic] = -lower_[iSet]; int kphase; if (value >= lower_[iSet] - tolerance && value <= upper_[iSet] + tolerance) { // feasible kphase = 1; cost[iBasic] = 0.0; for (int j = 0; j < numberInSet; j++) cost[j] = cost_[j+iStart]; } else { // infeasible kphase = 0; // remember bounds are flipped so opposite to natural if (value < lower_[iSet] - tolerance) cost[iBasic] = 1.0; else cost[iBasic] = -1.0; CoinZeroN(cost, numberInSet); } double dualTolerance = model->dualTolerance(); for (int iphase = kphase; iphase < 2; iphase++) { if (iphase) { cost[numberInSet] = 0.0; for (int j = 0; j < numberInSet; j++) cost[j] = cost_[j+iStart]; } // now do one row lp bool improve = true; while (improve) { improve = false; double dual = cost[iBasic]; int chosen = -1; double best = dualTolerance; int way = 0; for (int i = 0; i <= numberInSet; i++) { double dj = cost[i] - dual; double improvement = 0.0; if (iphase || i < numberInSet) assert (solution[i] >= lower[i] && solution[i] <= upper[i]); if (dj > dualTolerance) improvement = dj * (solution[i] - lower[i]); else if (dj < -dualTolerance) improvement = dj * (solution[i] - upper[i]); if (improvement > best) { best = improvement; chosen = i; if (dj < 0.0) { way = 1; } else { way = -1; } } } if (chosen >= 0) { improve = true; // now see how far if (way > 0) { // incoming increasing so basic decreasing // if phase 0 then go to nearest bound double distance = upper[chosen] - solution[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] > upper[iBasic]); basicDistance = solution[iBasic] - upper[iBasic]; } else { basicDistance = solution[iBasic] - lower[iBasic]; } // need extra coding for unbounded assert (CoinMin(distance, basicDistance) < 1.0e20); if (distance > basicDistance) { // incoming becomes basic solution[chosen] += basicDistance; if (!iphase) solution[iBasic] = upper[iBasic]; else solution[iBasic] = lower[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = upper[chosen]; solution[iBasic] -= distance; } } else { // incoming decreasing so basic increasing // if phase 0 then go to nearest bound double distance = solution[chosen] - lower[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] < lower[iBasic]); basicDistance = lower[iBasic] - solution[iBasic]; } else { basicDistance = upper[iBasic] - solution[iBasic]; } // need extra coding for unbounded - for now just exit if (CoinMin(distance, basicDistance) > 1.0e20) { printf("unbounded on set %d\n", iSet); iphase = 1; iBasic = numberInSet; break; } if (distance > basicDistance) { // incoming becomes basic solution[chosen] -= basicDistance; if (!iphase) solution[iBasic] = lower[iBasic]; else solution[iBasic] = upper[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = lower[chosen]; solution[iBasic] += distance; } } if (!iphase) { if(iBasic < numberInSet) break; // feasible else if (solution[iBasic] >= lower[iBasic] && solution[iBasic] <= upper[iBasic]) break; // feasible (on flip) } } } } // do solution i.e. bounds if (lowerColumn_ || upperColumn_) { for (int j = 0; j < numberInSet; j++) { if (j != iBasic) { objectiveOffset += solution[j] * cost[j]; if (lowerColumn_ && upperColumn_) { if (fabs(solution[j] - lowerColumn_[j+iStart]) > fabs(solution[j] - upperColumn_[j+iStart])) setDynamicStatus(j + iStart, atUpperBound); } else if (upperColumn_ && solution[j] > 0.0) { setDynamicStatus(j + iStart, atUpperBound); } else { setDynamicStatus(j + iStart, atLowerBound); } } } } // convert iBasic back and do bounds if (iBasic == numberInSet) { // slack basic setStatus(iSet, ClpSimplex::basic); iBasic = iSet + numberColumns; } else { iBasic += fullStart_[iSet]; if (back[iBasic] >= 0) { // exists iBasic = back[iBasic]; } else { // create CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[iBasic+1] - startColumn_[iBasic]; if (numberElements + numberThis > numberElements_) { // need to redo numberElements_ = CoinMax(3 * numberElements_ / 2, numberElements + numberThis); matrix_->reserve(numberColumns, numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } length[firstAvailable_] = numberThis; model->costRegion()[firstAvailable_] = cost_[iBasic]; if (lowerColumn_) model->lowerRegion()[firstAvailable_] = lowerColumn_[iBasic]; else model->lowerRegion()[firstAvailable_] = 0.0; if (upperColumn_) model->upperRegion()[firstAvailable_] = upperColumn_[iBasic]; else model->upperRegion()[firstAvailable_] = COIN_DBL_MAX; columnSolution[firstAvailable_] = solution[iBasic-fullStart_[iSet]]; CoinBigIndex base = startColumn_[iBasic]; for (int j = 0; j < numberThis; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } // already set startColumn[firstAvailable_]=numberElements; id_[firstAvailable_-firstDynamic_] = iBasic; setDynamicStatus(iBasic, inSmall); backward_[firstAvailable_] = iSet; iBasic = firstAvailable_; firstAvailable_++; startColumn[firstAvailable_] = numberElements; } model->setStatus(iBasic, ClpSimplex::basic); // remember bounds flipped if (upper[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::isFixed); else if (solution[numberInSet] == upper[numberInSet]) setStatus(iSet, ClpSimplex::atLowerBound); else if (solution[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::atUpperBound); else abort(); } for (j = iStart; j < iEnd; j++) { int iBack = back[j]; if (iBack >= 0) { if (model->getStatus(iBack) != ClpSimplex::basic) { int inSet = j - iStart; columnSolution[iBack] = solution[inSet]; if (upper[inSet] == lower[inSet]) model->setStatus(iBack, ClpSimplex::isFixed); else if (solution[inSet] == upper[inSet]) model->setStatus(iBack, ClpSimplex::atUpperBound); else if (solution[inSet] == lower[inSet]) model->setStatus(iBack, ClpSimplex::atLowerBound); } } } } } keyVariable_[iSet] = iBasic; } model->setObjectiveOffset(objectiveOffset_ - objectiveOffset); delete [] lower; delete [] solution; delete [] upper; delete [] cost; // make sure matrix is in good shape matrix_->orderMatrix(); // create effective rhs delete [] rhsOffset_; rhsOffset_ = new double[numberRows]; // and redo chains memset(mark, 0, numberColumns); for (int iColumnX = 0; iColumnX < firstAvailable_; iColumnX++) next_[iColumnX] = COIN_INT_MAX; for (i = 0; i < numberSets_; i++) { keys[i] = COIN_INT_MAX; int iKey = keyVariable_[i]; if (iKey < numberColumns) model->setStatus(iKey, ClpSimplex::basic); } // set up chains for (i = 0; i < firstAvailable_; i++) { if (model->getStatus(i) == ClpSimplex::basic) mark[i] = 1; int iSet = backward_[i]; if (iSet >= 0) { int iNext = keys[iSet]; next_[i] = iNext; keys[iSet] = i; } } for (i = 0; i < numberSets_; i++) { if (keys[i] != COIN_INT_MAX) { // something in set int j; if (getStatus(i) != ClpSimplex::basic) { // make sure fixed if it is if (upper_[i] == lower_[i]) setStatus(i, ClpSimplex::isFixed); // slack not key - choose one with smallest length int smallest = numberRows + 1; int key = -1; j = keys[i]; while (1) { if (mark[j] && length[j] < smallest) { key = j; smallest = length[j]; } if (next_[j] != COIN_INT_MAX) { j = next_[j]; } else { // correct end next_[j] = -(keys[i] + 1); break; } } if (key >= 0) { keyVariable_[i] = key; } else { // nothing basic - make slack key //((ClpGubMatrix *)this)->setStatus(i,ClpSimplex::basic); // fudge to avoid const problem status_[i] = 1; } } else { // slack key keyVariable_[i] = numberColumns + i; int j; double sol = 0.0; j = keys[i]; while (1) { sol += columnSolution[j]; if (next_[j] != COIN_INT_MAX) { j = next_[j]; } else { // correct end next_[j] = -(keys[i] + 1); break; } } if (sol > upper_[i] + tolerance) { setAbove(i); } else if (sol < lower_[i] - tolerance) { setBelow(i); } else { setFeasible(i); } } // Create next_ int key = keyVariable_[i]; redoSet(model, key, keys[i], i); } else { // nothing in set! next_[i+numberColumns] = -(i + numberColumns + 1); keyVariable_[i] = numberColumns + i; double sol = 0.0; if (sol > upper_[i] + tolerance) { setAbove(i); } else if (sol < lower_[i] - tolerance) { setBelow(i); } else { setFeasible(i); } } } delete [] keys; delete [] mark; delete [] back; rhsOffset(model, true); } /* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpGubDynamicMatrix::rhsOffset(ClpSimplex * model, bool forceRefresh, bool #ifdef CLP_DEBUG check #endif ) { //forceRefresh=true; //check=false; #ifdef CLP_DEBUG double * saveE = NULL; if (rhsOffset_ && check) { int numberRows = model->numberRows(); saveE = new double[numberRows]; } #endif if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway int numberRows = model->numberRows(); double * rhs = new double[numberRows]; int numberColumns = model->numberColumns(); int iRow; CoinZeroN(rhs, numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; for (iColumn = 0; iColumn < firstDynamic_; iColumn++) { if (model->getStatus(iColumn) != ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; rhs[jRow] -= value * element[j]; } } } if (lowerColumn_ || upperColumn_) { double * solution = new double [numberGubColumns_]; for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = 0.0; if(getDynamicStatus(iColumn) == atUpperBound) value = upperColumn_[iColumn]; else if (lowerColumn_) value = lowerColumn_[iColumn]; solution[iColumn] = value; } // ones at bounds in small and gub for (iColumn = firstDynamic_; iColumn < firstAvailable_; iColumn++) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull] = smallSolution[iColumn]; } // zero all basic in small model int * pivotVariable = model->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iColumn = pivotVariable[iRow]; if (iColumn >= firstDynamic_ && iColumn < lastDynamic_) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = 0.0; } } // and now compute value to use for key ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = 0.0; double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lowerSet_[iSet]; else b = upperSet_[iSet]; // subtract out others at bounds for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) b -= solution[j]; solution[iSequence] = b; } } for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = solution[iColumn]; if (value) { for (CoinBigIndex j = startColumn_[iColumn]; j < startColumn_[iColumn+1]; j++) { int iRow = row_[j]; rhs[iRow] -= element_[j] * value; } } } // now do lower and upper bounds on sets for (int iSet = 0; iSet < numberSets_; iSet++) { iColumn = keyVariable_[iSet]; double shift = 0.0; for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) { if (getDynamicStatus(j) != inSmall && j != iColumn) { if (getDynamicStatus(j) == atLowerBound) { if (lowerColumn_) shift += lowerColumn_[j]; } else { shift += upperColumn_[j]; } } } if (lowerSet_[iSet] > -1.0e20) assert(fabs(lower_[iSet] - (lowerSet_[iSet] - shift)) < 1.0e-3); if (upperSet_[iSet] < 1.0e20) assert(fabs(upper_[iSet] - ( upperSet_[iSet] - shift)) < 1.0e-3); } delete [] solution; } else { // no bounds ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { int iSequence = id_[iColumn-firstDynamic_]; double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lower_[iSet]; else b = upper_[iSet]; if (b) { for (CoinBigIndex j = startColumn_[iSequence]; j < startColumn_[iSequence+1]; j++) { int iRow = row_[j]; rhs[iRow] -= element_[j] * b; } } } } } for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** bad effective %d - true %g old %g\n", iRow, rhs[iRow], rhsOffset_[iRow]); } CoinMemcpyN(rhs, numberRows, saveE); delete [] rhs; } #endif if (forceRefresh || (refreshFrequency_ && model->numberIterations() >= lastRefresh_ + refreshFrequency_)) { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int iRow; CoinZeroN(rhsOffset_, numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; for (iColumn = 0; iColumn < firstDynamic_; iColumn++) { if (model->getStatus(iColumn) != ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; rhsOffset_[jRow] -= value * element[j]; } } } if (lowerColumn_ || upperColumn_) { double * solution = new double [numberGubColumns_]; for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = 0.0; if(getDynamicStatus(iColumn) == atUpperBound) value = upperColumn_[iColumn]; else if (lowerColumn_) value = lowerColumn_[iColumn]; solution[iColumn] = value; } // ones in gub and in small problem for (iColumn = firstDynamic_; iColumn < firstAvailable_; iColumn++) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull] = smallSolution[iColumn]; } // zero all basic in small model int * pivotVariable = model->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iColumn = pivotVariable[iRow]; if (iColumn >= firstDynamic_ && iColumn < lastDynamic_) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = 0.0; } } // and now compute value to use for key ClpSimplex::Status iStatus; int iSet; for ( iSet = 0; iSet < numberSets_; iSet++) { iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = 0.0; double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lowerSet_[iSet]; else b = upperSet_[iSet]; // subtract out others at bounds for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) b -= solution[j]; solution[iSequence] = b; } } for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = solution[iColumn]; if (value) { for (CoinBigIndex j = startColumn_[iColumn]; j < startColumn_[iColumn+1]; j++) { int iRow = row_[j]; rhsOffset_[iRow] -= element_[j] * value; } } } // now do lower and upper bounds on sets // and offset double objectiveOffset = 0.0; for ( iSet = 0; iSet < numberSets_; iSet++) { iColumn = keyVariable_[iSet]; double shift = 0.0; for (CoinBigIndex j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) { if (getDynamicStatus(j) != inSmall) { double value = 0.0; if (getDynamicStatus(j) == atLowerBound) { if (lowerColumn_) value = lowerColumn_[j]; } else { value = upperColumn_[j]; } if (j != iColumn) shift += value; objectiveOffset += value * cost_[j]; } } if (lowerSet_[iSet] > -1.0e20) lower_[iSet] = lowerSet_[iSet] - shift; if (upperSet_[iSet] < 1.0e20) upper_[iSet] = upperSet_[iSet] - shift; } delete [] solution; model->setObjectiveOffset(objectiveOffset_ - objectiveOffset); } else { // no bounds ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { int iSequence = id_[iColumn-firstDynamic_]; double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lower_[iSet]; else b = upper_[iSet]; if (b) { for (CoinBigIndex j = startColumn_[iSequence]; j < startColumn_[iSequence+1]; j++) { int iRow = row_[j]; rhsOffset_[iRow] -= element_[j] * b; } } } } } #ifdef CLP_DEBUG if (saveE) { for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(saveE[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** %d - old eff %g new %g\n", iRow, saveE[iRow], rhsOffset_[iRow]); } delete [] saveE; } #endif lastRefresh_ = model->numberIterations(); } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpGubDynamicMatrix::updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue) { // now update working model int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); bool doPrinting = (model->messageHandler()->logLevel() == 63); bool print = false; int iSet; int trueIn = -1; int trueOut = -1; int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); if (sequenceIn == firstAvailable_) { if (doPrinting) printf("New variable "); if (sequenceIn != sequenceOut) { insertNonBasic(firstAvailable_, backward_[firstAvailable_]); setDynamicStatus(id_[sequenceIn-firstDynamic_], inSmall); firstAvailable_++; } else { int bigSequence = id_[sequenceIn-firstDynamic_]; if (model->getStatus(sequenceIn) == ClpSimplex::atUpperBound) setDynamicStatus(bigSequence, atUpperBound); else setDynamicStatus(bigSequence, atLowerBound); } synchronize(model, 8); } if (sequenceIn < lastDynamic_) { iSet = backward_[sequenceIn]; if (iSet >= 0) { int bigSequence = id_[sequenceIn-firstDynamic_]; trueIn = bigSequence + numberRows + numberColumns + numberSets_; if (doPrinting) printf(" incoming set %d big seq %d", iSet, bigSequence); print = true; } } else if (sequenceIn >= numberRows + numberColumns) { trueIn = numberRows + numberColumns + gubSlackIn_; } if (sequenceOut < lastDynamic_) { iSet = backward_[sequenceOut]; if (iSet >= 0) { int bigSequence = id_[sequenceOut-firstDynamic_]; trueOut = bigSequence + firstDynamic_; if (getDynamicStatus(bigSequence) != inSmall) { if (model->getStatus(sequenceOut) == ClpSimplex::atUpperBound) setDynamicStatus(bigSequence, atUpperBound); else setDynamicStatus(bigSequence, atLowerBound); } if (doPrinting) printf(" ,outgoing set %d big seq %d,", iSet, bigSequence); print = true; model->setSequenceIn(sequenceOut); synchronize(model, 8); model->setSequenceIn(sequenceIn); } } if (print && doPrinting) printf("\n"); ClpGubMatrix::updatePivot(model, oldInValue, oldOutValue); // Redo true in and out if (trueIn >= 0) trueSequenceIn_ = trueIn; if (trueOut >= 0) trueSequenceOut_ = trueOut; if (doPrinting && 0) { for (int i = 0; i < numberSets_; i++) { printf("set %d key %d lower %g upper %g\n", i, keyVariable_[i], lower_[i], upper_[i]); for (int j = fullStart_[i]; j < fullStart_[i+1]; j++) if (getDynamicStatus(j) == atUpperBound) { bool print = true; for (int k = firstDynamic_; k < firstAvailable_; k++) { if (id_[k-firstDynamic_] == j) print = false; if (id_[k-firstDynamic_] == j) assert(getDynamicStatus(j) == inSmall); } if (print) printf("variable %d at ub\n", j); } } } #ifdef CLP_DEBUG char * inSmall = new char [numberGubColumns_]; memset(inSmall, 0, numberGubColumns_); for (int i = 0; i < numberGubColumns_; i++) if (getDynamicStatus(i) == ClpGubDynamicMatrix::inSmall) inSmall[i] = 1; for (int i = firstDynamic_; i < firstAvailable_; i++) { int k = id_[i-firstDynamic_]; inSmall[k] = 0; } for (int i = 0; i < numberGubColumns_; i++) assert (!inSmall[i]); delete [] inSmall; #endif return 0; } void ClpGubDynamicMatrix::times(double scalar, const double * x, double * y) const { if (model_->specialOptions() != 16) { ClpPackedMatrix::times(scalar, x, y); } else { int iRow; int numberColumns = model_->numberColumns(); int numberRows = model_->numberRows(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int * pivotVariable = model_->pivotVariable(); int numberToDo = 0; for (iRow = 0; iRow < numberRows; iRow++) { y[iRow] -= scalar * rhsOffset_[iRow]; int iColumn = pivotVariable[iRow]; if (iColumn < numberColumns) { int iSet = backward_[iColumn]; if (iSet >= 0 && toIndex_[iSet] < 0) { toIndex_[iSet] = 0; fromIndex_[numberToDo++] = iSet; } CoinBigIndex j; double value = scalar * x[iColumn]; if (value) { for (j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; y[jRow] += value * element[j]; } } } } // and gubs which are interacting for (int jSet = 0; jSet < numberToDo; jSet++) { int iSet = fromIndex_[jSet]; toIndex_[iSet] = -1; int iKey = keyVariable_[iSet]; if (iKey < numberColumns) { double valueKey; if (getStatus(iSet) == ClpSimplex::atLowerBound) valueKey = lower_[iSet]; else valueKey = upper_[iSet]; double value = scalar * (x[iKey] - valueKey); if (value) { for (CoinBigIndex j = startColumn[iKey]; j < startColumn[iKey] + length[iKey]; j++) { int jRow = row[j]; y[jRow] += value * element[j]; } } } } } } /* Just for debug - may be extended to other matrix types later. Returns number and sum of primal infeasibilities. */ int ClpGubDynamicMatrix::checkFeasible(ClpSimplex * /*model*/, double & sum) const { int numberRows = model_->numberRows(); double * rhs = new double[numberRows]; int numberColumns = model_->numberColumns(); int iRow; CoinZeroN(rhs, numberRows); // do ones at bounds before gub const double * smallSolution = model_->solutionRegion(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; int numberInfeasible = 0; const double * rowLower = model_->rowLower(); const double * rowUpper = model_->rowUpper(); sum = 0.0; for (iRow = 0; iRow < numberRows; iRow++) { double value = smallSolution[numberColumns+iRow]; if (value < rowLower[iRow] - 1.0e-5 || value > rowUpper[iRow] + 1.0e-5) { //printf("row %d %g %g %g\n", // iRow,rowLower[iRow],value,rowUpper[iRow]); numberInfeasible++; sum += CoinMax(rowLower[iRow] - value, value - rowUpper[iRow]); } rhs[iRow] = value; } const double * columnLower = model_->columnLower(); const double * columnUpper = model_->columnUpper(); for (iColumn = 0; iColumn < firstDynamic_; iColumn++) { double value = smallSolution[iColumn]; if (value < columnLower[iColumn] - 1.0e-5 || value > columnUpper[iColumn] + 1.0e-5) { //printf("column %d %g %g %g\n", // iColumn,columnLower[iColumn],value,columnUpper[iColumn]); numberInfeasible++; sum += CoinMax(columnLower[iColumn] - value, value - columnUpper[iColumn]); } for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; rhs[jRow] -= value * element[j]; } } double * solution = new double [numberGubColumns_]; for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = 0.0; if(getDynamicStatus(iColumn) == atUpperBound) value = upperColumn_[iColumn]; else if (lowerColumn_) value = lowerColumn_[iColumn]; solution[iColumn] = value; } // ones in small and gub for (iColumn = firstDynamic_; iColumn < firstAvailable_; iColumn++) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull] = smallSolution[iColumn]; } // fill in all basic in small model int * pivotVariable = model_->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iColumn = pivotVariable[iRow]; if (iColumn >= firstDynamic_ && iColumn < lastDynamic_) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = smallSolution[iColumn]; } } // and now compute value to use for key ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { int iSequence = id_[iColumn-firstDynamic_]; solution[iSequence] = 0.0; double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lower_[iSet]; else b = upper_[iSet]; // subtract out others at bounds for (int j = fullStart_[iSet]; j < fullStart_[iSet+1]; j++) b -= solution[j]; solution[iSequence] = b; } } for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) { double value = solution[iColumn]; if ((lowerColumn_ && value < lowerColumn_[iColumn] - 1.0e-5) || (!lowerColumn_ && value < -1.0e-5) || (upperColumn_ && value > upperColumn_[iColumn] + 1.0e-5)) { //printf("column %d %g %g %g\n", // iColumn,lowerColumn_[iColumn],value,upperColumn_[iColumn]); numberInfeasible++; } if (value) { for (CoinBigIndex j = startColumn_[iColumn]; j < startColumn_[iColumn+1]; j++) { int iRow = row_[j]; rhs[iRow] -= element_[j] * value; } } } for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow]) > 1.0e-5) printf("rhs mismatch %d %g\n", iRow, rhs[iRow]); } delete [] solution; delete [] rhs; return numberInfeasible; } // Cleans data after setWarmStart void ClpGubDynamicMatrix::cleanData(ClpSimplex * model) { // and redo chains int numberColumns = model->numberColumns(); int iColumn; // do backward int * mark = new int [numberGubColumns_]; for (iColumn = 0; iColumn < numberGubColumns_; iColumn++) mark[iColumn] = -1; int i; for (i = 0; i < firstDynamic_; i++) { assert (backward_[i] == -1); next_[i] = -1; } for (i = firstDynamic_; i < firstAvailable_; i++) { iColumn = id_[i-firstDynamic_]; mark[iColumn] = i; } for (i = 0; i < numberSets_; i++) { int iKey = keyVariable_[i]; int lastNext = -1; int firstNext = -1; for (CoinBigIndex k = fullStart_[i]; k < fullStart_[i+1]; k++) { iColumn = mark[k]; if (iColumn >= 0) { if (iColumn != iKey) { if (lastNext >= 0) next_[lastNext] = iColumn; else firstNext = iColumn; lastNext = iColumn; } backward_[iColumn] = i; } } setFeasible(i); if (firstNext >= 0) { // others next_[iKey] = firstNext; next_[lastNext] = -(iKey + 1); } else if (iKey < numberColumns) { next_[iKey] = -(iKey + 1); } } delete [] mark; // fill matrix double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstDynamic_]; for (i = firstDynamic_; i < firstAvailable_; i++) { int iColumn = id_[i-firstDynamic_]; int numberThis = startColumn_[iColumn+1] - startColumn_[iColumn]; length[i] = numberThis; for (CoinBigIndex jBigIndex = startColumn_[iColumn]; jBigIndex < startColumn_[iColumn+1]; jBigIndex++) { row[numberElements] = row_[jBigIndex]; element[numberElements++] = element_[jBigIndex]; } startColumn[i+1] = numberElements; } } Clp-1.15.10/src/Clp_C_Interface.cpp0000644000076600007660000011525612272740164015325 0ustar coincoin// $Id: Clp_C_Interface.cpp 2020 2014-01-31 15:25:40Z 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). #include "CoinPragma.hpp" #include #include #include "CoinHelperFunctions.hpp" #include "ClpConfig.h" #include "ClpSimplex.hpp" #include "ClpInterior.hpp" #ifndef SLIM_CLP #include "Idiot.hpp" #endif #include // Get C stuff but with extern C #define CLP_EXTERN_C #include "Coin_C_defines.h" /// To allow call backs class CMessageHandler : public CoinMessageHandler { public: /**@name Overrides */ //@{ virtual int print(); //@} /**@name set and get */ //@{ /// Model const Clp_Simplex * model() const; void setModel(Clp_Simplex * model); /// Call back void setCallBack(clp_callback callback); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ CMessageHandler(); /// Constructor with pointer to model CMessageHandler(Clp_Simplex * model, FILE * userPointer = NULL); /** Destructor */ virtual ~CMessageHandler(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ CMessageHandler(const CMessageHandler&); /** The copy constructor from an CoinSimplexMessageHandler. */ CMessageHandler(const CoinMessageHandler&); CMessageHandler& operator=(const CMessageHandler&); /// Clone virtual CoinMessageHandler * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer back to model Clp_Simplex * model_; /// call back clp_callback callback_; //@} }; //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CMessageHandler::CMessageHandler () : CoinMessageHandler(), model_(NULL), callback_(NULL) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CMessageHandler::CMessageHandler (const CMessageHandler & rhs) : CoinMessageHandler(rhs), model_(rhs.model_), callback_(rhs.callback_) { } CMessageHandler::CMessageHandler (const CoinMessageHandler & rhs) : CoinMessageHandler(rhs), model_(NULL), callback_(NULL) { } // Constructor with pointer to model CMessageHandler::CMessageHandler(Clp_Simplex * model, FILE * ) : CoinMessageHandler(), model_(model), callback_(NULL) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CMessageHandler::~CMessageHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CMessageHandler & CMessageHandler::operator=(const CMessageHandler& rhs) { if (this != &rhs) { CoinMessageHandler::operator=(rhs); model_ = rhs.model_; callback_ = rhs.callback_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CoinMessageHandler * CMessageHandler::clone() const { return new CMessageHandler(*this); } int CMessageHandler::print() { if (callback_) { int messageNumber = currentMessage().externalNumber(); if (currentSource() != "Clp") messageNumber += 1000000; int i; int nDouble = numberDoubleFields(); assert (nDouble <= 10); double vDouble[10]; for (i = 0; i < nDouble; i++) vDouble[i] = doubleValue(i); int nInt = numberIntFields(); assert (nInt <= 10); int vInt[10]; for (i = 0; i < nInt; i++) vInt[i] = intValue(i); int nString = numberStringFields(); assert (nString <= 10); char * vString[10]; 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(); } const Clp_Simplex * CMessageHandler::model() const { return model_; } void CMessageHandler::setModel(Clp_Simplex * model) { model_ = model; } // Call back void CMessageHandler::setCallBack(clp_callback callback) { callback_ = callback; } #include "Clp_C_Interface.h" #include #include #include #if defined(__MWERKS__) #pragma export on #endif COINLIBAPI const char* COINLINKAGE Clp_Version(void) { return CLP_VERSION; } COINLIBAPI int COINLINKAGE Clp_VersionMajor(void) { return CLP_VERSION_MAJOR; } COINLIBAPI int COINLINKAGE Clp_VersionMinor(void) { return CLP_VERSION_MINOR; } COINLIBAPI int COINLINKAGE Clp_VersionRelease(void) { return CLP_VERSION_RELEASE; } /* Default constructor */ COINLIBAPI Clp_Simplex * COINLINKAGE Clp_newModel() { Clp_Simplex * model = new Clp_Simplex; model->model_ = new ClpSimplex(); model->handler_ = NULL; return model; } /* Destructor */ COINLIBAPI void COINLINKAGE Clp_deleteModel(Clp_Simplex * model) { delete model->model_; delete model->handler_; delete model; } /* 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 Clp_loadProblem (Clp_Simplex * 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[] = "Clp_c_Interface::Clp_loadProblem(): "; const int verbose = 0; 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, reinterpret_cast(model), reinterpret_cast(start), reinterpret_cast(index), reinterpret_cast(value)); printf("%s collb = %p, colub = %p, obj = %p, rowlb = %p, rowub = %p\n", prefix, reinterpret_cast(collb), reinterpret_cast(colub), reinterpret_cast(obj), reinterpret_cast(rowlb), reinterpret_cast(rowub)); } model->model_->loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); } /* read quadratic part of the objective (the matrix part) */ COINLIBAPI void COINLINKAGE Clp_loadQuadraticObjective(Clp_Simplex * model, const int numberColumns, const CoinBigIndex * start, const int * column, const double * element) { model->model_->loadQuadraticObjective(numberColumns, start, column, element); } /* Read an mps file from the given filename */ COINLIBAPI int COINLINKAGE Clp_readMps(Clp_Simplex * model, const char *filename, int keepNames, int ignoreErrors) { return model->model_->readMps(filename, keepNames != 0, ignoreErrors != 0); } /* Copy in integer informations */ COINLIBAPI void COINLINKAGE Clp_copyInIntegerInformation(Clp_Simplex * model, const char * information) { model->model_->copyInIntegerInformation(information); } /* Drop integer informations */ COINLIBAPI void COINLINKAGE Clp_deleteIntegerInformation(Clp_Simplex * model) { model->model_->deleteIntegerInformation(); } /* Resizes rim part of model */ COINLIBAPI void COINLINKAGE Clp_resize (Clp_Simplex * model, int newNumberRows, int newNumberColumns) { model->model_->resize(newNumberRows, newNumberColumns); } /* Deletes rows */ COINLIBAPI void COINLINKAGE Clp_deleteRows(Clp_Simplex * model, int number, const int * which) { model->model_->deleteRows(number, which); } /* Add rows */ COINLIBAPI void COINLINKAGE Clp_addRows(Clp_Simplex * model, int number, const double * rowLower, const double * rowUpper, const int * rowStarts, const int * columns, const double * elements) { model->model_->addRows(number, rowLower, rowUpper, rowStarts, columns, elements); } /* Deletes columns */ COINLIBAPI void COINLINKAGE Clp_deleteColumns(Clp_Simplex * model, int number, const int * which) { model->model_->deleteColumns(number, which); } /* Add columns */ COINLIBAPI void COINLINKAGE Clp_addColumns(Clp_Simplex * model, int number, const double * columnLower, const double * columnUpper, const double * objective, const int * columnStarts, const int * rows, const double * elements) { model->model_->addColumns(number, columnLower, columnUpper, objective, columnStarts, rows, elements); } /* Change row lower bounds */ COINLIBAPI void COINLINKAGE Clp_chgRowLower(Clp_Simplex * model, const double * rowLower) { model->model_->chgRowLower(rowLower); } /* Change row upper bounds */ COINLIBAPI void COINLINKAGE Clp_chgRowUpper(Clp_Simplex * model, const double * rowUpper) { model->model_->chgRowUpper(rowUpper); } /* Change column lower bounds */ COINLIBAPI void COINLINKAGE Clp_chgColumnLower(Clp_Simplex * model, const double * columnLower) { model->model_->chgColumnLower(columnLower); } /* Change column upper bounds */ COINLIBAPI void COINLINKAGE Clp_chgColumnUpper(Clp_Simplex * model, const double * columnUpper) { model->model_->chgColumnUpper(columnUpper); } /* Change objective coefficients */ COINLIBAPI void COINLINKAGE Clp_chgObjCoefficients(Clp_Simplex * model, const double * objIn) { model->model_->chgObjCoefficients(objIn); } /* Drops names - makes lengthnames 0 and names empty */ COINLIBAPI void COINLINKAGE Clp_dropNames(Clp_Simplex * model) { model->model_->dropNames(); } /* Copies in names */ COINLIBAPI void COINLINKAGE Clp_copyNames(Clp_Simplex * model, const char * const * rowNamesIn, const char * const * columnNamesIn) { int iRow; std::vector rowNames; int numberRows = model->model_->numberRows(); rowNames.reserve(numberRows); for (iRow = 0; iRow < numberRows; iRow++) { rowNames.push_back(rowNamesIn[iRow]); } int iColumn; std::vector columnNames; int numberColumns = model->model_->numberColumns(); columnNames.reserve(numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnNames.push_back(columnNamesIn[iColumn]); } model->model_->copyNames(rowNames, columnNames); } /* Number of rows */ COINLIBAPI int COINLINKAGE Clp_numberRows(Clp_Simplex * model) { return model->model_->numberRows(); } /* Number of columns */ COINLIBAPI int COINLINKAGE Clp_numberColumns(Clp_Simplex * model) { return model->model_->numberColumns(); } /* Primal tolerance to use */ COINLIBAPI double COINLINKAGE Clp_primalTolerance(Clp_Simplex * model) { return model->model_->primalTolerance(); } COINLIBAPI void COINLINKAGE Clp_setPrimalTolerance(Clp_Simplex * model, double value) { model->model_->setPrimalTolerance(value); } /* Dual tolerance to use */ COINLIBAPI double COINLINKAGE Clp_dualTolerance(Clp_Simplex * model) { return model->model_->dualTolerance(); } COINLIBAPI void COINLINKAGE Clp_setDualTolerance(Clp_Simplex * model, double value) { model->model_->setDualTolerance(value); } /* Dual objective limit */ COINLIBAPI double COINLINKAGE Clp_dualObjectiveLimit(Clp_Simplex * model) { return model->model_->dualObjectiveLimit(); } COINLIBAPI void COINLINKAGE Clp_setDualObjectiveLimit(Clp_Simplex * model, double value) { model->model_->setDualObjectiveLimit(value); } /* Objective offset */ COINLIBAPI double COINLINKAGE Clp_objectiveOffset(Clp_Simplex * model) { return model->model_->objectiveOffset(); } COINLIBAPI void COINLINKAGE Clp_setObjectiveOffset(Clp_Simplex * model, double value) { model->model_->setObjectiveOffset(value); } /* Fills in array with problem name */ COINLIBAPI void COINLINKAGE Clp_problemName(Clp_Simplex * model, int maxNumberCharacters, char * array) { std::string name = model->model_->problemName(); maxNumberCharacters = CoinMin(maxNumberCharacters, ((int) strlen(name.c_str()))+1) ; strncpy(array, name.c_str(), maxNumberCharacters - 1); array[maxNumberCharacters-1] = '\0'; } /* Sets problem name. Must have \0 at end. */ COINLIBAPI int COINLINKAGE Clp_setProblemName(Clp_Simplex * model, int /*maxNumberCharacters*/, char * array) { return model->model_->setStrParam(ClpProbName, array); } /* Number of iterations */ COINLIBAPI int COINLINKAGE Clp_numberIterations(Clp_Simplex * model) { return model->model_->numberIterations(); } COINLIBAPI void COINLINKAGE Clp_setNumberIterations(Clp_Simplex * model, int numberIterations) { model->model_->setNumberIterations(numberIterations); } /* Maximum number of iterations */ COINLIBAPI int maximumIterations(Clp_Simplex * model) { return model->model_->maximumIterations(); } COINLIBAPI void COINLINKAGE Clp_setMaximumIterations(Clp_Simplex * model, int value) { model->model_->setMaximumIterations(value); } /* Maximum time in seconds (from when set called) */ COINLIBAPI double COINLINKAGE Clp_maximumSeconds(Clp_Simplex * model) { return model->model_->maximumSeconds(); } COINLIBAPI void COINLINKAGE Clp_setMaximumSeconds(Clp_Simplex * model, double value) { model->model_->setMaximumSeconds(value); } /* Returns true if hit maximum iteratio`ns (or time) */ COINLIBAPI int COINLINKAGE Clp_hitMaximumIterations(Clp_Simplex * model) { return model->model_->hitMaximumIterations() ? 1 : 0; } /* Status of problem: 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations etc 4 - stopped due to errors */ COINLIBAPI int COINLINKAGE Clp_status(Clp_Simplex * model) { return model->model_->status(); } /* Set problem status */ COINLIBAPI void COINLINKAGE Clp_setProblemStatus(Clp_Simplex * model, int problemStatus) { model->model_->setProblemStatus(problemStatus); } /* Secondary status of problem - may get extended 0 - none 1 - primal infeasible because dual limit reached 2 - scaled problem optimal - unscaled has primal infeasibilities 3 - scaled problem optimal - unscaled has dual infeasibilities 4 - scaled problem optimal - unscaled has both dual and primal infeasibilities */ COINLIBAPI int COINLINKAGE Clp_secondaryStatus(Clp_Simplex * model) { return model->model_->secondaryStatus(); } COINLIBAPI void COINLINKAGE Clp_setSecondaryStatus(Clp_Simplex * model, int status) { model->model_->setSecondaryStatus(status); } /* Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI double COINLINKAGE Clp_optimizationDirection(Clp_Simplex * model) { return model->model_->optimizationDirection(); } COINLIBAPI void COINLINKAGE Clp_setOptimizationDirection(Clp_Simplex * model, double value) { model->model_->setOptimizationDirection(value); } /* Primal row solution */ COINLIBAPI double * COINLINKAGE Clp_primalRowSolution(Clp_Simplex * model) { return model->model_->primalRowSolution(); } /* Primal column solution */ COINLIBAPI double * COINLINKAGE Clp_primalColumnSolution(Clp_Simplex * model) { return model->model_->primalColumnSolution(); } /* Dual row solution */ COINLIBAPI double * COINLINKAGE Clp_dualRowSolution(Clp_Simplex * model) { return model->model_->dualRowSolution(); } /* Reduced costs */ COINLIBAPI double * COINLINKAGE Clp_dualColumnSolution(Clp_Simplex * model) { return model->model_->dualColumnSolution(); } /* Row lower */ COINLIBAPI double* COINLINKAGE Clp_rowLower(Clp_Simplex * model) { return model->model_->rowLower(); } /* Row upper */ COINLIBAPI double* COINLINKAGE Clp_rowUpper(Clp_Simplex * model) { return model->model_->rowUpper(); } /* Objective */ COINLIBAPI double * COINLINKAGE Clp_objective(Clp_Simplex * model) { return model->model_->objective(); } /* Column Lower */ COINLIBAPI double * COINLINKAGE Clp_columnLower(Clp_Simplex * model) { return model->model_->columnLower(); } /* Column Upper */ COINLIBAPI double * COINLINKAGE Clp_columnUpper(Clp_Simplex * model) { return model->model_->columnUpper(); } /* Number of elements in matrix */ COINLIBAPI int COINLINKAGE Clp_getNumElements(Clp_Simplex * model) { return model->model_->getNumElements(); } // Column starts in matrix COINLIBAPI const CoinBigIndex * COINLINKAGE Clp_getVectorStarts(Clp_Simplex * model) { CoinPackedMatrix * matrix; matrix = model->model_->matrix(); return (matrix == NULL) ? NULL : matrix->getVectorStarts(); } // Row indices in matrix COINLIBAPI const int * COINLINKAGE Clp_getIndices(Clp_Simplex * model) { CoinPackedMatrix * matrix = model->model_->matrix(); return (matrix == NULL) ? NULL : matrix->getIndices(); } // Column vector lengths in matrix COINLIBAPI const int * COINLINKAGE Clp_getVectorLengths(Clp_Simplex * model) { CoinPackedMatrix * matrix = model->model_->matrix(); return (matrix == NULL) ? NULL : matrix->getVectorLengths(); } // Element values in matrix COINLIBAPI const double * COINLINKAGE Clp_getElements(Clp_Simplex * model) { CoinPackedMatrix * matrix = model->model_->matrix(); return (matrix == NULL) ? NULL : matrix->getElements(); } /* Objective value */ COINLIBAPI double COINLINKAGE Clp_objectiveValue(Clp_Simplex * model) { return model->model_->objectiveValue(); } /* Integer information */ COINLIBAPI char * COINLINKAGE Clp_integerInformation(Clp_Simplex * model) { return model->model_->integerInformation(); } /* Infeasibility/unbounded ray (NULL returned if none/wrong) Up to user to use free() on these arrays. */ COINLIBAPI double * COINLINKAGE Clp_infeasibilityRay(Clp_Simplex * model) { const double * ray = model->model_->internalRay(); double * array = NULL; int numberRows = model->model_->numberRows(); int status = model->model_->status(); if (status == 1 && ray) { array = static_cast(malloc(numberRows*sizeof(double))); memcpy(array,ray,numberRows*sizeof(double)); #ifdef PRINT_RAY_METHOD printf("Infeasibility ray obtained by algorithm %s\n",model->model_->algorithm()>0 ? "primal" : "dual"); #endif } return array; } COINLIBAPI double * COINLINKAGE Clp_unboundedRay(Clp_Simplex * model) { const double * ray = model->model_->internalRay(); double * array = NULL; int numberColumns = model->model_->numberColumns(); int status = model->model_->status(); if (status == 2 && ray) { array = static_cast(malloc(numberColumns*sizeof(double))); memcpy(array,ray,numberColumns*sizeof(double)); } return array; } COINLIBAPI void COINLINKAGE Clp_freeRay(Clp_Simplex * model, double * ray) { free(ray); } /* See if status array exists (partly for OsiClp) */ COINLIBAPI int COINLINKAGE Clp_statusExists(Clp_Simplex * model) { return model->model_->statusExists() ? 1 : 0; } /* Return address of status array (char[numberRows+numberColumns]) */ COINLIBAPI unsigned char * COINLINKAGE Clp_statusArray(Clp_Simplex * model) { return model->model_->statusArray(); } /* Copy in status vector */ COINLIBAPI void COINLINKAGE Clp_copyinStatus(Clp_Simplex * model, const unsigned char * statusArray) { model->model_->copyinStatus(statusArray); } /* User pointer for whatever reason */ COINLIBAPI void COINLINKAGE Clp_setUserPointer (Clp_Simplex * model, void * pointer) { model->model_->setUserPointer(pointer); } COINLIBAPI void * COINLINKAGE Clp_getUserPointer (Clp_Simplex * model) { return model->model_->getUserPointer(); } /* Pass in Callback function */ COINLIBAPI void COINLINKAGE Clp_registerCallBack(Clp_Simplex * model, clp_callback userCallBack) { // Will be copy of users one delete model->handler_; model->handler_ = new CMessageHandler(*(model->model_->messageHandler())); model->handler_->setCallBack(userCallBack); model->handler_->setModel(model); model->model_->passInMessageHandler(model->handler_); } /* Unset Callback function */ COINLIBAPI void COINLINKAGE Clp_clearCallBack(Clp_Simplex * model) { delete model->handler_; model->handler_ = NULL; } /* 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 */ COINLIBAPI void COINLINKAGE Clp_setLogLevel(Clp_Simplex * model, int value) { model->model_->setLogLevel(value); } COINLIBAPI int COINLINKAGE Clp_logLevel(Clp_Simplex * model) { return model->model_->logLevel(); } /* length of names (0 means no names0 */ COINLIBAPI int COINLINKAGE Clp_lengthNames(Clp_Simplex * model) { return model->model_->lengthNames(); } /* Fill in array (at least lengthNames+1 long) with a row name */ COINLIBAPI void COINLINKAGE Clp_rowName(Clp_Simplex * model, int iRow, char * name) { std::string rowName = model->model_->rowName(iRow); strcpy(name, rowName.c_str()); } /* Fill in array (at least lengthNames+1 long) with a column name */ COINLIBAPI void COINLINKAGE Clp_columnName(Clp_Simplex * model, int iColumn, char * name) { std::string columnName = model->model_->columnName(iColumn); strcpy(name, columnName.c_str()); } /* General solve algorithm which can do presolve. See ClpSolve.hpp for options */ COINLIBAPI int COINLINKAGE Clp_initialSolve(Clp_Simplex * model) { return model->model_->initialSolve(); } /* Pass solve options. (Exception to direct analogue rule) */ COINLIBAPI int COINLINKAGE Clp_initialSolveWithOptions(Clp_Simplex * model, Clp_Solve * s) { return model->model_->initialSolve(s->options); } /* Barrier initial solve */ COINLIBAPI int COINLINKAGE Clp_initialBarrierSolve(Clp_Simplex * model0) { ClpSimplex *model = model0->model_; return model->initialBarrierSolve(); } /* Barrier initial solve */ COINLIBAPI int COINLINKAGE Clp_initialBarrierNoCrossSolve(Clp_Simplex * model0) { ClpSimplex *model = model0->model_; return model->initialBarrierNoCrossSolve(); } /* Dual initial solve */ COINLIBAPI int COINLINKAGE Clp_initialDualSolve(Clp_Simplex * model) { return model->model_->initialDualSolve(); } /* Primal initial solve */ COINLIBAPI int COINLINKAGE Clp_initialPrimalSolve(Clp_Simplex * model) { return model->model_->initialPrimalSolve(); } /* Dual algorithm - see ClpSimplexDual.hpp for method */ COINLIBAPI int COINLINKAGE Clp_dual(Clp_Simplex * model, int ifValuesPass) { return model->model_->dual(ifValuesPass); } /* Primal algorithm - see ClpSimplexPrimal.hpp for method */ COINLIBAPI int COINLINKAGE Clp_primal(Clp_Simplex * model, int ifValuesPass) { return model->model_->primal(ifValuesPass); } /* Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ COINLIBAPI void COINLINKAGE Clp_scaling(Clp_Simplex * model, int mode) { model->model_->scaling(mode); } /* Gets scalingFlag */ COINLIBAPI int COINLINKAGE Clp_scalingFlag(Clp_Simplex * model) { return model->model_->scalingFlag(); } /* Crash - at present just aimed at dual, returns -2 if dual preferred and crash basis created -1 if dual preferred and all slack basis preferred 0 if basis going in was not all slack 1 if primal preferred and all slack basis preferred 2 if primal preferred and crash basis created. if gap between bounds <="gap" variables can be flipped If "pivot" is 0 No pivoting (so will just be choice of algorithm) 1 Simple pivoting e.g. gub 2 Mini iterations */ COINLIBAPI int COINLINKAGE Clp_crash(Clp_Simplex * model, double gap, int pivot) { return model->model_->crash(gap, pivot); } /* If problem is primal feasible */ COINLIBAPI int COINLINKAGE Clp_primalFeasible(Clp_Simplex * model) { return model->model_->primalFeasible() ? 1 : 0; } /* If problem is dual feasible */ COINLIBAPI int COINLINKAGE Clp_dualFeasible(Clp_Simplex * model) { return model->model_->dualFeasible() ? 1 : 0; } /* Dual bound */ COINLIBAPI double COINLINKAGE Clp_dualBound(Clp_Simplex * model) { return model->model_->dualBound(); } COINLIBAPI void COINLINKAGE Clp_setDualBound(Clp_Simplex * model, double value) { model->model_->setDualBound(value); } /* Infeasibility cost */ COINLIBAPI double COINLINKAGE Clp_infeasibilityCost(Clp_Simplex * model) { return model->model_->infeasibilityCost(); } COINLIBAPI void COINLINKAGE Clp_setInfeasibilityCost(Clp_Simplex * model, double value) { model->model_->setInfeasibilityCost(value); } /* Perturbation: 50 - switch on perturbation 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 others are for playing */ COINLIBAPI int COINLINKAGE Clp_perturbation(Clp_Simplex * model) { return model->model_->perturbation(); } COINLIBAPI void COINLINKAGE Clp_setPerturbation(Clp_Simplex * model, int value) { model->model_->setPerturbation(value); } /* Current (or last) algorithm */ COINLIBAPI int COINLINKAGE Clp_algorithm(Clp_Simplex * model) { return model->model_->algorithm(); } /* Set algorithm */ COINLIBAPI void COINLINKAGE Clp_setAlgorithm(Clp_Simplex * model, int value) { model->model_->setAlgorithm(value); } /* Sum of dual infeasibilities */ COINLIBAPI double COINLINKAGE Clp_sumDualInfeasibilities(Clp_Simplex * model) { return model->model_->sumDualInfeasibilities(); } /* Number of dual infeasibilities */ COINLIBAPI int COINLINKAGE Clp_numberDualInfeasibilities(Clp_Simplex * model) { return model->model_->numberDualInfeasibilities(); } /* Sum of primal infeasibilities */ COINLIBAPI double COINLINKAGE Clp_sumPrimalInfeasibilities(Clp_Simplex * model) { return model->model_->sumPrimalInfeasibilities(); } /* Number of primal infeasibilities */ COINLIBAPI int COINLINKAGE Clp_numberPrimalInfeasibilities(Clp_Simplex * model) { return model->model_->numberPrimalInfeasibilities(); } /* Save model to file, returns 0 if success. This is designed for use outside algorithms so does not save iterating arrays etc. It does not save any messaging information. Does not save scaling values. It does not know about all types of virtual functions. */ COINLIBAPI int COINLINKAGE Clp_saveModel(Clp_Simplex * model, const char * fileName) { return model->model_->saveModel(fileName); } /* Restore model from file, returns 0 if success, deletes current model */ COINLIBAPI int COINLINKAGE Clp_restoreModel(Clp_Simplex * model, const char * fileName) { return model->model_->restoreModel(fileName); } /* Just check solution (for external use) - sets sum of infeasibilities etc */ COINLIBAPI void COINLINKAGE Clp_checkSolution(Clp_Simplex * model) { model->model_->checkSolution(); } /* Number of rows */ COINLIBAPI int COINLINKAGE Clp_getNumRows(Clp_Simplex * model) { return model->model_->getNumRows(); } /* Number of columns */ COINLIBAPI int COINLINKAGE Clp_getNumCols(Clp_Simplex * model) { return model->model_->getNumCols(); } /* Number of iterations */ COINLIBAPI int COINLINKAGE Clp_getIterationCount(Clp_Simplex * model) { return model->model_->getIterationCount(); } /* Are there a numerical difficulties? */ COINLIBAPI int COINLINKAGE Clp_isAbandoned(Clp_Simplex * model) { return model->model_->isAbandoned() ? 1 : 0; } /* Is optimality proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenOptimal(Clp_Simplex * model) { return model->model_->isProvenOptimal() ? 1 : 0; } /* Is primal infeasiblity proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenPrimalInfeasible(Clp_Simplex * model) { return model->model_->isProvenPrimalInfeasible() ? 1 : 0; } /* Is dual infeasiblity proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenDualInfeasible(Clp_Simplex * model) { return model->model_->isProvenDualInfeasible() ? 1 : 0; } /* Is the given primal objective limit reached? */ COINLIBAPI int COINLINKAGE Clp_isPrimalObjectiveLimitReached(Clp_Simplex * model) { return model->model_->isPrimalObjectiveLimitReached() ? 1 : 0; } /* Is the given dual objective limit reached? */ COINLIBAPI int COINLINKAGE Clp_isDualObjectiveLimitReached(Clp_Simplex * model) { return model->model_->isDualObjectiveLimitReached() ? 1 : 0; } /* Iteration limit reached? */ COINLIBAPI int COINLINKAGE Clp_isIterationLimitReached(Clp_Simplex * model) { return model->model_->isIterationLimitReached() ? 1 : 0; } /* Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI double COINLINKAGE Clp_getObjSense(Clp_Simplex * model) { return model->model_->getObjSense(); } /* Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI void COINLINKAGE Clp_setObjSense(Clp_Simplex * model, double objsen) { model->model_->setOptimizationDirection(objsen); } /* Primal row solution */ COINLIBAPI const double * COINLINKAGE Clp_getRowActivity(Clp_Simplex * model) { return model->model_->getRowActivity(); } /* Primal column solution */ COINLIBAPI const double * COINLINKAGE Clp_getColSolution(Clp_Simplex * model) { return model->model_->getColSolution(); } COINLIBAPI void COINLINKAGE Clp_setColSolution(Clp_Simplex * model, const double * input) { model->model_->setColSolution(input); } /* Dual row solution */ COINLIBAPI const double * COINLINKAGE Clp_getRowPrice(Clp_Simplex * model) { return model->model_->getRowPrice(); } /* Reduced costs */ COINLIBAPI const double * COINLINKAGE Clp_getReducedCost(Clp_Simplex * model) { return model->model_->getReducedCost(); } /* Row lower */ COINLIBAPI const double* COINLINKAGE Clp_getRowLower(Clp_Simplex * model) { return model->model_->getRowLower(); } /* Row upper */ COINLIBAPI const double* COINLINKAGE Clp_getRowUpper(Clp_Simplex * model) { return model->model_->getRowUpper(); } /* Objective */ COINLIBAPI const double * COINLINKAGE Clp_getObjCoefficients(Clp_Simplex * model) { return model->model_->getObjCoefficients(); } /* Column Lower */ COINLIBAPI const double * COINLINKAGE Clp_getColLower(Clp_Simplex * model) { return model->model_->getColLower(); } /* Column Upper */ COINLIBAPI const double * COINLINKAGE Clp_getColUpper(Clp_Simplex * model) { return model->model_->getColUpper(); } /* Objective value */ COINLIBAPI double COINLINKAGE Clp_getObjValue(Clp_Simplex * model) { return model->model_->getObjValue(); } /* Get variable basis info */ COINLIBAPI int COINLINKAGE Clp_getColumnStatus(Clp_Simplex * model, int sequence) { return (int) model->model_->getColumnStatus(sequence); } /* Get row basis info */ COINLIBAPI int COINLINKAGE Clp_getRowStatus(Clp_Simplex * model, int sequence) { return (int) model->model_->getRowStatus(sequence); } /* Set variable basis info */ COINLIBAPI void COINLINKAGE Clp_setColumnStatus(Clp_Simplex * model, int sequence, int value) { if (value >= 0 && value <= 5) { model->model_->setColumnStatus(sequence, (ClpSimplex::Status) value ); if (value == 3 || value == 5) model->model_->primalColumnSolution()[sequence] = model->model_->columnLower()[sequence]; else if (value == 2) model->model_->primalColumnSolution()[sequence] = model->model_->columnUpper()[sequence]; } } /* Set row basis info */ COINLIBAPI void COINLINKAGE Clp_setRowStatus(Clp_Simplex * model, int sequence, int value) { if (value >= 0 && value <= 5) { model->model_->setRowStatus(sequence, (ClpSimplex::Status) value ); if (value == 3 || value == 5) model->model_->primalRowSolution()[sequence] = model->model_->rowLower()[sequence]; else if (value == 2) model->model_->primalRowSolution()[sequence] = model->model_->rowUpper()[sequence]; } } /* Small element value - elements less than this set to zero, default is 1.0e-20 */ COINLIBAPI double COINLINKAGE Clp_getSmallElementValue(Clp_Simplex * model) { return model->model_->getSmallElementValue(); } COINLIBAPI void COINLINKAGE Clp_setSmallElementValue(Clp_Simplex * model, double value) { model->model_->setSmallElementValue(value); } /* Print model */ COINLIBAPI void COINLINKAGE Clp_printModel(Clp_Simplex * model, const char * prefix) { ClpSimplex *clp_simplex = model->model_; int numrows = clp_simplex->numberRows(); int numcols = clp_simplex->numberColumns(); int numelem = clp_simplex->getNumElements(); const CoinBigIndex *start = clp_simplex->matrix()->getVectorStarts(); const int *index = clp_simplex->matrix()->getIndices(); const double *value = clp_simplex->matrix()->getElements(); const double *collb = model->model_->columnLower(); const double *colub = model->model_->columnUpper(); const double *obj = model->model_->objective(); const double *rowlb = model->model_->rowLower(); const double *rowub = model->model_->rowUpper(); printf("%s numcols = %i, numrows = %i, numelem = %i\n", prefix, numcols, numrows, numelem); printf("%s model = %p, start = %p, index = %p, value = %p\n", prefix, reinterpret_cast(model), reinterpret_cast(start), reinterpret_cast(index), reinterpret_cast(value)); clp_simplex->matrix()->dumpMatrix(NULL); { int i; for (i = 0; i <= numcols; i++) printf("%s start[%i] = %i\n", prefix, i, start[i]); for (i = 0; i < numelem; i++) printf("%s index[%i] = %i, value[%i] = %g\n", prefix, i, index[i], i, value[i]); } printf("%s collb = %p, colub = %p, obj = %p, rowlb = %p, rowub = %p\n", prefix, reinterpret_cast(collb), reinterpret_cast(colub), reinterpret_cast(obj), reinterpret_cast(rowlb), reinterpret_cast(rowub)); printf("%s optimization direction = %g\n", prefix, Clp_optimizationDirection(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", prefix, i, collb[i], i, colub[i], i, obj[i]); for (i = 0; i < numrows; i++) printf("%s rowlb[%i] = %g, rowub[%i] = %g\n", prefix, i, rowlb[i], i, rowub[i]); } } #ifndef SLIM_CLP /** Solve the problem with the idiot code */ /* tryhard values: tryhard & 7: 0: NOT lightweight, 105 iterations within a pass (when mu stays fixed) 1: lightweight, but focus more on optimality (mu is high) (23 iters in a pass) 2: lightweight, but focus more on feasibility (11 iters in a pass) 3: lightweight, but focus more on feasibility (23 iters in a pass, so it goes closer to opt than option 2) tryhard >> 3: number of passes, the larger the number the closer it gets to optimality */ COINLIBAPI void COINLINKAGE Clp_idiot(Clp_Simplex * model, int tryhard) { ClpSimplex *clp = model->model_; Idiot info(*clp); int numberpass = tryhard >> 3; int lightweight = tryhard & 7; info.setLightweight(lightweight); info.crash(numberpass, clp->messageHandler(), clp->messagesPointer(), false); } #endif COINLIBAPI Clp_Solve * COINLINKAGE ClpSolve_new() { return new Clp_Solve(); } COINLIBAPI void COINLINKAGE ClpSolve_delete(Clp_Solve * solve) { delete solve; } // space- and error-saving macros #define ClpSolveGetIntProperty(prop) \ COINLIBAPI int COINLINKAGE \ ClpSolve_ ## prop (Clp_Solve *s) \ { \ return s->options.prop(); \ } #define ClpSolveSetIntProperty(prop) \ COINLIBAPI void COINLINKAGE \ ClpSolve_ ## prop (Clp_Solve *s, int val) \ { \ s->options.prop(val); \ } COINLIBAPI void COINLINKAGE ClpSolve_setSpecialOption(Clp_Solve * s, int which, int value, int extraInfo) { s->options.setSpecialOption(which,value,extraInfo); } COINLIBAPI int COINLINKAGE ClpSolve_getSpecialOption(Clp_Solve * s, int which) { return s->options.getSpecialOption(which); } COINLIBAPI void COINLINKAGE ClpSolve_setSolveType(Clp_Solve * s, int method, int extraInfo) { s->options.setSolveType(static_cast(method), extraInfo); } ClpSolveGetIntProperty(getSolveType) COINLIBAPI void COINLINKAGE ClpSolve_setPresolveType(Clp_Solve * s, int amount, int extraInfo) { s->options.setPresolveType(static_cast(amount),extraInfo); } ClpSolveGetIntProperty(getPresolveType) ClpSolveGetIntProperty(getPresolvePasses) COINLIBAPI int COINLINKAGE ClpSolve_getExtraInfo(Clp_Solve * s, int which) { return s->options.getExtraInfo(which); } ClpSolveSetIntProperty(setInfeasibleReturn) ClpSolveGetIntProperty(infeasibleReturn) ClpSolveGetIntProperty(doDual) ClpSolveSetIntProperty(setDoDual) ClpSolveGetIntProperty(doSingleton) ClpSolveSetIntProperty(setDoSingleton) ClpSolveGetIntProperty(doDoubleton) ClpSolveSetIntProperty(setDoDoubleton) ClpSolveGetIntProperty(doTripleton) ClpSolveSetIntProperty(setDoTripleton) ClpSolveGetIntProperty(doTighten) ClpSolveSetIntProperty(setDoTighten) ClpSolveGetIntProperty(doForcing) ClpSolveSetIntProperty(setDoForcing) ClpSolveGetIntProperty(doImpliedFree) ClpSolveSetIntProperty(setDoImpliedFree) ClpSolveGetIntProperty(doDupcol) ClpSolveSetIntProperty(setDoDupcol) ClpSolveGetIntProperty(doDuprow) ClpSolveSetIntProperty(setDoDuprow) ClpSolveGetIntProperty(doSingletonColumn) ClpSolveSetIntProperty(setDoSingletonColumn) ClpSolveGetIntProperty(presolveActions) ClpSolveSetIntProperty(setPresolveActions) ClpSolveGetIntProperty(substitution) ClpSolveSetIntProperty(setSubstitution) #if defined(__MWERKS__) #pragma export off #endif Clp-1.15.10/src/ClpParameters.hpp0000644000076600007660000001112212372677302015123 0ustar coincoin/* $Id: ClpParameters.hpp 2045 2014-08-13 15:05:38Z tkr $ */ // Copyright (C) 2000, 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef _ClpParameters_H #define _ClpParameters_H /** This is where to put any useful stuff. */ enum ClpIntParam { /** The maximum number of iterations Clp can execute in the simplex methods */ ClpMaxNumIteration = 0, /** The maximum number of iterations Clp can execute in hotstart before terminating */ ClpMaxNumIterationHotStart, /** The name discipline; specifies how the solver will handle row and column names. - 0: Auto names: Names cannot be set by the client. Names of the form Rnnnnnnn or Cnnnnnnn are generated on demand when a name for a specific row or column is requested; nnnnnnn is derived from the row or column index. Requests for a vector of names return a vector with zero entries. - 1: Lazy names: Names supplied by the client are retained. Names of the form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been supplied by the client. Requests for a vector of names return a vector sized to the largest index of a name supplied by the client; some entries in the vector may be null strings. - 2: Full names: Names supplied by the client are retained. Names of the form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been supplied by the client. Requests for a vector of names return a vector sized to match the constraint system, and all entries will contain either the name specified by the client or a generated name. */ ClpNameDiscipline, /** Just a marker, so that we can allocate a static sized array to store parameters. */ ClpLastIntParam }; enum ClpDblParam { /** Set Dual objective limit. This is to be used as a termination criteria in methods where the dual objective monotonically changes (dual simplex). */ ClpDualObjectiveLimit, /** Primal objective limit. This is to be used as a termination criteria in methods where the primal objective monotonically changes (e.g., primal simplex) */ ClpPrimalObjectiveLimit, /** The maximum amount the dual constraints can be violated and still be considered feasible. */ ClpDualTolerance, /** The maximum amount the primal constraints can be violated and still be considered feasible. */ ClpPrimalTolerance, /** Objective function constant. This the value of the constant term in the objective function. */ ClpObjOffset, /// Maximum time in seconds - after, this action is as max iterations ClpMaxSeconds, /// Maximum wallclock running time in seconds - after, this action is as max iterations ClpMaxWallSeconds, /// Tolerance to use in presolve ClpPresolveTolerance, /** Just a marker, so that we can allocate a static sized array to store parameters. */ ClpLastDblParam }; enum ClpStrParam { /** Name of the problem. This is the found on the Name card of an mps file. */ ClpProbName = 0, /** Just a marker, so that we can allocate a static sized array to store parameters. */ ClpLastStrParam }; /// Copy (I don't like complexity of Coin version) template inline void ClpDisjointCopyN( const T * array, const int size, T * newArray) { memcpy(reinterpret_cast (newArray), array, size * sizeof(T)); } /// And set template inline void ClpFillN( T * array, const int size, T value) { int i; for (i = 0; i < size; i++) array[i] = value; } /// This returns a non const array filled with input from scalar or actual array template inline T* ClpCopyOfArray( const T * array, const int size, T value) { T * arrayNew = new T[size]; if (array) ClpDisjointCopyN(array, size, arrayNew); else ClpFillN ( arrayNew, size, value); return arrayNew; } /// This returns a non const array filled with actual array (or NULL) template inline T* ClpCopyOfArray( const T * array, const int size) { if (array) { T * arrayNew = new T[size]; ClpDisjointCopyN(array, size, arrayNew); return arrayNew; } else { return NULL; } } /// For a structure to be used by trusted code typedef struct { int typeStruct; // allocated as 1,2 etc int typeCall; void * data; } ClpTrustedData; #endif Clp-1.15.10/src/ClpNetworkMatrix.hpp0000644000076600007660000002312411510657452015640 0ustar coincoin/* $Id: ClpNetworkMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpNetworkMatrix_H #define ClpNetworkMatrix_H #include "CoinPragma.hpp" #include "ClpMatrixBase.hpp" /** This implements a simple network matrix as derived from ClpMatrixBase. If you want more sophisticated version then you could inherit from this. Also you might want to allow networks with gain */ class ClpNetworkMatrix : public ClpMatrixBase { public: /**@name Useful methods */ //@{ /// Return a complete CoinPackedMatrix virtual CoinPackedMatrix * getPackedMatrix() const; /** Whether the packed matrix is column major ordered or not. */ virtual bool isColOrdered() const { return true; } /** Number of entries in the packed matrix. */ virtual CoinBigIndex getNumElements() const { return 2 * numberColumns_; } /** Number of columns. */ virtual int getNumCols() const { return numberColumns_; } /** Number of rows. */ virtual int getNumRows() const { return numberRows_; } /** A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const double * getElements() const; /** A vector containing the minor indices of the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const int * getIndices() const { return indices_; } virtual const CoinBigIndex * getVectorStarts() const; /** The lengths of the major-dimension vectors. */ virtual const int * getVectorLengths() const; /** Delete the columns whose indices are listed in indDel. */ virtual void deleteCols(const int numDel, const int * indDel); /** Delete the rows whose indices are listed in indDel. */ virtual void deleteRows(const int numDel, const int * indDel); /// Append Columns virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); /// Append Rows virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); #ifndef SLIM_CLP /** Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ virtual int appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther = -1); #endif /** Returns a new matrix in reverse order without gaps */ virtual ClpMatrixBase * reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis( const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element); /** Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; /** Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ virtual void rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const ; /** Unpacks a column into an CoinIndexedvector ** in packed format Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const ; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const; /// Allow any parts of a created CoinMatrix to be deleted virtual void releasePackedMatrix() const ; /// Says whether it can do partial pricing virtual bool canDoPartialPricing() const; /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); //@} /**@name Matrix times vector methods */ //@{ /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /// And for scaling virtual void times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ virtual void transposeTimes(double scalar, const double * x, double * y) const; /// And for scaling virtual void transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale, double * spare = NULL) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x *A in z but just for indices in y. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const; //@} /**@name Other */ //@{ /// Return true if really network, false if has slacks inline bool trueNetwork() const { return trueNetwork_; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpNetworkMatrix(); /** Constructor from two arrays */ ClpNetworkMatrix(int numberColumns, const int * head, const int * tail); /** Destructor */ virtual ~ClpNetworkMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpNetworkMatrix(const ClpNetworkMatrix&); /** The copy constructor from an CoinNetworkMatrix. */ ClpNetworkMatrix(const CoinPackedMatrix&); ClpNetworkMatrix& operator=(const ClpNetworkMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpNetworkMatrix (const ClpNetworkMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); /** Subset clone (without gaps). Duplicates are allowed and order is as given */ virtual ClpMatrixBase * subsetClone ( int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// For fake CoinPackedMatrix mutable CoinPackedMatrix * matrix_; mutable int * lengths_; /// Data -1, then +1 rows in pairs (row==-1 if one entry) int * indices_; /// Number of rows int numberRows_; /// Number of columns int numberColumns_; /// True if all entries have two elements bool trueNetwork_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyWssmp.hpp0000644000076600007660000000347211510657452015641 0ustar coincoin/* $Id: ClpCholeskyWssmp.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpCholeskyWssmp_H #define ClpCholeskyWssmp_H #include "ClpCholeskyBase.hpp" class ClpMatrixBase; class ClpCholeskyDense; /** Wssmp class for Clp Cholesky factorization */ class ClpCholeskyWssmp : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ //@{ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /** Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const double * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (double * region) ; //@} /**@name Constructors, destructor */ //@{ /** Constructor which has dense columns activated. Default is off. */ ClpCholeskyWssmp(int denseThreshold = -1); /** Destructor */ virtual ~ClpCholeskyWssmp(); // Copy ClpCholeskyWssmp(const ClpCholeskyWssmp&); // Assignment ClpCholeskyWssmp& operator=(const ClpCholeskyWssmp&); /// Clone virtual ClpCholeskyBase * clone() const ; //@} private: /**@name Data members */ //@{ //@} }; #endif Clp-1.15.10/src/ClpPredictorCorrector.cpp0000644000076600007660000055171112347557460016652 0ustar coincoin/* $Id: ClpPredictorCorrector.cpp 2035 2014-06-16 12:12:32Z forrest $ */ // 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). /* Implements crude primal dual predictor corrector algorithm */ //#define SOME_DEBUG #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpPredictorCorrector.hpp" #include "ClpEventHandler.hpp" #include "CoinPackedMatrix.hpp" #include "ClpMessage.hpp" #include "ClpCholeskyBase.hpp" #include "ClpHelperFunctions.hpp" #include "ClpQuadraticObjective.hpp" #include #include #include #include #include #if 0 static int yyyyyy = 0; void ClpPredictorCorrector::saveSolution(std::string fileName) { FILE * fp = fopen(fileName.c_str(), "wb"); if (fp) { int numberRows = numberRows_; int numberColumns = numberColumns_; fwrite(&numberRows, sizeof(int), 1, fp); fwrite(&numberColumns, sizeof(int), 1, fp); CoinWorkDouble dsave[20]; memset(dsave, 0, sizeof(dsave)); fwrite(dsave, sizeof(CoinWorkDouble), 20, fp); int msave[20]; memset(msave, 0, sizeof(msave)); msave[0] = numberIterations_; fwrite(msave, sizeof(int), 20, fp); fwrite(dual_, sizeof(CoinWorkDouble), numberRows, fp); fwrite(errorRegion_, sizeof(CoinWorkDouble), numberRows, fp); fwrite(rhsFixRegion_, sizeof(CoinWorkDouble), numberRows, fp); fwrite(solution_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(solution_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fwrite(diagonal_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(diagonal_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fwrite(wVec_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(wVec_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fwrite(zVec_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(zVec_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fwrite(upperSlack_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(upperSlack_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fwrite(lowerSlack_, sizeof(CoinWorkDouble), numberColumns, fp); fwrite(lowerSlack_ + numberColumns, sizeof(CoinWorkDouble), numberRows, fp); fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } #endif // Could change on CLP_LONG_CHOLESKY or COIN_LONG_WORK? static CoinWorkDouble eScale = 1.0e27; static CoinWorkDouble eBaseCaution = 1.0e-12; static CoinWorkDouble eBase = 1.0e-12; static CoinWorkDouble eDiagonal = 1.0e25; static CoinWorkDouble eDiagonalCaution = 1.0e18; static CoinWorkDouble eExtra = 1.0e-12; // main function int ClpPredictorCorrector::solve ( ) { problemStatus_ = -1; algorithm_ = 1; //create all regions if (!createWorkingData()) { problemStatus_ = 4; return 2; } #if COIN_LONG_WORK // reallocate some regions double * dualSave = dual_; dual_ = reinterpret_cast(new CoinWorkDouble[numberRows_]); double * reducedCostSave = reducedCost_; reducedCost_ = reinterpret_cast(new CoinWorkDouble[numberColumns_]); #endif //diagonalPerturbation_=1.0e-25; ClpMatrixBase * saveMatrix = NULL; // If quadratic then make copy so we can actually scale or normalize #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif /* If modeSwitch is : 0 - normal 1 - bit switch off centering 2 - bit always do type 2 4 - accept corrector nearly always */ int modeSwitch = 0; //if (quadraticObj) //modeSwitch |= 1; // switch off centring for now //if (quadraticObj) //modeSwitch |=4; ClpObjective * saveObjective = NULL; if (quadraticObj) { // check KKT is on if (!cholesky_->kkt()) { //No! handler_->message(CLP_BARRIER_KKT, messages_) << CoinMessageEol; return -1; } saveObjective = objective_; // We are going to make matrix full rather half objective_ = new ClpQuadraticObjective(*quadraticObj, 1); } bool allowIncreasingGap = (modeSwitch & 4) != 0; // If scaled then really scale matrix if (scalingFlag_ > 0 && rowScale_) { saveMatrix = matrix_; matrix_ = matrix_->scaledColumnCopy(this); } //initializeFeasible(); - this just set fixed flag smallestInfeasibility_ = COIN_DBL_MAX; int i; for (i = 0; i < LENGTH_HISTORY; i++) historyInfeasibility_[i] = COIN_DBL_MAX; //bool firstTime=true; //firstFactorization(true); int returnCode = cholesky_->order(this); if (returnCode || cholesky_->symbolic()) { COIN_DETAIL_PRINT(printf("Error return from symbolic - probably not enough memory\n")); problemStatus_ = 4; //delete all temporary regions deleteWorkingData(); if (saveMatrix) { // restore normal copy delete matrix_; matrix_ = saveMatrix; } // Restore quadratic objective if necessary if (saveObjective) { delete objective_; objective_ = saveObjective; } return -1; } mu_ = 1.0e10; diagonalScaleFactor_ = 1.0; //set iterations numberIterations_ = -1; int numberTotal = numberRows_ + numberColumns_; //initialize solution here if(createSolution() < 0) { COIN_DETAIL_PRINT(printf("Not enough memory\n")); problemStatus_ = 4; //delete all temporary regions deleteWorkingData(); if (saveMatrix) { // restore normal copy delete matrix_; matrix_ = saveMatrix; } return -1; } CoinWorkDouble * dualArray = reinterpret_cast(dual_); // Could try centering steps without any original step i.e. just center //firstFactorization(false); CoinZeroN(dualArray, numberRows_); multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0); matrix_->times(1.0, solution_, errorRegion_); maximumRHSError_ = maximumAbsElement(errorRegion_, numberRows_); maximumBoundInfeasibility_ = maximumRHSError_; //CoinWorkDouble maximumDualError_=COIN_DBL_MAX; //initialize actualDualStep_ = 0.0; actualPrimalStep_ = 0.0; gonePrimalFeasible_ = false; goneDualFeasible_ = false; //bool hadGoodSolution=false; diagonalNorm_ = solutionNorm_; mu_ = solutionNorm_; int numberFixed = updateSolution(-COIN_DBL_MAX); int numberFixedTotal = numberFixed; //int numberRows_DroppedBefore=0; //CoinWorkDouble extra=eExtra; //CoinWorkDouble maximumPerturbation=COIN_DBL_MAX; //constants for infeas interior point const CoinWorkDouble beta2 = 0.99995; const CoinWorkDouble tau = 0.00002; CoinWorkDouble lastComplementarityGap = COIN_DBL_MAX * 1.0e-20; CoinWorkDouble lastStep = 1.0; // use to see if to take affine CoinWorkDouble checkGap = COIN_DBL_MAX; int lastGoodIteration = 0; CoinWorkDouble bestObjectiveGap = COIN_DBL_MAX; CoinWorkDouble bestObjective = COIN_DBL_MAX; int bestKilled = -1; int saveIteration = -1; int saveIteration2 = -1; bool sloppyOptimal = false; // this just to be used to exit bool sloppyOptimal2 = false; CoinWorkDouble * savePi = NULL; CoinWorkDouble * savePrimal = NULL; CoinWorkDouble * savePi2 = NULL; CoinWorkDouble * savePrimal2 = NULL; // Extra regions for centering CoinWorkDouble * saveX = new CoinWorkDouble[numberTotal]; CoinWorkDouble * saveY = new CoinWorkDouble[numberRows_]; CoinWorkDouble * saveZ = new CoinWorkDouble[numberTotal]; CoinWorkDouble * saveW = new CoinWorkDouble[numberTotal]; CoinWorkDouble * saveSL = new CoinWorkDouble[numberTotal]; CoinWorkDouble * saveSU = new CoinWorkDouble[numberTotal]; // Save smallest mu used in primal dual moves CoinWorkDouble objScale = optimizationDirection_ / (rhsScale_ * objectiveScale_); while (problemStatus_ < 0) { //#define FULL_DEBUG #ifdef FULL_DEBUG { int i; printf("row pi artvec rhsfx\n"); for (i = 0; i < numberRows_; i++) { printf("%d %g %g %g\n", i, dual_[i], errorRegion_[i], rhsFixRegion_[i]); } printf(" col dsol ddiag dwvec dzvec dbdslu dbdsll\n"); for (i = 0; i < numberColumns_ + numberRows_; i++) { printf(" %d %g %g %g %g %g %g\n", i, solution_[i], diagonal_[i], wVec_[i], zVec_[i], upperSlack_[i], lowerSlack_[i]); } } #endif complementarityGap_ = complementarityGap(numberComplementarityPairs_, numberComplementarityItems_, 0); handler_->message(CLP_BARRIER_ITERATION, messages_) << numberIterations_ << static_cast(primalObjective_ * objScale - dblParam_[ClpObjOffset]) << static_cast(dualObjective_ * objScale - dblParam_[ClpObjOffset]) << static_cast(complementarityGap_) << numberFixedTotal << cholesky_->rank() << CoinMessageEol; // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; break; } } #if 0 if (numberIterations_ == -1) { saveSolution("xxx.sav"); if (yyyyyy) exit(99); } #endif // move up history for (i = 1; i < LENGTH_HISTORY; i++) historyInfeasibility_[i-1] = historyInfeasibility_[i]; historyInfeasibility_[LENGTH_HISTORY-1] = complementarityGap_; // switch off saved if changes //if (saveIteration+10 KEEP_GOING_IF_FIXED) goodGapChange = 0.99; // make more likely to carry on } CoinWorkDouble gapO; CoinWorkDouble lastGood = bestObjectiveGap; if (gonePrimalFeasible_ && goneDualFeasible_) { CoinWorkDouble largestObjective; if (CoinAbs(primalObjective_) > CoinAbs(dualObjective_)) { largestObjective = CoinAbs(primalObjective_); } else { largestObjective = CoinAbs(dualObjective_); } if (largestObjective < 1.0) { largestObjective = 1.0; } gapO = CoinAbs(primalObjective_ - dualObjective_) / largestObjective; handler_->message(CLP_BARRIER_OBJECTIVE_GAP, messages_) << static_cast(gapO) << CoinMessageEol; //start saving best bool saveIt = false; if (gapO < bestObjectiveGap) { bestObjectiveGap = gapO; #ifndef SAVE_ON_OBJ saveIt = true; #endif } if (primalObjective_ < bestObjective) { bestObjective = primalObjective_; #ifdef SAVE_ON_OBJ saveIt = true; #endif } if (numberFixedTotal > bestKilled) { bestKilled = numberFixedTotal; #if KEEP_GOING_IF_FIXED<10 saveIt = true; #endif } if (saveIt) { #if KEEP_GOING_IF_FIXED<10 COIN_DETAIL_PRINT(printf("saving\n")); #endif saveIteration = numberIterations_; if (!savePi) { savePi = new CoinWorkDouble[numberRows_]; savePrimal = new CoinWorkDouble [numberTotal]; } CoinMemcpyN(dualArray, numberRows_, savePi); CoinMemcpyN(solution_, numberTotal, savePrimal); } else if(gapO > 2.0 * bestObjectiveGap) { //maybe be more sophisticated e.g. re-initialize having //fixed variables and dropped rows //std::cout <<" gap increasing "<= 0) { handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_) << CoinMessageEol; CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0); // save alternate if (numberFixedTotal > bestKilled && maximumBoundInfeasibility_ < 1.0e-6 && scaledRHSError < 1.0e-2) { bestKilled = numberFixedTotal; #if KEEP_GOING_IF_FIXED<10 COIN_DETAIL_PRINT(printf("saving alternate\n")); #endif saveIteration2 = numberIterations_; if (!savePi2) { savePi2 = new CoinWorkDouble[numberRows_]; savePrimal2 = new CoinWorkDouble [numberTotal]; } CoinMemcpyN(dualArray, numberRows_, savePi2); CoinMemcpyN(solution_, numberTotal, savePrimal2); } if (sloppyOptimal2) { // vaguely optimal if (maximumBoundInfeasibility_ > 1.0e-2 || scaledRHSError > 1.0e-2 || maximumDualError_ > objectiveNorm_ * 1.0e-2) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; problemStatus_ = 0; // benefit of doubt break; } } else { // not close to optimal but check if getting bad CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0); if ((maximumBoundInfeasibility_ > 1.0e-1 || scaledRHSError > 1.0e-1 || maximumDualError_ > objectiveNorm_ * 1.0e-1) && (numberIterations_ > 50 && complementarityGap_ > 0.9 * historyInfeasibility_[0])) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; break; } if (complementarityGap_ > 0.95 * checkGap && bestObjectiveGap < 1.0e-3 && (numberIterations_ > saveIteration + 5 || numberIterations_ > 100)) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; break; } } } if (complementarityGap_ > 0.5 * checkGap && primalObjective_ > bestObjective + 1.0e-9 && (numberIterations_ > saveIteration + 5 || numberIterations_ > 100)) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; break; } } // See if we should be thinking about exit if diverging double relativeMultiplier = 1.0 + fabs(primalObjective_) + fabs(dualObjective_); // Quadratic coding is rubbish so be more forgiving? double gapO2 = gapO; if (quadraticObj) { relativeMultiplier *= 5.0; CoinWorkDouble largestObjective; if (CoinAbs(primalObjective_) > CoinAbs(dualObjective_)) { largestObjective = CoinAbs(primalObjective_); } else { largestObjective = CoinAbs(dualObjective_); } if (largestObjective < 1.0) { largestObjective = 1.0; } gapO2 = CoinAbs(primalObjective_ - dualObjective_) / largestObjective; } if (gapO2 < 1.0e-5 + 1.0e-9 * relativeMultiplier || complementarityGap_ < 0.1 + 1.0e-9 * relativeMultiplier) sloppyOptimal2 = true; if ((gapO2 < 1.0e-6 || (gapO2 < 1.0e-4 && complementarityGap_ < 0.1)) && !sloppyOptimal) { // save solution if none saved if (saveIteration<0) { saveIteration = numberIterations_; if (!savePi) { savePi = new CoinWorkDouble[numberRows_]; savePrimal = new CoinWorkDouble [numberTotal]; } CoinMemcpyN(dualArray, numberRows_, savePi); CoinMemcpyN(solution_, numberTotal, savePrimal); } sloppyOptimal = true; sloppyOptimal2 = true; handler_->message(CLP_BARRIER_CLOSE_TO_OPTIMAL, messages_) << numberIterations_ << static_cast(complementarityGap_) << CoinMessageEol; } int numberBack = quadraticObj ? 10 : 5; //tryJustPredictor=true; //printf("trying just predictor\n"); //} if (complementarityGap_ >= 1.05 * lastComplementarityGap) { handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_) << static_cast(complementarityGap_) << "increasing" << CoinMessageEol; if (saveIteration >= 0 && sloppyOptimal2) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; break; } else if (numberIterations_ - lastGoodIteration >= numberBack && complementarityGap_ < 1.0e-6) { break; // not doing very well - give up } } else if (complementarityGap_ < goodGapChange * lastComplementarityGap) { lastGoodIteration = numberIterations_; lastComplementarityGap = complementarityGap_; } else if (numberIterations_ - lastGoodIteration >= numberBack && complementarityGap_ < 1.0e-3) { handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_) << static_cast(complementarityGap_) << "not decreasing" << CoinMessageEol; if (gapO > 0.75 * lastGood && numberFixed < KEEP_GOING_IF_FIXED) { break; } } else if (numberIterations_ - lastGoodIteration >= 2 && complementarityGap_ < 1.0e-6) { handler_->message(CLP_BARRIER_COMPLEMENTARITY, messages_) << static_cast(complementarityGap_) << "not decreasing" << CoinMessageEol; break; } if (numberIterations_ > maximumBarrierIterations_ || hitMaximumIterations()) { handler_->message(CLP_BARRIER_STOPPING, messages_) << CoinMessageEol; problemStatus_ = 3; onStopped(); // set secondary status break; } if (gapO < targetGap_) { problemStatus_ = 0; handler_->message(CLP_BARRIER_EXIT, messages_) << " " << CoinMessageEol; break;//finished } if (complementarityGap_ < 1.0e-12) { problemStatus_ = 0; handler_->message(CLP_BARRIER_EXIT, messages_) << "- small complementarity gap" << CoinMessageEol; break;//finished } if (complementarityGap_ < 1.0e-10 && gapO < 1.0e-10) { problemStatus_ = 0; handler_->message(CLP_BARRIER_EXIT, messages_) << "- objective gap and complementarity gap both small" << CoinMessageEol; break;//finished } if (gapO < 1.0e-9) { CoinWorkDouble value = gapO * complementarityGap_; value *= actualPrimalStep_; value *= actualDualStep_; //std::cout< lastGoodIteration) { problemStatus_ = 0; handler_->message(CLP_BARRIER_EXIT, messages_) << "- objective gap and complementarity gap both smallish and small steps" << CoinMessageEol; break;//finished } } CoinWorkDouble nextGap = COIN_DBL_MAX; int nextNumber = 0; int nextNumberItems = 0; worstDirectionAccuracy_ = 0.0; int newDropped = 0; //Predictor step //prepare for cholesky. Set up scaled diagonal in deltaX // ** for efficiency may be better if scale factor known before CoinWorkDouble norm2 = 0.0; CoinWorkDouble maximumValue; getNorms(diagonal_, numberTotal, maximumValue, norm2); diagonalNorm_ = CoinSqrt(norm2 / numberComplementarityPairs_); diagonalScaleFactor_ = 1.0; CoinWorkDouble maximumAllowable = eScale; //scale so largest is less than allowable ? could do better CoinWorkDouble factor = 0.5; while (maximumValue > maximumAllowable) { diagonalScaleFactor_ *= factor; maximumValue *= factor; } /* endwhile */ if (diagonalScaleFactor_ != 1.0) { handler_->message(CLP_BARRIER_SCALING, messages_) << "diagonal" << static_cast(diagonalScaleFactor_) << CoinMessageEol; diagonalNorm_ *= diagonalScaleFactor_; } multiplyAdd(NULL, numberTotal, 0.0, diagonal_, diagonalScaleFactor_); int * rowsDroppedThisTime = new int [numberRows_]; newDropped = cholesky_->factorize(diagonal_, rowsDroppedThisTime); if (newDropped) { if (newDropped == -1) { COIN_DETAIL_PRINT(printf("Out of memory\n")); problemStatus_ = 4; //delete all temporary regions deleteWorkingData(); if (saveMatrix) { // restore normal copy delete matrix_; matrix_ = saveMatrix; } return -1; } else { #ifndef NDEBUG //int newDropped2=cholesky_->factorize(diagonal_,rowsDroppedThisTime); //assert(!newDropped2); #endif if (newDropped < 0 && 0) { //replace dropped newDropped = -newDropped; //off 1 to allow for reset all newDropped--; //set all bits false cholesky_->resetRowsDropped(); } } } delete [] rowsDroppedThisTime; if (cholesky_->status()) { std::cout << "bad cholesky?" << std::endl; abort(); } int phase = 0; // predictor, corrector , primal dual CoinWorkDouble directionAccuracy = 0.0; bool doCorrector = true; bool goodMove = true; //set up for affine direction setupForSolve(phase); if ((modeSwitch & 2) == 0) { directionAccuracy = findDirectionVector(phase); if (directionAccuracy > worstDirectionAccuracy_) { worstDirectionAccuracy_ = directionAccuracy; } if (saveIteration > 0 && directionAccuracy > 1.0) { handler_->message(CLP_BARRIER_EXIT2, messages_) << saveIteration << CoinMessageEol; break; } findStepLength(phase); nextGap = complementarityGap(nextNumber, nextNumberItems, 1); debugMove(0, actualPrimalStep_, actualDualStep_); debugMove(0, 1.0e-2, 1.0e-2); } CoinWorkDouble affineGap = nextGap; int bestPhase = 0; CoinWorkDouble bestNextGap = nextGap; // ? bestNextGap = CoinMax(nextGap, 0.8 * complementarityGap_); if (quadraticObj) bestNextGap = CoinMax(nextGap, 0.99 * complementarityGap_); if (complementarityGap_ > 1.0e-4 * numberComplementarityPairs_) { //std::cout <<"predicted duality gap "< (numberComplementarityPairs_), 2.0); } else { phi = pow(static_cast (numberComplementarityPairs_), 1.5); if (phi < 500.0 * 500.0) { phi = 500.0 * 500.0; } } mu_ = complementarityGap_ / phi; } //save information CoinWorkDouble product = affineProduct(); #if 0 //can we do corrector step? CoinWorkDouble xx = complementarityGap_ * (beta2 - tau) + product; if (xx > 0.0) { CoinWorkDouble saveMu = mu_; CoinWorkDouble mu2 = numberComplementarityPairs_; mu2 = xx / mu2; if (mu2 > mu_) { //std::cout<<" could increase to "<message(CLP_BARRIER_MU, messages_) << saveMu << mu_ << CoinMessageEol; } else { //std::cout<<" bad by any standards"< 0.9 * complementarityGap_ || 1) { goodMove = false; bestNextGap = COIN_DBL_MAX; } //CoinWorkDouble floatNumber = 2.0*numberComplementarityPairs_; //floatNumber = 1.0*numberComplementarityItems_; //mu_=nextGap/floatNumber; handler_->message(CLP_BARRIER_INFO, messages_) << "no corrector step" << CoinMessageEol; } else { phase = 1; } // If bad gap - try standard primal dual if (nextGap > complementarityGap_ * 1.001) goodMove = false; if ((modeSwitch & 2) != 0) goodMove = false; if (goodMove && doCorrector) { CoinMemcpyN(deltaX_, numberTotal, saveX); CoinMemcpyN(deltaY_, numberRows_, saveY); CoinMemcpyN(deltaZ_, numberTotal, saveZ); CoinMemcpyN(deltaW_, numberTotal, saveW); CoinMemcpyN(deltaSL_, numberTotal, saveSL); CoinMemcpyN(deltaSU_, numberTotal, saveSU); #ifdef HALVE CoinWorkDouble savePrimalStep = actualPrimalStep_; CoinWorkDouble saveDualStep = actualDualStep_; CoinWorkDouble saveMu = mu_; #endif //set up for next step setupForSolve(phase); CoinWorkDouble directionAccuracy2 = findDirectionVector(phase); if (directionAccuracy2 > worstDirectionAccuracy_) { worstDirectionAccuracy_ = directionAccuracy2; } CoinWorkDouble testValue = 1.0e2 * directionAccuracy; if (1.0e2 * projectionTolerance_ > testValue) { testValue = 1.0e2 * projectionTolerance_; } if (primalTolerance() > testValue) { testValue = primalTolerance(); } if (maximumRHSError_ > testValue) { testValue = maximumRHSError_; } if (directionAccuracy2 > testValue && numberIterations_ >= -77) { goodMove = false; #ifdef SOME_DEBUG printf("accuracy %g phase 1 failed, test value %g\n", directionAccuracy2, testValue); #endif } if (goodMove) { phase = 1; CoinWorkDouble norm = findStepLength(phase); nextGap = complementarityGap(nextNumber, nextNumberItems, 1); debugMove(1, actualPrimalStep_, actualDualStep_); //debugMove(1,1.0e-7,1.0e-7); goodMove = checkGoodMove(true, bestNextGap, allowIncreasingGap); if (norm < 0) goodMove = false; if (!goodMove) { #ifdef SOME_DEBUG printf("checkGoodMove failed\n"); #endif } } #ifdef HALVE int nHalve = 0; // relax test bestNextGap = CoinMax(bestNextGap, 0.9 * complementarityGap_); while (!goodMove) { mu_ = saveMu; actualPrimalStep_ = savePrimalStep; actualDualStep_ = saveDualStep; int i; //printf("halve %d\n",nHalve); nHalve++; const CoinWorkDouble lambda = 0.5; for (i = 0; i < numberRows_; i++) deltaY_[i] = lambda * deltaY_[i] + (1.0 - lambda) * saveY[i]; for (i = 0; i < numberTotal; i++) { deltaX_[i] = lambda * deltaX_[i] + (1.0 - lambda) * saveX[i]; deltaZ_[i] = lambda * deltaZ_[i] + (1.0 - lambda) * saveZ[i]; deltaW_[i] = lambda * deltaW_[i] + (1.0 - lambda) * saveW[i]; deltaSL_[i] = lambda * deltaSL_[i] + (1.0 - lambda) * saveSL[i]; deltaSU_[i] = lambda * deltaSU_[i] + (1.0 - lambda) * saveSU[i]; } CoinMemcpyN(saveX, numberTotal, deltaX_); CoinMemcpyN(saveY, numberRows_, deltaY_); CoinMemcpyN(saveZ, numberTotal, deltaZ_); CoinMemcpyN(saveW, numberTotal, deltaW_); CoinMemcpyN(saveSL, numberTotal, deltaSL_); CoinMemcpyN(saveSU, numberTotal, deltaSU_); findStepLength(1); nextGap = complementarityGap(nextNumber, nextNumberItems, 1); goodMove = checkGoodMove(true, bestNextGap, allowIncreasingGap); if (nHalve > 10) break; //assert (goodMove); } if (nHalve && handler_->logLevel() > 2) printf("halved %d times\n", nHalve); #endif } //bestPhase=-1; //goodMove=false; if (!goodMove) { // Just primal dual step CoinWorkDouble floatNumber; floatNumber = 2.0 * numberComplementarityPairs_; //floatNumber = numberComplementarityItems_; CoinWorkDouble saveMu = mu_; // use one from predictor corrector mu_ = complementarityGap_ / floatNumber; // If going well try small mu mu_ *= CoinSqrt((1.0 - lastStep) / (1.0 + 10.0 * lastStep)); CoinWorkDouble mu1 = mu_; CoinWorkDouble phi; if (numberComplementarityPairs_ <= 500) { phi = pow(static_cast (numberComplementarityPairs_), 2.0); } else { phi = pow(static_cast (numberComplementarityPairs_), 1.5); if (phi < 500.0 * 500.0) { phi = 500.0 * 500.0; } } mu_ = complementarityGap_ / phi; //printf("pd mu %g, alternate %g, smallest\n",mu_,mu1); mu_ = CoinSqrt(mu_ * mu1); mu_ = mu1; if ((numberIterations_ & 1) == 0 || numberIterations_ < 10) mu_ = saveMu; // Try simpler floatNumber = numberComplementarityItems_; mu_ = 0.5 * complementarityGap_ / floatNumber; //if ((modeSwitch&2)==0) { //if ((numberIterations_&1)==0) // mu_ *= 0.5; //} else { //mu_ *= 0.8; //} //set up for next step setupForSolve(2); findDirectionVector(2); CoinWorkDouble norm = findStepLength(2); // just for debug bestNextGap = complementarityGap_ * 1.0005; //bestNextGap=COIN_DBL_MAX; nextGap = complementarityGap(nextNumber, nextNumberItems, 2); debugMove(2, actualPrimalStep_, actualDualStep_); //debugMove(2,1.0e-7,1.0e-7); checkGoodMove(false, bestNextGap, allowIncreasingGap); if ((nextGap > 0.9 * complementarityGap_ && bestPhase == 0 && affineGap < nextGap && (numberIterations_ > 80 || (numberIterations_ > 20 && quadraticObj))) || norm < 0.0) { // Back to affine phase = 0; setupForSolve(phase); directionAccuracy = findDirectionVector(phase); findStepLength(phase); nextGap = complementarityGap(nextNumber, nextNumberItems, 1); bestNextGap = complementarityGap_; //checkGoodMove(false, bestNextGap,allowIncreasingGap); } } if (!goodMove) mu_ = nextGap / (static_cast (nextNumber) * 1.1); //if (quadraticObj) //goodMove=true; //goodMove=false; //TEMP // Do centering steps int numberTries = 0; int numberGoodTries = 0; #ifdef COIN_DETAIL CoinWorkDouble nextCenterGap = 0.0; CoinWorkDouble originalDualStep = actualDualStep_; CoinWorkDouble originalPrimalStep = actualPrimalStep_; #endif if (actualDualStep_ > 0.9 && actualPrimalStep_ > 0.9) goodMove = false; // don't bother if ((modeSwitch & 1) != 0) goodMove = false; while (goodMove && numberTries < 5) { goodMove = false; numberTries++; CoinMemcpyN(deltaX_, numberTotal, saveX); CoinMemcpyN(deltaY_, numberRows_, saveY); CoinMemcpyN(deltaZ_, numberTotal, saveZ); CoinMemcpyN(deltaW_, numberTotal, saveW); CoinWorkDouble savePrimalStep = actualPrimalStep_; CoinWorkDouble saveDualStep = actualDualStep_; CoinWorkDouble saveMu = mu_; setupForSolve(3); findDirectionVector(3); findStepLength(3); debugMove(3, actualPrimalStep_, actualDualStep_); //debugMove(3,1.0e-7,1.0e-7); CoinWorkDouble xGap = complementarityGap(nextNumber, nextNumberItems, 3); // If one small then that's the one that counts CoinWorkDouble checkDual = saveDualStep; CoinWorkDouble checkPrimal = savePrimalStep; if (checkDual > 5.0 * checkPrimal) { checkDual = 2.0 * checkPrimal; } else if (checkPrimal > 5.0 * checkDual) { checkPrimal = 2.0 * checkDual; } if (actualPrimalStep_ < checkPrimal || actualDualStep_ < checkDual || (xGap > nextGap && xGap > 0.9 * complementarityGap_)) { //if (actualPrimalStep_<=checkPrimal|| //actualDualStep_<=checkDual) { #ifdef SOME_DEBUG printf("PP rejected gap %.18g, steps %.18g %.18g, 2 gap %.18g, steps %.18g %.18g\n", xGap, actualPrimalStep_, actualDualStep_, nextGap, savePrimalStep, saveDualStep); #endif mu_ = saveMu; actualPrimalStep_ = savePrimalStep; actualDualStep_ = saveDualStep; CoinMemcpyN(saveX, numberTotal, deltaX_); CoinMemcpyN(saveY, numberRows_, deltaY_); CoinMemcpyN(saveZ, numberTotal, deltaZ_); CoinMemcpyN(saveW, numberTotal, deltaW_); } else { #ifdef SOME_DEBUG printf("PPphase 3 gap %.18g, steps %.18g %.18g, 2 gap %.18g, steps %.18g %.18g\n", xGap, actualPrimalStep_, actualDualStep_, nextGap, savePrimalStep, saveDualStep); #endif numberGoodTries++; #ifdef COIN_DETAIL nextCenterGap = xGap; #endif // See if big enough change if (actualPrimalStep_ < 1.01 * checkPrimal || actualDualStep_ < 1.01 * checkDual) { // stop now } else { // carry on goodMove = true; } } } if (numberGoodTries && handler_->logLevel() > 1) { COIN_DETAIL_PRINT(printf("%d centering steps moved from (gap %.18g, dual %.18g, primal %.18g) to (gap %.18g, dual %.18g, primal %.18g)\n", numberGoodTries, static_cast(nextGap), static_cast(originalDualStep), static_cast(originalPrimalStep), static_cast(nextCenterGap), static_cast(actualDualStep_), static_cast(actualPrimalStep_))); } // save last gap checkGap = complementarityGap_; numberFixed = updateSolution(nextGap); numberFixedTotal += numberFixed; } /* endwhile */ delete [] saveX; delete [] saveY; delete [] saveZ; delete [] saveW; delete [] saveSL; delete [] saveSU; if (savePi) { if (numberIterations_ - saveIteration > 20 && numberIterations_ - saveIteration2 < 5) { #if KEEP_GOING_IF_FIXED<10 std::cout << "Restoring2 from iteration " << saveIteration2 << std::endl; #endif CoinMemcpyN(savePi2, numberRows_, dualArray); CoinMemcpyN(savePrimal2, numberTotal, solution_); } else { #if KEEP_GOING_IF_FIXED<10 std::cout << "Restoring from iteration " << saveIteration << std::endl; #endif CoinMemcpyN(savePi, numberRows_, dualArray); CoinMemcpyN(savePrimal, numberTotal, solution_); } delete [] savePi; delete [] savePrimal; } delete [] savePi2; delete [] savePrimal2; //recompute slacks // Split out solution CoinZeroN(rowActivity_, numberRows_); CoinMemcpyN(solution_, numberColumns_, columnActivity_); matrix_->times(1.0, columnActivity_, rowActivity_); //unscale objective multiplyAdd(NULL, numberTotal, 0.0, cost_, scaleFactor_); multiplyAdd(NULL, numberRows_, 0, dualArray, scaleFactor_); checkSolution(); //CoinMemcpyN(reducedCost_,numberColumns_,dj_); // If quadratic use last solution // Restore quadratic objective if necessary if (saveObjective) { delete objective_; objective_ = saveObjective; objectiveValue_ = 0.5 * (primalObjective_ + dualObjective_); } handler_->message(CLP_BARRIER_END, messages_) << static_cast(sumPrimalInfeasibilities_) << static_cast(sumDualInfeasibilities_) << static_cast(complementarityGap_) << static_cast(objectiveValue()) << CoinMessageEol; //#ifdef SOME_DEBUG if (handler_->logLevel() > 1) COIN_DETAIL_PRINT(printf("ENDRUN status %d after %d iterations\n", problemStatus_, numberIterations_)); //#endif //std::cout<<"Absolute primal infeasibility at end "< tolerance) { if (zVec_[iColumn] < -z1 * maximumDualStep) { maximumDualStep = -zVec_[iColumn] / z1; #ifdef SOME_DEBUG chosenDualSequence = iColumn; lowDual = true; #endif } } if (lowerSlack_[iColumn] < maximumPrimalStep * delta) { CoinWorkDouble newStep = lowerSlack_[iColumn] / delta; if (newStep > 0.2 || newZ < hitTolerance || delta > 1.0e3 || delta <= 1.0e-6 || dj_[iColumn] < hitTolerance) { maximumPrimalStep = newStep; #ifdef SOME_DEBUG chosenPrimalSequence = iColumn; lowPrimal = true; #endif } else { //printf("small %d delta %g newZ %g step %g\n",iColumn,delta,newZ,newStep); } } } if (upperBound(iColumn)) { CoinWorkDouble delta = - deltaSU_[iColumn];; CoinWorkDouble w1 = deltaW_[iColumn]; CoinWorkDouble newT = wVec_[iColumn] + w1; if (wVec_[iColumn] > tolerance) { if (wVec_[iColumn] < -w1 * maximumDualStep) { maximumDualStep = -wVec_[iColumn] / w1; #ifdef SOME_DEBUG chosenDualSequence = iColumn; lowDual = false; #endif } } if (upperSlack_[iColumn] < maximumPrimalStep * delta) { CoinWorkDouble newStep = upperSlack_[iColumn] / delta; if (newStep > 0.2 || newT < hitTolerance || delta > 1.0e3 || delta <= 1.0e-6 || dj_[iColumn] > -hitTolerance) { maximumPrimalStep = newStep; #ifdef SOME_DEBUG chosenPrimalSequence = iColumn; lowPrimal = false; #endif } else { //printf("small %d delta %g newT %g step %g\n",iColumn,delta,newT,newStep); } } } } } #ifdef SOME_DEBUG printf("new step - phase %d, norm %.18g, dual step %.18g, primal step %.18g\n", phase, directionNorm, maximumDualStep, maximumPrimalStep); if (lowDual) printf("ld %d %g %g => %g (dj %g,sol %g) ", chosenDualSequence, zVec_[chosenDualSequence], deltaZ_[chosenDualSequence], zVec_[chosenDualSequence] + maximumDualStep * deltaZ_[chosenDualSequence], dj_[chosenDualSequence], solution_[chosenDualSequence]); else printf("ud %d %g %g => %g (dj %g,sol %g) ", chosenDualSequence, wVec_[chosenDualSequence], deltaW_[chosenDualSequence], wVec_[chosenDualSequence] + maximumDualStep * deltaW_[chosenDualSequence], dj_[chosenDualSequence], solution_[chosenDualSequence]); if (lowPrimal) printf("lp %d %g %g => %g (dj %g,sol %g)\n", chosenPrimalSequence, lowerSlack_[chosenPrimalSequence], deltaSL_[chosenPrimalSequence], lowerSlack_[chosenPrimalSequence] + maximumPrimalStep * deltaSL_[chosenPrimalSequence], dj_[chosenPrimalSequence], solution_[chosenPrimalSequence]); else printf("up %d %g %g => %g (dj %g,sol %g)\n", chosenPrimalSequence, upperSlack_[chosenPrimalSequence], deltaSU_[chosenPrimalSequence], upperSlack_[chosenPrimalSequence] + maximumPrimalStep * deltaSU_[chosenPrimalSequence], dj_[chosenPrimalSequence], solution_[chosenPrimalSequence]); #endif actualPrimalStep_ = stepLength_ * maximumPrimalStep; if (phase >= 0 && actualPrimalStep_ > 1.0) { actualPrimalStep_ = 1.0; } actualDualStep_ = stepLength_ * maximumDualStep; if (phase >= 0 && actualDualStep_ > 1.0) { actualDualStep_ = 1.0; } // See if quadratic objective #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif if (quadraticObj) { // Use smaller unless very small CoinWorkDouble smallerStep = CoinMin(actualDualStep_, actualPrimalStep_); if (smallerStep > 0.0001) { actualDualStep_ = smallerStep; actualPrimalStep_ = smallerStep; } } #define OFFQ #ifndef OFFQ if (quadraticObj) { // Don't bother if phase 0 or 3 or large gap //if ((phase==1||phase==2||phase==0)&&maximumDualError_>0.1*complementarityGap_ //&&smallerStep>0.001) { if ((phase == 1 || phase == 2 || phase == 0 || phase == 3)) { // minimize complementarity + norm*dual inf ? primal inf // at first - just check better - if not // Complementarity gap will be a*change*change + b*change +c CoinWorkDouble a = 0.0; CoinWorkDouble b = 0.0; CoinWorkDouble c = 0.0; /* SQUARE of dual infeasibility will be: square of dj - ...... */ CoinWorkDouble aq = 0.0; CoinWorkDouble bq = 0.0; CoinWorkDouble cq = 0.0; CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal CoinWorkDouble * linearDjChange = new CoinWorkDouble[numberTotal]; CoinZeroN(linearDjChange, numberColumns_); multiplyAdd(deltaY_, numberRows_, 1.0, linearDjChange + numberColumns_, 0.0); matrix_->transposeTimes(-1.0, deltaY_, linearDjChange); CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); CoinWorkDouble * quadraticElement = quadratic->getMutableElements(); for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble oldPrimal = solution_[iColumn]; if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]; c += lowerSlack_[iColumn] * zVec_[iColumn]; b += lowerSlack_[iColumn] * deltaZ_[iColumn] + zVec_[iColumn] * change; a += deltaZ_[iColumn] * change; } if (upperBound(iColumn)) { CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn]; c += upperSlack_[iColumn] * wVec_[iColumn]; b += upperSlack_[iColumn] * deltaW_[iColumn] + wVec_[iColumn] * change; a += deltaW_[iColumn] * change; } // new djs are dj_ + change*value CoinWorkDouble djChange = linearDjChange[iColumn]; if (iColumn < numberColumns_) { for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble changeJ = deltaX_[jColumn]; CoinWorkDouble elementValue = quadraticElement[j]; djChange += changeJ * elementValue; } } CoinWorkDouble gammaTerm = gamma2; if (primalR_) { gammaTerm += primalR_[iColumn]; } djChange += gammaTerm; // and dual infeasibility CoinWorkDouble oldInf = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn] + gammaTerm * solution_[iColumn]; CoinWorkDouble changeInf = djChange - deltaZ_[iColumn] + deltaW_[iColumn]; cq += oldInf * oldInf; bq += 2.0 * oldInf * changeInf; aq += changeInf * changeInf; } else { // fixed if (lowerBound(iColumn)) { c += lowerSlack_[iColumn] * zVec_[iColumn]; } if (upperBound(iColumn)) { c += upperSlack_[iColumn] * wVec_[iColumn]; } // new djs are dj_ + change*value CoinWorkDouble djChange = linearDjChange[iColumn]; if (iColumn < numberColumns_) { for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble changeJ = deltaX_[jColumn]; CoinWorkDouble elementValue = quadraticElement[j]; djChange += changeJ * elementValue; } } CoinWorkDouble gammaTerm = gamma2; if (primalR_) { gammaTerm += primalR_[iColumn]; } djChange += gammaTerm; // and dual infeasibility CoinWorkDouble oldInf = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn] + gammaTerm * solution_[iColumn]; CoinWorkDouble changeInf = djChange - deltaZ_[iColumn] + deltaW_[iColumn]; cq += oldInf * oldInf; bq += 2.0 * oldInf * changeInf; aq += changeInf * changeInf; } } delete [] linearDjChange; // ? We want to minimize complementarityGap + solutionNorm_*square of inf ?? // maybe use inf and do line search // To check see if matches at current step CoinWorkDouble step = actualPrimalStep_; //Current gap + solutionNorm_ * CoinSqrt (sum square inf) CoinWorkDouble multiplier = solutionNorm_; multiplier *= 0.01; multiplier = 1.0; CoinWorkDouble currentInf = multiplier * CoinSqrt(cq); CoinWorkDouble nextInf = multiplier * CoinSqrt(CoinMax(cq + step * bq + step * step * aq, 0.0)); CoinWorkDouble allowedIncrease = 1.4; #ifdef SOME_DEBUG printf("lin %g %g %g -> %g\n", a, b, c, c + b * step + a * step * step); printf("quad %g %g %g -> %g\n", aq, bq, cq, cq + bq * step + aq * step * step); debugMove(7, step, step); printf ("current dualInf %g, with step of %g is %g\n", currentInf, step, nextInf); #endif if (b > -1.0e-6) { if (phase != 0) directionNorm = -1.0; } if ((phase == 1 || phase == 2 || phase == 0 || phase == 3) && nextInf > 0.1 * complementarityGap_ && nextInf > currentInf * allowedIncrease) { //cq = CoinMax(cq,10.0); // convert to (x+q)*(x+q) = w CoinWorkDouble q = bq / (1.0 * aq); CoinWorkDouble w = CoinMax(q * q + (cq / aq) * (allowedIncrease - 1.0), 0.0); w = CoinSqrt(w); CoinWorkDouble stepX = w - q; step = stepX; nextInf = multiplier * CoinSqrt(CoinMax(cq + step * bq + step * step * aq, 0.0)); #ifdef SOME_DEBUG printf ("with step of %g dualInf is %g\n", step, nextInf); #endif actualDualStep_ = CoinMin(step, actualDualStep_); actualPrimalStep_ = CoinMin(step, actualPrimalStep_); } } } else { // probably pointless as linear // minimize complementarity // Complementarity gap will be a*change*change + b*change +c CoinWorkDouble a = 0.0; CoinWorkDouble b = 0.0; CoinWorkDouble c = 0.0; for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble oldPrimal = solution_[iColumn]; if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]; c += lowerSlack_[iColumn] * zVec_[iColumn]; b += lowerSlack_[iColumn] * deltaZ_[iColumn] + zVec_[iColumn] * change; a += deltaZ_[iColumn] * change; } if (upperBound(iColumn)) { CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn]; c += upperSlack_[iColumn] * wVec_[iColumn]; b += upperSlack_[iColumn] * deltaW_[iColumn] + wVec_[iColumn] * change; a += deltaW_[iColumn] * change; } } else { // fixed if (lowerBound(iColumn)) { c += lowerSlack_[iColumn] * zVec_[iColumn]; } if (upperBound(iColumn)) { c += upperSlack_[iColumn] * wVec_[iColumn]; } } } // ? We want to minimize complementarityGap; // maybe use inf and do line search // To check see if matches at current step CoinWorkDouble step = CoinMin(actualPrimalStep_, actualDualStep_); CoinWorkDouble next = c + b * step + a * step * step; #ifdef SOME_DEBUG printf("lin %g %g %g -> %g\n", a, b, c, c + b * step + a * step * step); debugMove(7, step, step); #endif if (b > -1.0e-6) { if (phase == 0) { #ifdef SOME_DEBUG printf("*** odd phase 0 direction\n"); #endif } else { directionNorm = -1.0; } } // and with ratio a = 0.0; b = 0.0; CoinWorkDouble ratio = actualDualStep_ / actualPrimalStep_; for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble oldPrimal = solution_[iColumn]; if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = oldPrimal + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]; b += lowerSlack_[iColumn] * deltaZ_[iColumn] * ratio + zVec_[iColumn] * change; a += deltaZ_[iColumn] * change * ratio; } if (upperBound(iColumn)) { CoinWorkDouble change = upper_[iColumn] - oldPrimal - deltaX_[iColumn] - upperSlack_[iColumn]; b += upperSlack_[iColumn] * deltaW_[iColumn] * ratio + wVec_[iColumn] * change; a += deltaW_[iColumn] * change * ratio; } } } // ? We want to minimize complementarityGap; // maybe use inf and do line search // To check see if matches at current step step = actualPrimalStep_; CoinWorkDouble next2 = c + b * step + a * step * step; if (next2 > next) { actualPrimalStep_ = CoinMin(actualPrimalStep_, actualDualStep_); actualDualStep_ = actualPrimalStep_; } #ifdef SOME_DEBUG printf("linb %g %g %g -> %g\n", a, b, c, c + b * step + a * step * step); debugMove(7, actualPrimalStep_, actualDualStep_); #endif if (b > -1.0e-6) { if (phase == 0) { #ifdef SOME_DEBUG printf("*** odd phase 0 direction\n"); #endif } else { directionNorm = -1.0; } } } #else //actualPrimalStep_ =0.5*actualDualStep_; #endif #ifdef FULL_DEBUG if (phase == 3) { CoinWorkDouble minBeta = 0.1 * mu_; CoinWorkDouble maxBeta = 10.0 * mu_; for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn]; CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (delta2Z_[iColumn] < minBeta || delta2Z_[iColumn] > maxBeta) printf("3lower %d primal %g, dual %g, gap %g, old gap %g\n", iColumn, primalValue, dualValue, gapProduct, delta2Z_[iColumn]); } if (upperBound(iColumn)) { CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn]; CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (delta2W_[iColumn] < minBeta || delta2W_[iColumn] > maxBeta) printf("3upper %d primal %g, dual %g, gap %g, old gap %g\n", iColumn, primalValue, dualValue, gapProduct, delta2W_[iColumn]); } } } } #endif #ifdef SOME_DEBUG_not { CoinWorkDouble largestL = 0.0; CoinWorkDouble smallestL = COIN_DBL_MAX; CoinWorkDouble largestU = 0.0; CoinWorkDouble smallestU = COIN_DBL_MAX; CoinWorkDouble sumL = 0.0; CoinWorkDouble sumU = 0.0; int nL = 0; int nU = 0; for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn]; CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; largestL = CoinMax(largestL, gapProduct); smallestL = CoinMin(smallestL, gapProduct); nL++; sumL += gapProduct; } if (upperBound(iColumn)) { CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn]; CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; largestU = CoinMax(largestU, gapProduct); smallestU = CoinMin(smallestU, gapProduct); nU++; sumU += gapProduct; } } } CoinWorkDouble mu = (sumL + sumU) / (static_cast (nL + nU)); CoinWorkDouble minBeta = 0.1 * mu; CoinWorkDouble maxBeta = 10.0 * mu; int nBL = 0; int nAL = 0; int nBU = 0; int nAU = 0; for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn]; CoinWorkDouble dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; CoinWorkDouble primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct < minBeta) nBL++; else if (gapProduct > maxBeta) nAL++; //if (gapProduct<0.1*minBeta) //printf("Lsmall one %d dual %g primal %g\n",iColumn, // dualValue,primalValue); } if (upperBound(iColumn)) { CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn]; CoinWorkDouble dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; CoinWorkDouble primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct < minBeta) nBU++; else if (gapProduct > maxBeta) nAU++; //if (gapProduct<0.1*minBeta) //printf("Usmall one %d dual %g primal %g\n",iColumn, // dualValue,primalValue); } } } printf("phase %d new mu %.18g new gap %.18g\n", phase, mu, sumL + sumU); printf(" %d lower, smallest %.18g, %d below - largest %.18g, %d above\n", nL, smallestL, nBL, largestL, nAL); printf(" %d upper, smallest %.18g, %d below - largest %.18g, %d above\n", nU, smallestU, nBU, largestU, nAU); } #endif return directionNorm; } /* Does solve. region1 is for deltaX (columns+rows), region2 for deltaPi (rows) */ void ClpPredictorCorrector::solveSystem(CoinWorkDouble * region1, CoinWorkDouble * region2, const CoinWorkDouble * region1In, const CoinWorkDouble * region2In, const CoinWorkDouble * saveRegion1, const CoinWorkDouble * saveRegion2, bool gentleRefine) { int iRow; int numberTotal = numberRows_ + numberColumns_; if (region2In) { // normal for (iRow = 0; iRow < numberRows_; iRow++) region2[iRow] = region2In[iRow]; } else { // initial solution - (diagonal is 1 or 0) CoinZeroN(region2, numberRows_); } int iColumn; if (cholesky_->type() < 20) { // not KKT for (iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = region1In[iColumn] * diagonal_[iColumn]; multiplyAdd(region1 + numberColumns_, numberRows_, -1.0, region2, 1.0); matrix_->times(1.0, region1, region2); CoinWorkDouble maximumRHS = maximumAbsElement(region2, numberRows_); CoinWorkDouble scale = 1.0; CoinWorkDouble unscale = 1.0; if (maximumRHS > 1.0e-30) { if (maximumRHS <= 0.5) { CoinWorkDouble factor = 2.0; while (maximumRHS <= 0.5) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } else if (maximumRHS >= 2.0 && maximumRHS <= COIN_DBL_MAX) { CoinWorkDouble factor = 0.5; while (maximumRHS >= 2.0) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } unscale = diagonalScaleFactor_ / scale; } else { //effectively zero scale = 0.0; unscale = 0.0; } multiplyAdd(NULL, numberRows_, 0.0, region2, scale); cholesky_->solve(region2); multiplyAdd(NULL, numberRows_, 0.0, region2, unscale); multiplyAdd(region2, numberRows_, -1.0, region1 + numberColumns_, 0.0); CoinZeroN(region1, numberColumns_); matrix_->transposeTimes(1.0, region2, region1); for (iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = (region1[iColumn] - region1In[iColumn]) * diagonal_[iColumn]; } else { for (iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = region1In[iColumn]; cholesky_->solveKKT(region1, region2, diagonal_, diagonalScaleFactor_); } if (saveRegion2) { //refine? CoinWorkDouble scaleX = 1.0; if (gentleRefine) scaleX = 0.8; multiplyAdd(saveRegion2, numberRows_, 1.0, region2, scaleX); assert (saveRegion1); multiplyAdd(saveRegion1, numberTotal, 1.0, region1, scaleX); } } // findDirectionVector. CoinWorkDouble ClpPredictorCorrector::findDirectionVector(const int phase) { CoinWorkDouble projectionTolerance = projectionTolerance_; //temporary //projectionTolerance=1.0e-15; CoinWorkDouble errorCheck = 0.9 * maximumRHSError_ / solutionNorm_; if (errorCheck > primalTolerance()) { if (errorCheck < projectionTolerance) { projectionTolerance = errorCheck; } } else { if (primalTolerance() < projectionTolerance) { projectionTolerance = primalTolerance(); } } CoinWorkDouble * newError = new CoinWorkDouble [numberRows_]; int numberTotal = numberRows_ + numberColumns_; //if flagged then entries zero so can do // For KKT separate out CoinWorkDouble * region1Save = NULL; //for refinement int iColumn; if (cholesky_->type() < 20) { int iColumn; for (iColumn = 0; iColumn < numberTotal; iColumn++) deltaX_[iColumn] = workArray_[iColumn] - solution_[iColumn]; multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, deltaY_, 0.0); matrix_->times(1.0, deltaX_, deltaY_); } else { // regions in will be workArray and newError // regions out deltaX_ and deltaY_ multiplyAdd(solution_ + numberColumns_, numberRows_, 1.0, newError, 0.0); matrix_->times(-1.0, solution_, newError); // This is inefficient but just for now get values which will be in deltay int iColumn; for (iColumn = 0; iColumn < numberTotal; iColumn++) deltaX_[iColumn] = workArray_[iColumn] - solution_[iColumn]; multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, deltaY_, 0.0); matrix_->times(1.0, deltaX_, deltaY_); } bool goodSolve = false; CoinWorkDouble * regionSave = NULL; //for refinement int numberTries = 0; CoinWorkDouble relativeError = COIN_DBL_MAX; CoinWorkDouble tryError = 1.0e31; CoinWorkDouble saveMaximum = 0.0; double firstError = 0.0; double lastError2 = 0.0; while (!goodSolve && numberTries < 30) { CoinWorkDouble lastError = relativeError; goodSolve = true; CoinWorkDouble maximumRHS; maximumRHS = CoinMax(maximumAbsElement(deltaY_, numberRows_), 1.0e-12); if (!numberTries) saveMaximum = maximumRHS; if (cholesky_->type() < 20) { // no kkt CoinWorkDouble scale = 1.0; CoinWorkDouble unscale = 1.0; if (maximumRHS > 1.0e-30) { if (maximumRHS <= 0.5) { CoinWorkDouble factor = 2.0; while (maximumRHS <= 0.5) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } else if (maximumRHS >= 2.0 && maximumRHS <= COIN_DBL_MAX) { CoinWorkDouble factor = 0.5; while (maximumRHS >= 2.0) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } unscale = diagonalScaleFactor_ / scale; } else { //effectively zero scale = 0.0; unscale = 0.0; } //printf("--putting scales to 1.0\n"); //scale=1.0; //unscale=1.0; multiplyAdd(NULL, numberRows_, 0.0, deltaY_, scale); cholesky_->solve(deltaY_); multiplyAdd(NULL, numberRows_, 0.0, deltaY_, unscale); #if 0 { printf("deltay\n"); for (int i = 0; i < numberRows_; i++) printf("%d %.18g\n", i, deltaY_[i]); } exit(66); #endif if (numberTries) { //refine? CoinWorkDouble scaleX = 1.0; if (lastError > 1.0e-5) scaleX = 0.8; multiplyAdd(regionSave, numberRows_, 1.0, deltaY_, scaleX); } //CoinZeroN(newError,numberRows_); multiplyAdd(deltaY_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0); CoinZeroN(deltaX_, numberColumns_); matrix_->transposeTimes(1.0, deltaY_, deltaX_); //if flagged then entries zero so can do for (iColumn = 0; iColumn < numberTotal; iColumn++) deltaX_[iColumn] = deltaX_[iColumn] * diagonal_[iColumn] - workArray_[iColumn]; } else { // KKT solveSystem(deltaX_, deltaY_, workArray_, newError, region1Save, regionSave, lastError > 1.0e-5); } multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, newError, 0.0); matrix_->times(1.0, deltaX_, newError); numberTries++; //now add in old Ax - doing extra checking CoinWorkDouble maximumRHSError = 0.0; CoinWorkDouble maximumRHSChange = 0.0; int iRow; char * dropped = cholesky_->rowsDropped(); for (iRow = 0; iRow < numberRows_; iRow++) { if (!dropped[iRow]) { CoinWorkDouble newValue = newError[iRow]; CoinWorkDouble oldValue = errorRegion_[iRow]; //severity of errors depend on signs //**later */ if (CoinAbs(newValue) > maximumRHSChange) { maximumRHSChange = CoinAbs(newValue); } CoinWorkDouble result = newValue + oldValue; if (CoinAbs(result) > maximumRHSError) { maximumRHSError = CoinAbs(result); } newError[iRow] = result; } else { CoinWorkDouble newValue = newError[iRow]; CoinWorkDouble oldValue = errorRegion_[iRow]; if (CoinAbs(newValue) > maximumRHSChange) { maximumRHSChange = CoinAbs(newValue); } CoinWorkDouble result = newValue + oldValue; newError[iRow] = result; //newError[iRow]=0.0; //assert(deltaY_[iRow]==0.0); deltaY_[iRow] = 0.0; } } relativeError = maximumRHSError / solutionNorm_; relativeError = maximumRHSError / saveMaximum; if (relativeError > tryError) relativeError = tryError; if (numberTries == 1) firstError = relativeError; if (relativeError < lastError) { lastError2 = relativeError; maximumRHSChange_ = maximumRHSChange; if (relativeError > projectionTolerance && numberTries <= 3) { //try and refine goodSolve = false; } //*** extra test here if (!goodSolve) { if (!regionSave) { regionSave = new CoinWorkDouble [numberRows_]; if (cholesky_->type() >= 20) region1Save = new CoinWorkDouble [numberTotal]; } CoinMemcpyN(deltaY_, numberRows_, regionSave); if (cholesky_->type() < 20) { // not KKT multiplyAdd(newError, numberRows_, -1.0, deltaY_, 0.0); } else { // KKT CoinMemcpyN(deltaX_, numberTotal, region1Save); // and back to input region CoinMemcpyN(deltaY_, numberRows_, newError); } } } else { //std::cout <<" worse residual = "<type() < 20) { // not KKT multiplyAdd(deltaY_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0); CoinZeroN(deltaX_, numberColumns_); matrix_->transposeTimes(1.0, deltaY_, deltaX_); //if flagged then entries zero so can do for (iColumn = 0; iColumn < numberTotal; iColumn++) deltaX_[iColumn] = deltaX_[iColumn] * diagonal_[iColumn] - workArray_[iColumn]; } else { // KKT CoinMemcpyN(region1Save, numberTotal, deltaX_); } } else { // disaster CoinFillN(deltaX_, numberTotal, static_cast(1.0)); CoinFillN(deltaY_, numberRows_, static_cast(1.0)); COIN_DETAIL_PRINT(printf("bad cholesky\n")); } } } /* endwhile */ if (firstError > 1.0e-8 || numberTries > 1) { handler_->message(CLP_BARRIER_ACCURACY, messages_) << phase << numberTries << static_cast(firstError) << static_cast(lastError2) << CoinMessageEol; } delete [] regionSave; delete [] region1Save; delete [] newError; // now rest CoinWorkDouble extra = eExtra; //multiplyAdd(deltaY_,numberRows_,1.0,deltaW_+numberColumns_,0.0); //CoinZeroN(deltaW_,numberColumns_); //matrix_->transposeTimes(-1.0,deltaY_,deltaW_); for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { deltaSU_[iColumn] = 0.0; deltaSL_[iColumn] = 0.0; deltaZ_[iColumn] = 0.0; CoinWorkDouble dd = deltaW_[iColumn]; deltaW_[iColumn] = 0.0; if (!flagged(iColumn)) { CoinWorkDouble deltaX = deltaX_[iColumn]; if (lowerBound(iColumn)) { CoinWorkDouble zValue = rhsZ_[iColumn]; CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn]; CoinWorkDouble slack = lowerSlack_[iColumn] + extra; deltaSL_[iColumn] = -rhsL_[iColumn] + deltaX; deltaZ_[iColumn] = (gHat - zVec_[iColumn] * deltaX) / slack; } if (upperBound(iColumn)) { CoinWorkDouble wValue = rhsW_[iColumn]; CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn]; CoinWorkDouble slack = upperSlack_[iColumn] + extra; deltaSU_[iColumn] = rhsU_[iColumn] - deltaX; deltaW_[iColumn] = (hHat + wVec_[iColumn] * deltaX) / slack; } if (0) { // different way of calculating CoinWorkDouble gamma2 = gamma_ * gamma_; CoinWorkDouble dZ = 0.0; CoinWorkDouble dW = 0.0; CoinWorkDouble zValue = rhsZ_[iColumn]; CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn]; CoinWorkDouble slackL = lowerSlack_[iColumn] + extra; CoinWorkDouble wValue = rhsW_[iColumn]; CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn]; CoinWorkDouble slackU = upperSlack_[iColumn] + extra; CoinWorkDouble q = rhsC_[iColumn] + gamma2 * deltaX + dd; if (primalR_) q += deltaX * primalR_[iColumn]; dW = (gHat + hHat - slackL * q + (wValue - zValue) * deltaX) / (slackL + slackU); dZ = dW + q; //printf("B %d old %g %g new %g %g\n",iColumn,deltaZ_[iColumn], //deltaW_[iColumn],dZ,dW); if (lowerBound(iColumn)) { if (upperBound(iColumn)) { //printf("B %d old %g %g new %g %g\n",iColumn,deltaZ_[iColumn], //deltaW_[iColumn],dZ,dW); deltaW_[iColumn] = dW; deltaZ_[iColumn] = dZ; } else { // just lower //printf("L %d old %g new %g\n",iColumn,deltaZ_[iColumn], //dZ); } } else { assert (upperBound(iColumn)); //printf("U %d old %g new %g\n",iColumn,deltaW_[iColumn], //dW); } } } } #if 0 CoinWorkDouble * check = new CoinWorkDouble[numberTotal]; // Check out rhsC_ multiplyAdd(deltaY_, numberRows_, -1.0, check + numberColumns_, 0.0); CoinZeroN(check, numberColumns_); matrix_->transposeTimes(1.0, deltaY_, check); quadraticDjs(check, deltaX_, -1.0); for (iColumn = 0; iColumn < numberTotal; iColumn++) { check[iColumn] += deltaZ_[iColumn] - deltaW_[iColumn]; if (CoinAbs(check[iColumn] - rhsC_[iColumn]) > 1.0e-3) printf("rhsC %d %g %g\n", iColumn, check[iColumn], rhsC_[iColumn]); } // Check out rhsZ_ for (iColumn = 0; iColumn < numberTotal; iColumn++) { check[iColumn] += lowerSlack_[iColumn] * deltaZ_[iColumn] + zVec_[iColumn] * deltaSL_[iColumn]; if (CoinAbs(check[iColumn] - rhsZ_[iColumn]) > 1.0e-3) printf("rhsZ %d %g %g\n", iColumn, check[iColumn], rhsZ_[iColumn]); } // Check out rhsW_ for (iColumn = 0; iColumn < numberTotal; iColumn++) { check[iColumn] += upperSlack_[iColumn] * deltaW_[iColumn] + wVec_[iColumn] * deltaSU_[iColumn]; if (CoinAbs(check[iColumn] - rhsW_[iColumn]) > 1.0e-3) printf("rhsW %d %g %g\n", iColumn, check[iColumn], rhsW_[iColumn]); } delete [] check; #endif return relativeError; } // createSolution. Creates solution from scratch int ClpPredictorCorrector::createSolution() { int numberTotal = numberRows_ + numberColumns_; int iColumn; CoinWorkDouble tolerance = primalTolerance(); // See if quadratic objective #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif if (!quadraticObj) { for (iColumn = 0; iColumn < numberTotal; iColumn++) { if (upper_[iColumn] - lower_[iColumn] > tolerance) clearFixed(iColumn); else setFixed(iColumn); } } else { // try leaving fixed for (iColumn = 0; iColumn < numberTotal; iColumn++) clearFixed(iColumn); } CoinWorkDouble maximumObjective = 0.0; CoinWorkDouble objectiveNorm2 = 0.0; getNorms(cost_, numberTotal, maximumObjective, objectiveNorm2); if (!maximumObjective) { maximumObjective = 1.0; // objective all zero } objectiveNorm2 = CoinSqrt(objectiveNorm2) / static_cast (numberTotal); objectiveNorm_ = maximumObjective; scaleFactor_ = 1.0; if (maximumObjective > 0.0) { if (maximumObjective < 1.0) { scaleFactor_ = maximumObjective; } else if (maximumObjective > 1.0e4) { scaleFactor_ = maximumObjective / 1.0e4; } } if (scaleFactor_ != 1.0) { objectiveNorm2 *= scaleFactor_; multiplyAdd(NULL, numberTotal, 0.0, cost_, 1.0 / scaleFactor_); objectiveNorm_ = maximumObjective / scaleFactor_; } // See if quadratic objective if (quadraticObj) { // If scaled then really scale matrix CoinWorkDouble scaleFactor = scaleFactor_ * optimizationDirection_ * objectiveScale_ * rhsScale_; if ((scalingFlag_ > 0 && rowScale_) || scaleFactor != 1.0) { CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); double * quadraticElement = quadratic->getMutableElements(); int numberColumns = quadratic->getNumCols(); CoinWorkDouble scale = 1.0 / scaleFactor; if (scalingFlag_ > 0 && rowScale_) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinWorkDouble scaleI = columnScale_[iColumn] * scale; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble scaleJ = columnScale_[jColumn]; quadraticElement[j] *= scaleI * scaleJ; objectiveNorm_ = CoinMax(objectiveNorm_, CoinAbs(quadraticElement[j])); } } } else { // not scaled for (int iColumn = 0; iColumn < numberColumns; iColumn++) { for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { quadraticElement[j] *= scale; objectiveNorm_ = CoinMax(objectiveNorm_, CoinAbs(quadraticElement[j])); } } } } } baseObjectiveNorm_ = objectiveNorm_; //accumulate fixed in dj region (as spare) //accumulate primal solution in primal region //DZ in lowerDual //DW in upperDual CoinWorkDouble infiniteCheck = 1.0e40; //CoinWorkDouble fakeCheck=1.0e10; //use deltaX region for work region for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble primalValue = solution_[iColumn]; clearFlagged(iColumn); clearFixedOrFree(iColumn); clearLowerBound(iColumn); clearUpperBound(iColumn); clearFakeLower(iColumn); clearFakeUpper(iColumn); if (!fixed(iColumn)) { dj_[iColumn] = 0.0; diagonal_[iColumn] = 1.0; deltaX_[iColumn] = 1.0; CoinWorkDouble lowerValue = lower_[iColumn]; CoinWorkDouble upperValue = upper_[iColumn]; if (lowerValue > -infiniteCheck) { if (upperValue < infiniteCheck) { //upper and lower bounds setLowerBound(iColumn); setUpperBound(iColumn); if (lowerValue >= 0.0) { solution_[iColumn] = lowerValue; } else if (upperValue <= 0.0) { solution_[iColumn] = upperValue; } else { solution_[iColumn] = 0.0; } } else { //just lower bound setLowerBound(iColumn); if (lowerValue >= 0.0) { solution_[iColumn] = lowerValue; } else { solution_[iColumn] = 0.0; } } } else { if (upperValue < infiniteCheck) { //just upper bound setUpperBound(iColumn); if (upperValue <= 0.0) { solution_[iColumn] = upperValue; } else { solution_[iColumn] = 0.0; } } else { //free setFixedOrFree(iColumn); solution_[iColumn] = 0.0; //std::cout<<" free "<times(-1.0, dj_, rhsFixRegion_); multiplyAdd(solution_ + numberColumns_, numberRows_, 1.0, errorRegion_, 0.0); matrix_->times(-1.0, solution_, errorRegion_); rhsNorm_ = maximumAbsElement(errorRegion_, numberRows_); if (rhsNorm_ < 1.0) { rhsNorm_ = 1.0; } int * rowsDropped = new int [numberRows_]; int returnCode = cholesky_->factorize(diagonal_, rowsDropped); if (returnCode == -1) { COIN_DETAIL_PRINT(printf("Out of memory\n")); problemStatus_ = 4; return -1; } if (cholesky_->status()) { std::cout << "singular on initial cholesky?" << std::endl; cholesky_->resetRowsDropped(); //cholesky_->factorize(rowDropped_); //if (cholesky_->status()) { //std::cout << "bad cholesky??? (after retry)" <type() < 20) { // not KKT cholesky_->solve(errorRegion_); //create information for solution multiplyAdd(errorRegion_, numberRows_, -1.0, deltaX_ + numberColumns_, 0.0); CoinZeroN(deltaX_, numberColumns_); matrix_->transposeTimes(1.0, errorRegion_, deltaX_); } else { // KKT // reverse sign on solution multiplyAdd(NULL, numberRows_ + numberColumns_, 0.0, solution_, -1.0); solveSystem(deltaX_, errorRegion_, solution_, NULL, NULL, NULL, false); } CoinWorkDouble initialValue = 1.0e2; if (rhsNorm_ * 1.0e-2 > initialValue) { initialValue = rhsNorm_ * 1.0e-2; } //initialValue = CoinMax(1.0,rhsNorm_); CoinWorkDouble smallestBoundDifference = COIN_DBL_MAX; CoinWorkDouble * fakeSolution = deltaX_; for ( iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { if (lower_[iColumn] - fakeSolution[iColumn] > initialValue) { initialValue = lower_[iColumn] - fakeSolution[iColumn]; } if (fakeSolution[iColumn] - upper_[iColumn] > initialValue) { initialValue = fakeSolution[iColumn] - upper_[iColumn]; } if (upper_[iColumn] - lower_[iColumn] < smallestBoundDifference) { smallestBoundDifference = upper_[iColumn] - lower_[iColumn]; } } } solutionNorm_ = 1.0e-12; handler_->message(CLP_BARRIER_SAFE, messages_) << static_cast(initialValue) << static_cast(objectiveNorm_) << CoinMessageEol; CoinWorkDouble extra = 1.0e-10; CoinWorkDouble largeGap = 1.0e15; //CoinWorkDouble safeObjectiveValue=2.0*objectiveNorm_; CoinWorkDouble safeObjectiveValue = objectiveNorm_ + 1.0; CoinWorkDouble safeFree = 1.0e-1 * initialValue; //printf("normal safe dual value of %g, primal value of %g\n", // safeObjectiveValue,initialValue); //safeObjectiveValue=CoinMax(2.0,1.0e-1*safeObjectiveValue); //initialValue=CoinMax(100.0,1.0e-1*initialValue);; //printf("temp safe dual value of %g, primal value of %g\n", // safeObjectiveValue,initialValue); CoinWorkDouble zwLarge = 1.0e2 * initialValue; //zwLarge=1.0e40; if (cholesky_->choleskyCondition() < 0.0 && cholesky_->type() < 20) { // looks bad - play safe initialValue *= 10.0; safeObjectiveValue *= 10.0; safeFree *= 10.0; } CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal // First do primal side for ( iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { CoinWorkDouble lowerValue = lower_[iColumn]; CoinWorkDouble upperValue = upper_[iColumn]; CoinWorkDouble newValue; CoinWorkDouble setPrimal = initialValue; if (quadraticObj) { // perturb primal solution a bit //fakeSolution[iColumn] *= 0.002*CoinDrand48()+0.999; } if (lowerBound(iColumn)) { if (upperBound(iColumn)) { //upper and lower bounds if (upperValue - lowerValue > 2.0 * setPrimal) { CoinWorkDouble fakeValue = fakeSolution[iColumn]; if (fakeValue < lowerValue + setPrimal) { fakeValue = lowerValue + setPrimal; } if (fakeValue > upperValue - setPrimal) { fakeValue = upperValue - setPrimal; } newValue = fakeValue; } else { newValue = 0.5 * (upperValue + lowerValue); } } else { //just lower bound CoinWorkDouble fakeValue = fakeSolution[iColumn]; if (fakeValue < lowerValue + setPrimal) { fakeValue = lowerValue + setPrimal; } newValue = fakeValue; } } else { if (upperBound(iColumn)) { //just upper bound CoinWorkDouble fakeValue = fakeSolution[iColumn]; if (fakeValue > upperValue - setPrimal) { fakeValue = upperValue - setPrimal; } newValue = fakeValue; } else { //free newValue = fakeSolution[iColumn]; if (newValue >= 0.0) { if (newValue < safeFree) { newValue = safeFree; } } else { if (newValue > -safeFree) { newValue = -safeFree; } } } } solution_[iColumn] = newValue; } else { // fixed lowerSlack_[iColumn] = 0.0; upperSlack_[iColumn] = 0.0; solution_[iColumn] = lower_[iColumn]; zVec_[iColumn] = 0.0; wVec_[iColumn] = 0.0; diagonal_[iColumn] = 0.0; } } solutionNorm_ = maximumAbsElement(solution_, numberTotal); // Set bounds and do dj including quadratic largeGap = CoinMax(1.0e7, 1.02 * solutionNorm_); CoinPackedMatrix * quadratic = NULL; const int * columnQuadratic = NULL; const CoinBigIndex * columnQuadraticStart = NULL; const int * columnQuadraticLength = NULL; const double * quadraticElement = NULL; if (quadraticObj) { quadratic = quadraticObj->quadraticObjective(); columnQuadratic = quadratic->getIndices(); columnQuadraticStart = quadratic->getVectorStarts(); columnQuadraticLength = quadratic->getVectorLengths(); quadraticElement = quadratic->getElements(); } CoinWorkDouble quadraticNorm = 0.0; for ( iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { CoinWorkDouble primalValue = solution_[iColumn]; CoinWorkDouble lowerValue = lower_[iColumn]; CoinWorkDouble upperValue = upper_[iColumn]; // Do dj CoinWorkDouble reducedCost = cost_[iColumn]; if (lowerBound(iColumn)) { reducedCost += linearPerturbation_; } if (upperBound(iColumn)) { reducedCost -= linearPerturbation_; } if (quadraticObj && iColumn < numberColumns_) { for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble valueJ = solution_[jColumn]; CoinWorkDouble elementValue = quadraticElement[j]; reducedCost += valueJ * elementValue; } quadraticNorm = CoinMax(quadraticNorm, CoinAbs(reducedCost)); } dj_[iColumn] = reducedCost; if (primalValue > lowerValue + largeGap && primalValue < upperValue - largeGap) { clearFixedOrFree(iColumn); setLowerBound(iColumn); setUpperBound(iColumn); lowerValue = CoinMax(lowerValue, primalValue - largeGap); upperValue = CoinMin(upperValue, primalValue + largeGap); lower_[iColumn] = lowerValue; upper_[iColumn] = upperValue; } } } safeObjectiveValue = CoinMax(safeObjectiveValue, quadraticNorm); for ( iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { CoinWorkDouble primalValue = solution_[iColumn]; CoinWorkDouble lowerValue = lower_[iColumn]; CoinWorkDouble upperValue = upper_[iColumn]; CoinWorkDouble reducedCost = dj_[iColumn]; CoinWorkDouble low = 0.0; CoinWorkDouble high = 0.0; if (lowerBound(iColumn)) { if (upperBound(iColumn)) { //upper and lower bounds if (upperValue - lowerValue > 2.0 * initialValue) { low = primalValue - lowerValue; high = upperValue - primalValue; } else { low = initialValue; high = initialValue; } CoinWorkDouble s = low + extra; CoinWorkDouble ratioZ; if (s < zwLarge) { ratioZ = 1.0; } else { ratioZ = CoinSqrt(zwLarge / s); } CoinWorkDouble t = high + extra; CoinWorkDouble ratioT; if (t < zwLarge) { ratioT = 1.0; } else { ratioT = CoinSqrt(zwLarge / t); } //modify s and t if (s > largeGap) { s = largeGap; } if (t > largeGap) { t = largeGap; } //modify if long long way away from bound if (reducedCost >= 0.0) { zVec_[iColumn] = reducedCost + safeObjectiveValue * ratioZ; zVec_[iColumn] = CoinMax(reducedCost, safeObjectiveValue * ratioZ); wVec_[iColumn] = safeObjectiveValue * ratioT; } else { zVec_[iColumn] = safeObjectiveValue * ratioZ; wVec_[iColumn] = -reducedCost + safeObjectiveValue * ratioT; wVec_[iColumn] = CoinMax(-reducedCost , safeObjectiveValue * ratioT); } CoinWorkDouble gammaTerm = gamma2; if (primalR_) gammaTerm += primalR_[iColumn]; diagonal_[iColumn] = (t * s) / (s * wVec_[iColumn] + t * zVec_[iColumn] + gammaTerm * t * s); } else { //just lower bound low = primalValue - lowerValue; high = 0.0; CoinWorkDouble s = low + extra; CoinWorkDouble ratioZ; if (s < zwLarge) { ratioZ = 1.0; } else { ratioZ = CoinSqrt(zwLarge / s); } //modify s if (s > largeGap) { s = largeGap; } if (reducedCost >= 0.0) { zVec_[iColumn] = reducedCost + safeObjectiveValue * ratioZ; zVec_[iColumn] = CoinMax(reducedCost , safeObjectiveValue * ratioZ); wVec_[iColumn] = 0.0; } else { zVec_[iColumn] = safeObjectiveValue * ratioZ; wVec_[iColumn] = 0.0; } CoinWorkDouble gammaTerm = gamma2; if (primalR_) gammaTerm += primalR_[iColumn]; diagonal_[iColumn] = s / (zVec_[iColumn] + s * gammaTerm); } } else { if (upperBound(iColumn)) { //just upper bound low = 0.0; high = upperValue - primalValue; CoinWorkDouble t = high + extra; CoinWorkDouble ratioT; if (t < zwLarge) { ratioT = 1.0; } else { ratioT = CoinSqrt(zwLarge / t); } //modify t if (t > largeGap) { t = largeGap; } if (reducedCost >= 0.0) { zVec_[iColumn] = 0.0; wVec_[iColumn] = safeObjectiveValue * ratioT; } else { zVec_[iColumn] = 0.0; wVec_[iColumn] = -reducedCost + safeObjectiveValue * ratioT; wVec_[iColumn] = CoinMax(-reducedCost , safeObjectiveValue * ratioT); } CoinWorkDouble gammaTerm = gamma2; if (primalR_) gammaTerm += primalR_[iColumn]; diagonal_[iColumn] = t / (wVec_[iColumn] + t * gammaTerm); } } lowerSlack_[iColumn] = low; upperSlack_[iColumn] = high; } } #if 0 if (solution_[0] > 0.0) { for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]), diagonal_[i], CoinAbs(dj_[i]), lowerSlack_[i], zVec_[i], upperSlack_[i], wVec_[i]); } else { for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]), diagonal_[i], CoinAbs(dj_[i]), upperSlack_[i], wVec_[i], lowerSlack_[i], zVec_[i] ); } exit(66); #endif return 0; } // complementarityGap. Computes gap //phase 0=as is , 1 = after predictor , 2 after corrector CoinWorkDouble ClpPredictorCorrector::complementarityGap(int & numberComplementarityPairs, int & numberComplementarityItems, const int phase) { CoinWorkDouble gap = 0.0; //seems to be same coding for phase = 1 or 2 numberComplementarityPairs = 0; numberComplementarityItems = 0; int numberTotal = numberRows_ + numberColumns_; CoinWorkDouble toleranceGap = 0.0; CoinWorkDouble largestGap = 0.0; CoinWorkDouble smallestGap = COIN_DBL_MAX; //seems to be same coding for phase = 1 or 2 int numberNegativeGaps = 0; CoinWorkDouble sumNegativeGap = 0.0; CoinWorkDouble largeGap = 1.0e2 * solutionNorm_; if (largeGap < 1.0e10) { largeGap = 1.0e10; } largeGap = 1.0e30; CoinWorkDouble dualTolerance = dblParam_[ClpDualTolerance]; CoinWorkDouble primalTolerance = dblParam_[ClpPrimalTolerance]; dualTolerance = dualTolerance / scaleFactor_; for (int iColumn = 0; iColumn < numberTotal; iColumn++) { if (!fixedOrFree(iColumn)) { numberComplementarityPairs++; //can collapse as if no lower bound both zVec and deltaZ 0.0 if (lowerBound(iColumn)) { numberComplementarityItems++; CoinWorkDouble dualValue; CoinWorkDouble primalValue; if (!phase) { dualValue = zVec_[iColumn]; primalValue = lowerSlack_[iColumn]; } else { CoinWorkDouble change; change = solution_[iColumn] + deltaX_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]; dualValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; primalValue = lowerSlack_[iColumn] + actualPrimalStep_ * change; } //reduce primalValue if (primalValue > largeGap) { primalValue = largeGap; } CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct < 0.0) { //cout<<"negative gap component "< largestGap) { largestGap = gapProduct; } smallestGap = CoinMin(smallestGap, gapProduct); if (dualValue > dualTolerance && primalValue > primalTolerance) { toleranceGap += dualValue * primalValue; } } if (upperBound(iColumn)) { numberComplementarityItems++; CoinWorkDouble dualValue; CoinWorkDouble primalValue; if (!phase) { dualValue = wVec_[iColumn]; primalValue = upperSlack_[iColumn]; } else { CoinWorkDouble change; change = upper_[iColumn] - solution_[iColumn] - deltaX_[iColumn] - upperSlack_[iColumn]; dualValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; primalValue = upperSlack_[iColumn] + actualPrimalStep_ * change; } //reduce primalValue if (primalValue > largeGap) { primalValue = largeGap; } CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct < 0.0) { //cout<<"negative gap component "< largestGap) { largestGap = gapProduct; } if (dualValue > dualTolerance && primalValue > primalTolerance) { toleranceGap += dualValue * primalValue; } } } } //if (numberIterations_>4) //exit(9); if (!phase && numberNegativeGaps) { handler_->message(CLP_BARRIER_NEGATIVE_GAPS, messages_) << numberNegativeGaps << static_cast(sumNegativeGap) << CoinMessageEol; } //in case all free! if (!numberComplementarityPairs) { numberComplementarityPairs = 1; } #ifdef SOME_DEBUG printf("with d,p steps %g,%g gap %g - smallest %g, largest %g, pairs %d\n", actualDualStep_, actualPrimalStep_, gap, smallestGap, largestGap, numberComplementarityPairs); #endif return gap; } // setupForSolve. //phase 0=affine , 1 = corrector , 2 = primal-dual void ClpPredictorCorrector::setupForSolve(const int phase) { CoinWorkDouble extra = eExtra; int numberTotal = numberRows_ + numberColumns_; int iColumn; #ifdef SOME_DEBUG printf("phase %d in setupForSolve, mu %.18g\n", phase, mu_); #endif CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal CoinWorkDouble * dualArray = reinterpret_cast(dual_); switch (phase) { case 0: CoinMemcpyN(errorRegion_, numberRows_, rhsB_); if (delta_ || dualR_) { // add in regularization CoinWorkDouble delta2 = delta_ * delta_; for (int iRow = 0; iRow < numberRows_; iRow++) { rhsB_[iRow] -= delta2 * dualArray[iRow]; if (dualR_) rhsB_[iRow] -= dualR_[iRow] * dualArray[iRow]; } } for (iColumn = 0; iColumn < numberTotal; iColumn++) { rhsC_[iColumn] = 0.0; rhsU_[iColumn] = 0.0; rhsL_[iColumn] = 0.0; rhsZ_[iColumn] = 0.0; rhsW_[iColumn] = 0.0; if (!flagged(iColumn)) { rhsC_[iColumn] = dj_[iColumn] - zVec_[iColumn] + wVec_[iColumn]; rhsC_[iColumn] += gamma2 * solution_[iColumn]; if (primalR_) rhsC_[iColumn] += primalR_[iColumn] * solution_[iColumn]; if (lowerBound(iColumn)) { rhsZ_[iColumn] = -zVec_[iColumn] * (lowerSlack_[iColumn] + extra); rhsL_[iColumn] = CoinMax(0.0, (lower_[iColumn] + lowerSlack_[iColumn]) - solution_[iColumn]); } if (upperBound(iColumn)) { rhsW_[iColumn] = -wVec_[iColumn] * (upperSlack_[iColumn] + extra); rhsU_[iColumn] = CoinMin(0.0, (upper_[iColumn] - upperSlack_[iColumn]) - solution_[iColumn]); } } } #if 0 for (int i = 0; i < 3; i++) { if (!CoinAbs(rhsZ_[i])) rhsZ_[i] = 0.0; if (!CoinAbs(rhsW_[i])) rhsW_[i] = 0.0; if (!CoinAbs(rhsU_[i])) rhsU_[i] = 0.0; if (!CoinAbs(rhsL_[i])) rhsL_[i] = 0.0; } if (solution_[0] > 0.0) { for (int i = 0; i < 3; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, solution_[i], diagonal_[i], dj_[i], lowerSlack_[i], zVec_[i], upperSlack_[i], wVec_[i]); for (int i = 0; i < 3; i++) printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, rhsC_[i], rhsZ_[i], rhsL_[i], rhsW_[i], rhsU_[i]); } else { for (int i = 0; i < 3; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, solution_[i], diagonal_[i], dj_[i], lowerSlack_[i], zVec_[i], upperSlack_[i], wVec_[i]); for (int i = 0; i < 3; i++) printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, rhsC_[i], rhsZ_[i], rhsL_[i], rhsW_[i], rhsU_[i]); } #endif break; case 1: // could be stored in delta2? for (iColumn = 0; iColumn < numberTotal; iColumn++) { rhsZ_[iColumn] = 0.0; rhsW_[iColumn] = 0.0; if (!flagged(iColumn)) { if (lowerBound(iColumn)) { rhsZ_[iColumn] = mu_ - zVec_[iColumn] * (lowerSlack_[iColumn] + extra) - deltaZ_[iColumn] * deltaX_[iColumn]; // To bring in line with OSL rhsZ_[iColumn] += deltaZ_[iColumn] * rhsL_[iColumn]; } if (upperBound(iColumn)) { rhsW_[iColumn] = mu_ - wVec_[iColumn] * (upperSlack_[iColumn] + extra) + deltaW_[iColumn] * deltaX_[iColumn]; // To bring in line with OSL rhsW_[iColumn] -= deltaW_[iColumn] * rhsU_[iColumn]; } } } #if 0 for (int i = 0; i < numberTotal; i++) { if (!CoinAbs(rhsZ_[i])) rhsZ_[i] = 0.0; if (!CoinAbs(rhsW_[i])) rhsW_[i] = 0.0; if (!CoinAbs(rhsU_[i])) rhsU_[i] = 0.0; if (!CoinAbs(rhsL_[i])) rhsL_[i] = 0.0; } if (solution_[0] > 0.0) { for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]), diagonal_[i], CoinAbs(dj_[i]), lowerSlack_[i], zVec_[i], upperSlack_[i], wVec_[i]); for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(rhsC_[i]), rhsZ_[i], rhsL_[i], rhsW_[i], rhsU_[i]); } else { for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(solution_[i]), diagonal_[i], CoinAbs(dj_[i]), upperSlack_[i], wVec_[i], lowerSlack_[i], zVec_[i] ); for (int i = 0; i < numberTotal; i++) printf("%d %.18g %.18g %.18g %.18g %.18g\n", i, CoinAbs(rhsC_[i]), rhsW_[i], rhsU_[i], rhsZ_[i], rhsL_[i]); } exit(66); #endif break; case 2: CoinMemcpyN(errorRegion_, numberRows_, rhsB_); for (iColumn = 0; iColumn < numberTotal; iColumn++) { rhsZ_[iColumn] = 0.0; rhsW_[iColumn] = 0.0; if (!flagged(iColumn)) { if (lowerBound(iColumn)) { rhsZ_[iColumn] = mu_ - zVec_[iColumn] * (lowerSlack_[iColumn] + extra); } if (upperBound(iColumn)) { rhsW_[iColumn] = mu_ - wVec_[iColumn] * (upperSlack_[iColumn] + extra); } } } break; case 3: { CoinWorkDouble minBeta = 0.1 * mu_; CoinWorkDouble maxBeta = 10.0 * mu_; CoinWorkDouble dualStep = CoinMin(1.0, actualDualStep_ + 0.1); CoinWorkDouble primalStep = CoinMin(1.0, actualPrimalStep_ + 0.1); #ifdef SOME_DEBUG printf("good complementarity range %g to %g\n", minBeta, maxBeta); #endif //minBeta=0.0; //maxBeta=COIN_DBL_MAX; for (iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble change = -rhsL_[iColumn] + deltaX_[iColumn]; CoinWorkDouble dualValue = zVec_[iColumn] + dualStep * deltaZ_[iColumn]; CoinWorkDouble primalValue = lowerSlack_[iColumn] + primalStep * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct > 0.0 && dualValue < 0.0) gapProduct = - gapProduct; #ifdef FULL_DEBUG delta2Z_[iColumn] = gapProduct; if (delta2Z_[iColumn] < minBeta || delta2Z_[iColumn] > maxBeta) printf("lower %d primal %g, dual %g, gap %g\n", iColumn, primalValue, dualValue, gapProduct); #endif CoinWorkDouble value = 0.0; if (gapProduct < minBeta) { value = 2.0 * (minBeta - gapProduct); value = (mu_ - gapProduct); value = (minBeta - gapProduct); assert (value > 0.0); } else if (gapProduct > maxBeta) { value = CoinMax(maxBeta - gapProduct, -maxBeta); assert (value < 0.0); } rhsZ_[iColumn] += value; } if (upperBound(iColumn)) { CoinWorkDouble change = rhsU_[iColumn] - deltaX_[iColumn]; CoinWorkDouble dualValue = wVec_[iColumn] + dualStep * deltaW_[iColumn]; CoinWorkDouble primalValue = upperSlack_[iColumn] + primalStep * change; CoinWorkDouble gapProduct = dualValue * primalValue; if (gapProduct > 0.0 && dualValue < 0.0) gapProduct = - gapProduct; #ifdef FULL_DEBUG delta2W_[iColumn] = gapProduct; if (delta2W_[iColumn] < minBeta || delta2W_[iColumn] > maxBeta) printf("upper %d primal %g, dual %g, gap %g\n", iColumn, primalValue, dualValue, gapProduct); #endif CoinWorkDouble value = 0.0; if (gapProduct < minBeta) { value = (minBeta - gapProduct); assert (value > 0.0); } else if (gapProduct > maxBeta) { value = CoinMax(maxBeta - gapProduct, -maxBeta); assert (value < 0.0); } rhsW_[iColumn] += value; } } } } break; } /* endswitch */ if (cholesky_->type() < 20) { for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble value = rhsC_[iColumn]; CoinWorkDouble zValue = rhsZ_[iColumn]; CoinWorkDouble wValue = rhsW_[iColumn]; #if 0 #if 1 if (phase == 0) { // more accurate value = dj[iColumn]; zValue = 0.0; wValue = 0.0; } else if (phase == 2) { // more accurate value = dj[iColumn]; zValue = mu_; wValue = mu_; } #endif assert (rhsL_[iColumn] >= 0.0); assert (rhsU_[iColumn] <= 0.0); if (lowerBound(iColumn)) { value += (-zVec_[iColumn] * rhsL_[iColumn] - zValue) / (lowerSlack_[iColumn] + extra); } if (upperBound(iColumn)) { value += (wValue - wVec_[iColumn] * rhsU_[iColumn]) / (upperSlack_[iColumn] + extra); } #else if (lowerBound(iColumn)) { CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn]; value -= gHat / (lowerSlack_[iColumn] + extra); } if (upperBound(iColumn)) { CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn]; value += hHat / (upperSlack_[iColumn] + extra); } #endif workArray_[iColumn] = diagonal_[iColumn] * value; } #if 0 if (solution_[0] > 0.0) { for (int i = 0; i < numberTotal; i++) printf("%d %.18g\n", i, workArray_[i]); } else { for (int i = 0; i < numberTotal; i++) printf("%d %.18g\n", i, workArray_[i]); } exit(66); #endif } else { // KKT for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble value = rhsC_[iColumn]; CoinWorkDouble zValue = rhsZ_[iColumn]; CoinWorkDouble wValue = rhsW_[iColumn]; if (lowerBound(iColumn)) { CoinWorkDouble gHat = zValue + zVec_[iColumn] * rhsL_[iColumn]; value -= gHat / (lowerSlack_[iColumn] + extra); } if (upperBound(iColumn)) { CoinWorkDouble hHat = wValue - wVec_[iColumn] * rhsU_[iColumn]; value += hHat / (upperSlack_[iColumn] + extra); } workArray_[iColumn] = value; } } } //method: sees if looks plausible change in complementarity bool ClpPredictorCorrector::checkGoodMove(const bool doCorrector, CoinWorkDouble & bestNextGap, bool allowIncreasingGap) { const CoinWorkDouble beta3 = 0.99997; bool goodMove = false; int nextNumber; int nextNumberItems; int numberTotal = numberRows_ + numberColumns_; CoinWorkDouble returnGap = bestNextGap; CoinWorkDouble nextGap = complementarityGap(nextNumber, nextNumberItems, 2); #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif if (nextGap > bestNextGap && nextGap > 0.9 * complementarityGap_ && doCorrector && !quadraticObj && !allowIncreasingGap) { #ifdef SOME_DEBUG printf("checkGood phase 1 next gap %.18g, phase 0 %.18g, old gap %.18g\n", nextGap, bestNextGap, complementarityGap_); #endif return false; } else { returnGap = nextGap; } CoinWorkDouble step; if (actualDualStep_ > actualPrimalStep_) { step = actualDualStep_; } else { step = actualPrimalStep_; } CoinWorkDouble testValue = 1.0 - step * (1.0 - beta3); //testValue=0.0; testValue *= complementarityGap_; if (nextGap < testValue) { //std::cout <<"predicted duality gap "< 1.0) { step = 1.0; } actualPrimalStep_ = step; //if (quadraticObj) //actualPrimalStep_ *=0.5; actualDualStep_ = step; goodMove = checkGoodMove2(step, bestNextGap, allowIncreasingGap); int pass = 0; while (!goodMove) { pass++; CoinWorkDouble gap = bestNextGap; goodMove = checkGoodMove2(step, gap, allowIncreasingGap); if (goodMove || pass > 3) { returnGap = gap; break; } if (step < 1.0e-4) { break; } step *= 0.5; actualPrimalStep_ = step; //if (quadraticObj) //actualPrimalStep_ *=0.5; actualDualStep_ = step; } /* endwhile */ if (doCorrector) { //say bad move if both small if (numberIterations_ & 1) { if (actualPrimalStep_ < 1.0e-2 && actualDualStep_ < 1.0e-2) { goodMove = false; } } else { if (actualPrimalStep_ < 1.0e-5 && actualDualStep_ < 1.0e-5) { goodMove = false; } if (actualPrimalStep_ * actualDualStep_ < 1.0e-20) { goodMove = false; } } } } if (goodMove) { //compute delta in objectives CoinWorkDouble deltaObjectivePrimal = 0.0; CoinWorkDouble deltaObjectiveDual = innerProduct(deltaY_, numberRows_, rhsFixRegion_); CoinWorkDouble error = 0.0; CoinWorkDouble * workArray = workArray_; CoinZeroN(workArray, numberColumns_); CoinMemcpyN(deltaY_, numberRows_, workArray + numberColumns_); matrix_->transposeTimes(-1.0, deltaY_, workArray); //CoinWorkDouble sumPerturbCost=0.0; for (int iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { //sumPerturbCost+=deltaX_[iColumn]; deltaObjectiveDual += deltaZ_[iColumn] * lower_[iColumn]; } if (upperBound(iColumn)) { //sumPerturbCost-=deltaX_[iColumn]; deltaObjectiveDual -= deltaW_[iColumn] * upper_[iColumn]; } CoinWorkDouble change = CoinAbs(workArray_[iColumn] - deltaZ_[iColumn] + deltaW_[iColumn]); error = CoinMax(change, error); } deltaObjectivePrimal += cost_[iColumn] * deltaX_[iColumn]; } //deltaObjectivePrimal+=sumPerturbCost*linearPerturbation_; CoinWorkDouble testValue; if (error > 0.0) { testValue = 1.0e1 * CoinMax(maximumDualError_, 1.0e-12) / error; } else { testValue = 1.0e1; } // If quadratic then primal step may compensate if (testValue < actualDualStep_ && !quadraticObj) { handler_->message(CLP_BARRIER_REDUCING, messages_) << "dual" << static_cast(actualDualStep_) << static_cast(testValue) << CoinMessageEol; actualDualStep_ = testValue; } } if (maximumRHSError_ < 1.0e1 * solutionNorm_ * primalTolerance() && maximumRHSChange_ > 1.0e-16 * solutionNorm_) { //check change in AX not too much //??? could be dropped row going infeasible CoinWorkDouble ratio = 1.0e1 * CoinMax(maximumRHSError_, 1.0e-12) / maximumRHSChange_; if (ratio < actualPrimalStep_) { handler_->message(CLP_BARRIER_REDUCING, messages_) << "primal" << static_cast(actualPrimalStep_) << static_cast(ratio) << CoinMessageEol; if (ratio > 1.0e-6) { actualPrimalStep_ = ratio; } else { actualPrimalStep_ = ratio; //std::cout <<"sign we should be stopping"< bestNextGap && !allowIncreasingGap) return false; CoinWorkDouble lowerBoundGap = gamma * nextGap * complementarityMultiplier; bool goodMove = true; int iColumn; for ( iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (lowerBound(iColumn)) { CoinWorkDouble part1 = lowerSlack_[iColumn] + actualPrimalStep_ * deltaSL_[iColumn]; CoinWorkDouble part2 = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; if (part1 * part2 < lowerBoundGap) { goodMove = false; break; } } if (upperBound(iColumn)) { CoinWorkDouble part1 = upperSlack_[iColumn] + actualPrimalStep_ * deltaSU_[iColumn]; CoinWorkDouble part2 = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; if (part1 * part2 < lowerBoundGap) { goodMove = false; break; } } } } CoinWorkDouble * nextDj = NULL; CoinWorkDouble maximumDualError = maximumDualError_; #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif CoinWorkDouble * dualArray = reinterpret_cast(dual_); if (quadraticObj) { // change gammad gammad = 1.0e-4; CoinWorkDouble gamma2 = gamma_ * gamma_; nextDj = new CoinWorkDouble [numberColumns_]; CoinWorkDouble * nextSolution = new CoinWorkDouble [numberColumns_]; // put next primal into nextSolution for ( iColumn = 0; iColumn < numberColumns_; iColumn++) { if (!flagged(iColumn)) { nextSolution[iColumn] = solution_[iColumn] + actualPrimalStep_ * deltaX_[iColumn]; } else { nextSolution[iColumn] = solution_[iColumn]; } } // do reduced costs CoinMemcpyN(cost_, numberColumns_, nextDj); matrix_->transposeTimes(-1.0, dualArray, nextDj); matrix_->transposeTimes(-actualDualStep_, deltaY_, nextDj); quadraticDjs(nextDj, nextSolution, 1.0); delete [] nextSolution; CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); const int * columnQuadraticLength = quadratic->getVectorLengths(); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (!fixedOrFree(iColumn)) { CoinWorkDouble newZ = 0.0; CoinWorkDouble newW = 0.0; if (lowerBound(iColumn)) { newZ = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; } if (upperBound(iColumn)) { newW = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; } if (columnQuadraticLength[iColumn]) { CoinWorkDouble gammaTerm = gamma2; if (primalR_) gammaTerm += primalR_[iColumn]; //CoinWorkDouble dualInfeasibility= //dj_[iColumn]-zVec_[iColumn]+wVec_[iColumn] //+gammaTerm*solution_[iColumn]; CoinWorkDouble newInfeasibility = nextDj[iColumn] - newZ + newW + gammaTerm * (solution_[iColumn] + actualPrimalStep_ * deltaX_[iColumn]); maximumDualError = CoinMax(maximumDualError, newInfeasibility); //if (CoinAbs(newInfeasibility)>CoinMax(2000.0*maximumDualError_,1.0e-2)) { //if (dualInfeasibility*newInfeasibility<0.0) { // printf("%d current %g next %g\n",iColumn,dualInfeasibility, // newInfeasibility); // goodMove=false; //} //} } } } delete [] nextDj; } // Satisfy g_p(alpha)? if (rhsNorm_ > solutionNorm_) { solutionNorm_ = rhsNorm_; } CoinWorkDouble errorCheck = maximumRHSError_ / solutionNorm_; if (errorCheck < maximumBoundInfeasibility_) { errorCheck = maximumBoundInfeasibility_; } // scale back move move = CoinMin(move, 0.95); //scale if ((1.0 - move)*errorCheck > primalTolerance()) { if (nextGap < gammap*(1.0 - move)*errorCheck) { goodMove = false; } } // Satisfy g_d(alpha)? errorCheck = maximumDualError / objectiveNorm_; if ((1.0 - move)*errorCheck > dualTolerance()) { if (nextGap < gammad*(1.0 - move)*errorCheck) { goodMove = false; } } if (goodMove) bestNextGap = nextGap; return goodMove; } // updateSolution. Updates solution at end of iteration //returns number fixed int ClpPredictorCorrector::updateSolution(CoinWorkDouble /*nextGap*/) { CoinWorkDouble * dualArray = reinterpret_cast(dual_); int numberTotal = numberRows_ + numberColumns_; //update pi multiplyAdd(deltaY_, numberRows_, actualDualStep_, dualArray, 1.0); CoinZeroN(errorRegion_, numberRows_); CoinZeroN(rhsFixRegion_, numberRows_); CoinWorkDouble maximumRhsInfeasibility = 0.0; CoinWorkDouble maximumBoundInfeasibility = 0.0; CoinWorkDouble maximumDualError = 1.0e-12; CoinWorkDouble primalObjectiveValue = 0.0; CoinWorkDouble dualObjectiveValue = 0.0; CoinWorkDouble solutionNorm = 1.0e-12; int numberKilled = 0; CoinWorkDouble freeMultiplier = 1.0e6; CoinWorkDouble trueNorm = diagonalNorm_ / diagonalScaleFactor_; if (freeMultiplier < trueNorm) { freeMultiplier = trueNorm; } if (freeMultiplier > 1.0e12) { freeMultiplier = 1.0e12; } freeMultiplier = 0.5 / freeMultiplier; CoinWorkDouble condition = CoinAbs(cholesky_->choleskyCondition()); bool caution; if ((condition < 1.0e10 && trueNorm < 1.0e12) || numberIterations_ < 20) { caution = false; } else { caution = true; } CoinWorkDouble extra = eExtra; const CoinWorkDouble largeFactor = 1.0e2; CoinWorkDouble largeGap = largeFactor * solutionNorm_; if (largeGap < largeFactor) { largeGap = largeFactor; } CoinWorkDouble dualFake = 0.0; CoinWorkDouble dualTolerance = dblParam_[ClpDualTolerance]; dualTolerance = dualTolerance / scaleFactor_; if (dualTolerance < 1.0e-12) { dualTolerance = 1.0e-12; } CoinWorkDouble offsetObjective = 0.0; CoinWorkDouble killTolerance = primalTolerance(); //CoinWorkDouble nextMu = nextGap/(static_cast(2*numberComplementarityPairs_)); //printf("using gap of %g\n",nextMu); //largest allowable ratio of lowerSlack/zVec (etc) CoinWorkDouble epsilonBase; CoinWorkDouble diagonalLimit; if (!caution) { epsilonBase = eBase; diagonalLimit = eDiagonal; } else { epsilonBase = eBaseCaution; diagonalLimit = eDiagonalCaution; } CoinWorkDouble maximumDJInfeasibility = 0.0; int numberIncreased = 0; int numberDecreased = 0; CoinWorkDouble largestDiagonal = 0.0; CoinWorkDouble smallestDiagonal = 1.0e50; CoinWorkDouble largeGap2 = CoinMax(1.0e7, 1.0e2 * solutionNorm_); //largeGap2 = 1.0e9; // When to start looking at killing (factor0 CoinWorkDouble killFactor; #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif #ifndef CLP_CAUTION #define KILL_ITERATION 50 #else #if CLP_CAUTION < 1 #define KILL_ITERATION 50 #else #define KILL_ITERATION 100 #endif #endif if (!quadraticObj || 1) { if (numberIterations_ < KILL_ITERATION) { killFactor = 1.0; } else if (numberIterations_ < 2 * KILL_ITERATION) { killFactor = 5.0; stepLength_ = CoinMax(stepLength_, 0.9995); } else if (numberIterations_ < 4 * KILL_ITERATION) { killFactor = 20.0; stepLength_ = CoinMax(stepLength_, 0.99995); } else { killFactor = 1.0e2; stepLength_ = CoinMax(stepLength_, 0.999995); } } else { killFactor = 1.0; } // put next primal into deltaSL_ int iColumn; int iRow; for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble thisWeight = deltaX_[iColumn]; CoinWorkDouble newPrimal = solution_[iColumn] + 1.0 * actualPrimalStep_ * thisWeight; deltaSL_[iColumn] = newPrimal; } #if 0 // nice idea but doesn't work multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0); matrix_->times(1.0, solution_, errorRegion_); multiplyAdd(deltaSL_ + numberColumns_, numberRows_, -1.0, rhsFixRegion_, 0.0); matrix_->times(1.0, deltaSL_, rhsFixRegion_); CoinWorkDouble newNorm = maximumAbsElement(deltaSL_, numberTotal); CoinWorkDouble tol = newNorm * primalTolerance(); bool goneInf = false; for (iRow = 0; iRow < numberRows_; iRow++) { CoinWorkDouble value = errorRegion_[iRow]; CoinWorkDouble valueNew = rhsFixRegion_[iRow]; if (CoinAbs(value) < tol && CoinAbs(valueNew) > tol) { printf("row %d old %g new %g\n", iRow, value, valueNew); goneInf = true; } } if (goneInf) { actualPrimalStep_ *= 0.5; for (iColumn = 0; iColumn < numberTotal; iColumn++) { CoinWorkDouble thisWeight = deltaX_[iColumn]; CoinWorkDouble newPrimal = solution_[iColumn] + 1.0 * actualPrimalStep_ * thisWeight; deltaSL_[iColumn] = newPrimal; } } CoinZeroN(errorRegion_, numberRows_); CoinZeroN(rhsFixRegion_, numberRows_); #endif // do reduced costs CoinMemcpyN(dualArray, numberRows_, dj_ + numberColumns_); CoinMemcpyN(cost_, numberColumns_, dj_); CoinWorkDouble quadraticOffset = quadraticDjs(dj_, deltaSL_, 1.0); // Save modified costs for fixed variables CoinMemcpyN(dj_, numberColumns_, deltaSU_); matrix_->transposeTimes(-1.0, dualArray, dj_); CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal CoinWorkDouble gammaOffset = 0.0; #if 0 const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const int * row = matrix_->getIndices(); const double * element = matrix_->getElements(); #endif for (iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { CoinWorkDouble reducedCost = dj_[iColumn]; bool thisKilled = false; CoinWorkDouble zValue = zVec_[iColumn] + actualDualStep_ * deltaZ_[iColumn]; CoinWorkDouble wValue = wVec_[iColumn] + actualDualStep_ * deltaW_[iColumn]; zVec_[iColumn] = zValue; wVec_[iColumn] = wValue; CoinWorkDouble thisWeight = deltaX_[iColumn]; CoinWorkDouble oldPrimal = solution_[iColumn]; CoinWorkDouble newPrimal = solution_[iColumn] + actualPrimalStep_ * thisWeight; CoinWorkDouble dualObjectiveThis = 0.0; CoinWorkDouble sUpper = extra; CoinWorkDouble sLower = extra; CoinWorkDouble kill; if (CoinAbs(newPrimal) > 1.0e4) { kill = killTolerance * 1.0e-4 * newPrimal; } else { kill = killTolerance; } kill *= 1.0e-3; //be conservative CoinWorkDouble smallerSlack = COIN_DBL_MAX; bool fakeOldBounds = false; bool fakeNewBounds = false; CoinWorkDouble trueLower; CoinWorkDouble trueUpper; if (iColumn < numberColumns_) { trueLower = columnLower_[iColumn]; trueUpper = columnUpper_[iColumn]; } else { trueLower = rowLower_[iColumn-numberColumns_]; trueUpper = rowUpper_[iColumn-numberColumns_]; } if (oldPrimal > trueLower + largeGap2 && oldPrimal < trueUpper - largeGap2) fakeOldBounds = true; if (newPrimal > trueLower + largeGap2 && newPrimal < trueUpper - largeGap2) fakeNewBounds = true; if (fakeOldBounds) { if (fakeNewBounds) { lower_[iColumn] = newPrimal - largeGap2; lowerSlack_[iColumn] = largeGap2; upper_[iColumn] = newPrimal + largeGap2; upperSlack_[iColumn] = largeGap2; } else { lower_[iColumn] = trueLower; setLowerBound(iColumn); lowerSlack_[iColumn] = CoinMax(newPrimal - trueLower, 1.0); upper_[iColumn] = trueUpper; setUpperBound(iColumn); upperSlack_[iColumn] = CoinMax(trueUpper - newPrimal, 1.0); } } else if (fakeNewBounds) { lower_[iColumn] = newPrimal - largeGap2; lowerSlack_[iColumn] = largeGap2; upper_[iColumn] = newPrimal + largeGap2; upperSlack_[iColumn] = largeGap2; // so we can just have one test fakeOldBounds = true; } CoinWorkDouble lowerBoundInfeasibility = 0.0; CoinWorkDouble upperBoundInfeasibility = 0.0; //double saveNewPrimal = newPrimal; if (lowerBound(iColumn)) { CoinWorkDouble oldSlack = lowerSlack_[iColumn]; CoinWorkDouble newSlack; newSlack = lowerSlack_[iColumn] + actualPrimalStep_ * (oldPrimal - oldSlack + thisWeight - lower_[iColumn]); if (fakeOldBounds) newSlack = lowerSlack_[iColumn]; CoinWorkDouble epsilon = CoinAbs(newSlack) * epsilonBase; epsilon = CoinMin(epsilon, 1.0e-5); //epsilon=1.0e-14; //make sure reasonable if (zValue < epsilon) { zValue = epsilon; } CoinWorkDouble feasibleSlack = newPrimal - lower_[iColumn]; if (feasibleSlack > 0.0 && newSlack > 0.0) { CoinWorkDouble larger; if (newSlack > feasibleSlack) { larger = newSlack; } else { larger = feasibleSlack; } if (CoinAbs(feasibleSlack - newSlack) < 1.0e-6 * larger) { newSlack = feasibleSlack; } } if (zVec_[iColumn] > dualTolerance) { dualObjectiveThis += lower_[iColumn] * zVec_[iColumn]; } lowerSlack_[iColumn] = newSlack; if (newSlack < smallerSlack) { smallerSlack = newSlack; } lowerBoundInfeasibility = CoinAbs(newPrimal - lowerSlack_[iColumn] - lower_[iColumn]); if (lowerSlack_[iColumn] <= kill * killFactor && CoinAbs(newPrimal - lower_[iColumn]) <= kill * killFactor) { CoinWorkDouble step = CoinMin(actualPrimalStep_ * 1.1, 1.0); CoinWorkDouble newPrimal2 = solution_[iColumn] + step * thisWeight; if (newPrimal2 < newPrimal && dj_[iColumn] > 1.0e-5 && numberIterations_ > 50 - 40) { newPrimal = lower_[iColumn]; lowerSlack_[iColumn] = 0.0; //printf("fixing %d to lower\n",iColumn); } } if (lowerSlack_[iColumn] <= kill && CoinAbs(newPrimal - lower_[iColumn]) <= kill) { //may be better to leave at value? newPrimal = lower_[iColumn]; lowerSlack_[iColumn] = 0.0; thisKilled = true; //cout< 0.0 && newSlack > 0.0) { CoinWorkDouble larger; if (newSlack > feasibleSlack) { larger = newSlack; } else { larger = feasibleSlack; } if (CoinAbs(feasibleSlack - newSlack) < 1.0e-6 * larger) { newSlack = feasibleSlack; } } if (wVec_[iColumn] > dualTolerance) { dualObjectiveThis -= upper_[iColumn] * wVec_[iColumn]; } upperSlack_[iColumn] = newSlack; if (newSlack < smallerSlack) { smallerSlack = newSlack; } upperBoundInfeasibility = CoinAbs(newPrimal + upperSlack_[iColumn] - upper_[iColumn]); if (upperSlack_[iColumn] <= kill * killFactor && CoinAbs(newPrimal - upper_[iColumn]) <= kill * killFactor) { CoinWorkDouble step = CoinMin(actualPrimalStep_ * 1.1, 1.0); CoinWorkDouble newPrimal2 = solution_[iColumn] + step * thisWeight; if (newPrimal2 > newPrimal && dj_[iColumn] < -1.0e-5 && numberIterations_ > 50 - 40) { newPrimal = upper_[iColumn]; upperSlack_[iColumn] = 0.0; //printf("fixing %d to upper\n",iColumn); } } if (upperSlack_[iColumn] <= kill && CoinAbs(newPrimal - upper_[iColumn]) <= kill) { //may be better to leave at value? newPrimal = upper_[iColumn]; upperSlack_[iColumn] = 0.0; thisKilled = true; } else { sUpper += upperSlack_[iColumn]; } } #if 0 if (newPrimal != saveNewPrimal && iColumn < numberColumns_) { // adjust slacks double movement = newPrimal - saveNewPrimal; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double slackMovement = element[j] * movement; solution_[iRow+numberColumns_] += slackMovement; // sign? } } #endif solution_[iColumn] = newPrimal; if (CoinAbs(newPrimal) > solutionNorm) { solutionNorm = CoinAbs(newPrimal); } if (!thisKilled) { CoinWorkDouble gammaTerm = gamma2; if (primalR_) { gammaTerm += primalR_[iColumn]; quadraticOffset += newPrimal * newPrimal * primalR_[iColumn]; } CoinWorkDouble dualInfeasibility = reducedCost - zVec_[iColumn] + wVec_[iColumn] + gammaTerm * newPrimal; if (CoinAbs(dualInfeasibility) > dualTolerance) { #if 0 if (dualInfeasibility > 0.0) { // To improve we could reduce t and/or increase z if (lowerBound(iColumn)) { CoinWorkDouble complementarity = zVec_[iColumn] * lowerSlack_[iColumn]; if (complementarity < nextMu) { CoinWorkDouble change = CoinMin(dualInfeasibility, (nextMu - complementarity) / lowerSlack_[iColumn]); dualInfeasibility -= change; COIN_DETAIL_PRINT(printf("%d lb locomp %g - dual inf from %g to %g\n", iColumn, complementarity, dualInfeasibility + change, dualInfeasibility)); zVec_[iColumn] += change; zValue = CoinMax(zVec_[iColumn], 1.0e-12); } } if (upperBound(iColumn)) { CoinWorkDouble complementarity = wVec_[iColumn] * upperSlack_[iColumn]; if (complementarity > nextMu) { CoinWorkDouble change = CoinMin(dualInfeasibility, (complementarity - nextMu) / upperSlack_[iColumn]); dualInfeasibility -= change; COIN_DETAIL_PRINT(printf("%d ub hicomp %g - dual inf from %g to %g\n", iColumn, complementarity, dualInfeasibility + change, dualInfeasibility)); wVec_[iColumn] -= change; wValue = CoinMax(wVec_[iColumn], 1.0e-12); } } } else { // To improve we could reduce z and/or increase t if (lowerBound(iColumn)) { CoinWorkDouble complementarity = zVec_[iColumn] * lowerSlack_[iColumn]; if (complementarity > nextMu) { CoinWorkDouble change = CoinMax(dualInfeasibility, (nextMu - complementarity) / lowerSlack_[iColumn]); dualInfeasibility -= change; COIN_DETAIL_PRINT(printf("%d lb hicomp %g - dual inf from %g to %g\n", iColumn, complementarity, dualInfeasibility + change, dualInfeasibility)); zVec_[iColumn] += change; zValue = CoinMax(zVec_[iColumn], 1.0e-12); } } if (upperBound(iColumn)) { CoinWorkDouble complementarity = wVec_[iColumn] * upperSlack_[iColumn]; if (complementarity < nextMu) { CoinWorkDouble change = CoinMax(dualInfeasibility, (complementarity - nextMu) / upperSlack_[iColumn]); dualInfeasibility -= change; COIN_DETAIL_PRINT(printf("%d ub locomp %g - dual inf from %g to %g\n", iColumn, complementarity, dualInfeasibility + change, dualInfeasibility)); wVec_[iColumn] -= change; wValue = CoinMax(wVec_[iColumn], 1.0e-12); } } } #endif dualFake += newPrimal * dualInfeasibility; } if (lowerBoundInfeasibility > maximumBoundInfeasibility) { maximumBoundInfeasibility = lowerBoundInfeasibility; } if (upperBoundInfeasibility > maximumBoundInfeasibility) { maximumBoundInfeasibility = upperBoundInfeasibility; } dualInfeasibility = CoinAbs(dualInfeasibility); if (dualInfeasibility > maximumDualError) { //printf("bad dual %d %g\n",iColumn, // reducedCost-zVec_[iColumn]+wVec_[iColumn]+gammaTerm*newPrimal); maximumDualError = dualInfeasibility; } dualObjectiveValue += dualObjectiveThis; gammaOffset += newPrimal * newPrimal; if (sLower > largeGap) { sLower = largeGap; } if (sUpper > largeGap) { sUpper = largeGap; } #if 1 CoinWorkDouble divisor = sLower * wValue + sUpper * zValue + gammaTerm * sLower * sUpper; CoinWorkDouble diagonalValue = (sUpper * sLower) / divisor; #else CoinWorkDouble divisor = sLower * wValue + sUpper * zValue + gammaTerm * sLower * sUpper; CoinWorkDouble diagonalValue2 = (sUpper * sLower) / divisor; CoinWorkDouble diagonalValue; if (!lowerBound(iColumn)) { diagonalValue = wValue / sUpper + gammaTerm; } else if (!upperBound(iColumn)) { diagonalValue = zValue / sLower + gammaTerm; } else { diagonalValue = zValue / sLower + wValue / sUpper + gammaTerm; } diagonalValue = 1.0 / diagonalValue; #endif diagonal_[iColumn] = diagonalValue; //FUDGE if (diagonalValue > diagonalLimit) { #ifdef COIN_DEVELOP std::cout << "large diagonal " << diagonalValue << std::endl; #endif diagonal_[iColumn] = diagonalLimit; } #ifdef COIN_DEVELOP if (diagonalValue < 1.0e-10) { //std::cout<<"small diagonal "< largestDiagonal) { largestDiagonal = diagonalValue; } if (diagonalValue < smallestDiagonal) { smallestDiagonal = diagonalValue; } deltaX_[iColumn] = 0.0; } else { numberKilled++; if (solution_[iColumn] != lower_[iColumn] && solution_[iColumn] != upper_[iColumn]) { COIN_DETAIL_PRINT(printf("%d %g %g %g\n", iColumn, static_cast(lower_[iColumn]), static_cast(solution_[iColumn]), static_cast(upper_[iColumn]))); } diagonal_[iColumn] = 0.0; zVec_[iColumn] = 0.0; wVec_[iColumn] = 0.0; setFlagged(iColumn); setFixedOrFree(iColumn); deltaX_[iColumn] = newPrimal; offsetObjective += newPrimal * deltaSU_[iColumn]; } } else { deltaX_[iColumn] = solution_[iColumn]; diagonal_[iColumn] = 0.0; offsetObjective += solution_[iColumn] * deltaSU_[iColumn]; if (upper_[iColumn] - lower_[iColumn] > 1.0e-5) { if (solution_[iColumn] < lower_[iColumn] + 1.0e-8 && dj_[iColumn] < -1.0e-8) { if (-dj_[iColumn] > maximumDJInfeasibility) { maximumDJInfeasibility = -dj_[iColumn]; } } if (solution_[iColumn] > upper_[iColumn] - 1.0e-8 && dj_[iColumn] > 1.0e-8) { if (dj_[iColumn] > maximumDJInfeasibility) { maximumDJInfeasibility = dj_[iColumn]; } } } } primalObjectiveValue += solution_[iColumn] * cost_[iColumn]; } handler_->message(CLP_BARRIER_DIAGONAL, messages_) << static_cast(largestDiagonal) << static_cast(smallestDiagonal) << CoinMessageEol; #if 0 // If diagonal wild - kill some if (largestDiagonal > 1.0e17 * smallestDiagonal) { CoinWorkDouble killValue = largestDiagonal * 1.0e-17; for (int iColumn = 0; iColumn < numberTotal; iColumn++) { if (CoinAbs(diagonal_[iColumn]) < killValue) diagonal_[iolumn] = 0.0; } } #endif // update rhs region multiplyAdd(deltaX_ + numberColumns_, numberRows_, -1.0, rhsFixRegion_, 1.0); matrix_->times(1.0, deltaX_, rhsFixRegion_); primalObjectiveValue += 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset; if (quadraticOffset) { // printf("gamma offset %g %g, quadoffset %g\n",gammaOffset,gamma2*gammaOffset,quadraticOffset); } dualObjectiveValue += offsetObjective + dualFake; dualObjectiveValue -= 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset; if (numberIncreased || numberDecreased) { handler_->message(CLP_BARRIER_SLACKS, messages_) << numberIncreased << numberDecreased << CoinMessageEol; } if (maximumDJInfeasibility) { handler_->message(CLP_BARRIER_DUALINF, messages_) << static_cast(maximumDJInfeasibility) << CoinMessageEol; } // Need to rethink (but it is only for printing) sumPrimalInfeasibilities_ = maximumRhsInfeasibility; sumDualInfeasibilities_ = maximumDualError; maximumBoundInfeasibility_ = maximumBoundInfeasibility; //compute error and fixed RHS multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, errorRegion_, 0.0); matrix_->times(1.0, solution_, errorRegion_); maximumDualError_ = maximumDualError; maximumBoundInfeasibility_ = maximumBoundInfeasibility; solutionNorm_ = solutionNorm; //finish off objective computation primalObjective_ = primalObjectiveValue * scaleFactor_; CoinWorkDouble dualValue2 = innerProduct(dualArray, numberRows_, rhsFixRegion_); dualObjectiveValue -= dualValue2; dualObjective_ = dualObjectiveValue * scaleFactor_; if (numberKilled) { handler_->message(CLP_BARRIER_KILLED, messages_) << numberKilled << CoinMessageEol; } CoinWorkDouble maximumRHSError1 = 0.0; CoinWorkDouble maximumRHSError2 = 0.0; CoinWorkDouble primalOffset = 0.0; char * dropped = cholesky_->rowsDropped(); for (iRow = 0; iRow < numberRows_; iRow++) { CoinWorkDouble value = errorRegion_[iRow]; if (!dropped[iRow]) { if (CoinAbs(value) > maximumRHSError1) { maximumRHSError1 = CoinAbs(value); } } else { if (CoinAbs(value) > maximumRHSError2) { maximumRHSError2 = CoinAbs(value); } primalOffset += value * dualArray[iRow]; } } primalObjective_ -= primalOffset * scaleFactor_; if (maximumRHSError1 > maximumRHSError2) { maximumRHSError_ = maximumRHSError1; } else { maximumRHSError_ = maximumRHSError1; //note change if (maximumRHSError2 > primalTolerance()) { handler_->message(CLP_BARRIER_ABS_DROPPED, messages_) << static_cast(maximumRHSError2) << CoinMessageEol; } } objectiveNorm_ = maximumAbsElement(dualArray, numberRows_); if (objectiveNorm_ < 1.0e-12) { objectiveNorm_ = 1.0e-12; } if (objectiveNorm_ < baseObjectiveNorm_) { //std::cout<<" base "< primalTolerance() || maximumDualError_ > dualTolerance / scaleFactor_) { handler_->message(CLP_BARRIER_ABS_ERROR, messages_) << static_cast(maximumRHSError_) << static_cast(maximumDualError_) << CoinMessageEol; } if (rhsNorm_ > solutionNorm_) { solutionNorm_ = rhsNorm_; } CoinWorkDouble scaledRHSError = maximumRHSError_ / (solutionNorm_ + 10.0); bool dualFeasible = true; #if KEEP_GOING_IF_FIXED > 5 if (maximumBoundInfeasibility_ > primalTolerance() || scaledRHSError > primalTolerance()) primalFeasible = false; #else if (maximumBoundInfeasibility_ > primalTolerance() || scaledRHSError > CoinMax(CoinMin(100.0 * primalTolerance(), 1.0e-5), primalTolerance())) primalFeasible = false; #endif // relax dual test if obj big and gap smallish CoinWorkDouble gap = CoinAbs(primalObjective_ - dualObjective_); CoinWorkDouble sizeObj = CoinMin(CoinAbs(primalObjective_), CoinAbs(dualObjective_)) + 1.0e-50; //printf("gap %g sizeObj %g ratio %g comp %g\n", // gap,sizeObj,gap/sizeObj,complementarityGap_); if (numberIterations_ > 100 && gap / sizeObj < 1.0e-9 && complementarityGap_ < 1.0e-7 * sizeObj) dualTolerance *= 1.0e2; if (maximumDualError_ > objectiveNorm_ * dualTolerance) dualFeasible = false; if (!primalFeasible || !dualFeasible) { handler_->message(CLP_BARRIER_FEASIBLE, messages_) << static_cast(maximumBoundInfeasibility_) << static_cast(scaledRHSError) << static_cast(maximumDualError_ / objectiveNorm_) << CoinMessageEol; } if (!gonePrimalFeasible_) { gonePrimalFeasible_ = primalFeasible; } else if (!primalFeasible) { gonePrimalFeasible_ = primalFeasible; if (!numberKilled) { handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_) << CoinMessageEol; } } if (!goneDualFeasible_) { goneDualFeasible_ = dualFeasible; } else if (!dualFeasible) { handler_->message(CLP_BARRIER_GONE_INFEASIBLE, messages_) << CoinMessageEol; goneDualFeasible_ = dualFeasible; } //objectiveValue(); if (solutionNorm_ > 1.0e40) { std::cout << "primal off to infinity" << std::endl; abort(); } if (objectiveNorm_ > 1.0e40) { std::cout << "dual off to infinity" << std::endl; abort(); } handler_->message(CLP_BARRIER_STEP, messages_) << static_cast(actualPrimalStep_) << static_cast(actualDualStep_) << static_cast(mu_) << CoinMessageEol; numberIterations_++; return numberKilled; } // Save info on products of affine deltaSU*deltaW and deltaSL*deltaZ CoinWorkDouble ClpPredictorCorrector::affineProduct() { CoinWorkDouble product = 0.0; //IF zVec starts as 0 then deltaZ always zero //(remember if free then zVec not 0) //I think free can be done with careful use of boundSlacks to zero //out all we want for (int iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { CoinWorkDouble w3 = deltaZ_[iColumn] * deltaX_[iColumn]; CoinWorkDouble w4 = -deltaW_[iColumn] * deltaX_[iColumn]; if (lowerBound(iColumn)) { w3 += deltaZ_[iColumn] * (solution_[iColumn] - lowerSlack_[iColumn] - lower_[iColumn]); product += w3; } if (upperBound(iColumn)) { w4 += deltaW_[iColumn] * (-solution_[iColumn] - upperSlack_[iColumn] + upper_[iColumn]); product += w4; } } return product; } //See exactly what would happen given current deltas void ClpPredictorCorrector::debugMove(int /*phase*/, CoinWorkDouble primalStep, CoinWorkDouble dualStep) { #ifndef SOME_DEBUG return; #endif CoinWorkDouble * dualArray = reinterpret_cast(dual_); int numberTotal = numberRows_ + numberColumns_; CoinWorkDouble * dualNew = ClpCopyOfArray(dualArray, numberRows_); CoinWorkDouble * errorRegionNew = new CoinWorkDouble [numberRows_]; CoinWorkDouble * rhsFixRegionNew = new CoinWorkDouble [numberRows_]; CoinWorkDouble * primalNew = ClpCopyOfArray(solution_, numberTotal); CoinWorkDouble * djNew = new CoinWorkDouble[numberTotal]; //update pi multiplyAdd(deltaY_, numberRows_, dualStep, dualNew, 1.0); // do reduced costs CoinMemcpyN(dualNew, numberRows_, djNew + numberColumns_); CoinMemcpyN(cost_, numberColumns_, djNew); matrix_->transposeTimes(-1.0, dualNew, djNew); // update x int iColumn; for (iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) primalNew[iColumn] += primalStep * deltaX_[iColumn]; } CoinWorkDouble quadraticOffset = quadraticDjs(djNew, primalNew, 1.0); CoinZeroN(errorRegionNew, numberRows_); CoinZeroN(rhsFixRegionNew, numberRows_); CoinWorkDouble maximumBoundInfeasibility = 0.0; CoinWorkDouble maximumDualError = 1.0e-12; CoinWorkDouble primalObjectiveValue = 0.0; CoinWorkDouble dualObjectiveValue = 0.0; CoinWorkDouble solutionNorm = 1.0e-12; const CoinWorkDouble largeFactor = 1.0e2; CoinWorkDouble largeGap = largeFactor * solutionNorm_; if (largeGap < largeFactor) { largeGap = largeFactor; } CoinWorkDouble dualFake = 0.0; CoinWorkDouble dualTolerance = dblParam_[ClpDualTolerance]; dualTolerance = dualTolerance / scaleFactor_; if (dualTolerance < 1.0e-12) { dualTolerance = 1.0e-12; } CoinWorkDouble newGap = 0.0; CoinWorkDouble offsetObjective = 0.0; CoinWorkDouble gamma2 = gamma_ * gamma_; // gamma*gamma will be added to diagonal CoinWorkDouble gammaOffset = 0.0; CoinWorkDouble maximumDjInfeasibility = 0.0; for ( iColumn = 0; iColumn < numberTotal; iColumn++) { if (!flagged(iColumn)) { CoinWorkDouble reducedCost = djNew[iColumn]; CoinWorkDouble zValue = zVec_[iColumn] + dualStep * deltaZ_[iColumn]; CoinWorkDouble wValue = wVec_[iColumn] + dualStep * deltaW_[iColumn]; CoinWorkDouble thisWeight = deltaX_[iColumn]; CoinWorkDouble oldPrimal = solution_[iColumn]; CoinWorkDouble newPrimal = primalNew[iColumn]; CoinWorkDouble lowerBoundInfeasibility = 0.0; CoinWorkDouble upperBoundInfeasibility = 0.0; if (lowerBound(iColumn)) { CoinWorkDouble oldSlack = lowerSlack_[iColumn]; CoinWorkDouble newSlack = lowerSlack_[iColumn] + primalStep * (oldPrimal - oldSlack + thisWeight - lower_[iColumn]); if (zValue > dualTolerance) { dualObjectiveValue += lower_[iColumn] * zVec_[iColumn]; } lowerBoundInfeasibility = CoinAbs(newPrimal - newSlack - lower_[iColumn]); newGap += newSlack * zValue; } if (upperBound(iColumn)) { CoinWorkDouble oldSlack = upperSlack_[iColumn]; CoinWorkDouble newSlack = upperSlack_[iColumn] + primalStep * (-oldPrimal - oldSlack - thisWeight + upper_[iColumn]); if (wValue > dualTolerance) { dualObjectiveValue -= upper_[iColumn] * wVec_[iColumn]; } upperBoundInfeasibility = CoinAbs(newPrimal + newSlack - upper_[iColumn]); newGap += newSlack * wValue; } if (CoinAbs(newPrimal) > solutionNorm) { solutionNorm = CoinAbs(newPrimal); } CoinWorkDouble gammaTerm = gamma2; if (primalR_) { gammaTerm += primalR_[iColumn]; quadraticOffset += newPrimal * newPrimal * primalR_[iColumn]; } CoinWorkDouble dualInfeasibility = reducedCost - zValue + wValue + gammaTerm * newPrimal; if (CoinAbs(dualInfeasibility) > dualTolerance) { dualFake += newPrimal * dualInfeasibility; } if (lowerBoundInfeasibility > maximumBoundInfeasibility) { maximumBoundInfeasibility = lowerBoundInfeasibility; } if (upperBoundInfeasibility > maximumBoundInfeasibility) { maximumBoundInfeasibility = upperBoundInfeasibility; } dualInfeasibility = CoinAbs(dualInfeasibility); if (dualInfeasibility > maximumDualError) { //printf("bad dual %d %g\n",iColumn, // reducedCost-zVec_[iColumn]+wVec_[iColumn]+gammaTerm*newPrimal); maximumDualError = dualInfeasibility; } gammaOffset += newPrimal * newPrimal; djNew[iColumn] = 0.0; } else { offsetObjective += primalNew[iColumn] * cost_[iColumn]; if (upper_[iColumn] - lower_[iColumn] > 1.0e-5) { if (primalNew[iColumn] < lower_[iColumn] + 1.0e-8 && djNew[iColumn] < -1.0e-8) { if (-djNew[iColumn] > maximumDjInfeasibility) { maximumDjInfeasibility = -djNew[iColumn]; } } if (primalNew[iColumn] > upper_[iColumn] - 1.0e-8 && djNew[iColumn] > 1.0e-8) { if (djNew[iColumn] > maximumDjInfeasibility) { maximumDjInfeasibility = djNew[iColumn]; } } } djNew[iColumn] = primalNew[iColumn]; } primalObjectiveValue += solution_[iColumn] * cost_[iColumn]; } // update rhs region multiplyAdd(djNew + numberColumns_, numberRows_, -1.0, rhsFixRegionNew, 1.0); matrix_->times(1.0, djNew, rhsFixRegionNew); primalObjectiveValue += 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset; dualObjectiveValue += offsetObjective + dualFake; dualObjectiveValue -= 0.5 * gamma2 * gammaOffset + 0.5 * quadraticOffset; // Need to rethink (but it is only for printing) //compute error and fixed RHS multiplyAdd(primalNew + numberColumns_, numberRows_, -1.0, errorRegionNew, 0.0); matrix_->times(1.0, primalNew, errorRegionNew); //finish off objective computation CoinWorkDouble primalObjectiveNew = primalObjectiveValue * scaleFactor_; CoinWorkDouble dualValue2 = innerProduct(dualNew, numberRows_, rhsFixRegionNew); dualObjectiveValue -= dualValue2; //CoinWorkDouble dualObjectiveNew=dualObjectiveValue*scaleFactor_; CoinWorkDouble maximumRHSError1 = 0.0; CoinWorkDouble maximumRHSError2 = 0.0; CoinWorkDouble primalOffset = 0.0; char * dropped = cholesky_->rowsDropped(); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { CoinWorkDouble value = errorRegionNew[iRow]; if (!dropped[iRow]) { if (CoinAbs(value) > maximumRHSError1) { maximumRHSError1 = CoinAbs(value); } } else { if (CoinAbs(value) > maximumRHSError2) { maximumRHSError2 = CoinAbs(value); } primalOffset += value * dualNew[iRow]; } } primalObjectiveNew -= primalOffset * scaleFactor_; //CoinWorkDouble maximumRHSError; if (maximumRHSError1 > maximumRHSError2) { ;//maximumRHSError = maximumRHSError1; } else { //maximumRHSError = maximumRHSError1; //note change if (maximumRHSError2 > primalTolerance()) { handler_->message(CLP_BARRIER_ABS_DROPPED, messages_) << static_cast(maximumRHSError2) << CoinMessageEol; } } /*printf("PH %d %g, %g new comp %g, b %g, p %g, d %g\n",phase, primalStep,dualStep,newGap,maximumBoundInfeasibility, maximumRHSError,maximumDualError); if (handler_->logLevel()>1) printf(" objs %g %g\n", primalObjectiveNew,dualObjectiveNew); if (maximumDjInfeasibility) { printf(" max dj error on fixed %g\n", maximumDjInfeasibility); } */ delete [] dualNew; delete [] errorRegionNew; delete [] rhsFixRegionNew; delete [] primalNew; delete [] djNew; } Clp-1.15.10/src/AbcSimplexPrimal.hpp0000644000076600007660000002407512101105055015545 0ustar coincoin/* $Id: AbcSimplexPrimal.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef AbcSimplexPrimal_H #define AbcSimplexPrimal_H #include "AbcSimplex.hpp" /** This solves LPs using the primal simplex method It inherits from AbcSimplex. It has no data of its own and is never created - only cast from a AbcSimplex object at algorithm time. */ class AbcSimplexPrimal : public AbcSimplex { public: /**@name Description of algorithm */ //@{ /** Primal algorithm Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of infeasibilityCost_ being given to getting primal feasible. In this version I have tried to be clever in a stupid way. The idea of fake bounds in dual seems to work so the primal analogue would be that of getting bounds on reduced costs (by a presolve approach) and using these for being above or below feasible region. I decided to waste memory and keep these explicitly. This allows for non-linear costs! I have not tested non-linear costs but will be glad to do something if a reasonable example is provided. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find incoming variable for Dantzig row choice. For steepest edge we keep an updated list of dual infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. This method has not been coded. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure whether we will also need explicit perturbation. The flow of primal is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by changing bounds so primal feasible. If looks finished check fake primal bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot column (incoming variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot column in tableau Choose outgoing row. If we don't find one then we look primal unbounded so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find outgoing row, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve changing bounds on variables to stay primal feasible. } } TODO's (or maybe not) At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot in option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. for use of exotic parameter startFinishoptions see Clpsimplex.hpp */ int primal(int ifValuesPass = 0, int startFinishOptions = 0); //@} /**@name For advanced users */ //@{ /// Do not change infeasibility cost and always say optimal void alwaysOptimal(bool onOff); bool alwaysOptimal() const; /** Normally outgoing variables can go out to slightly negative values (but within tolerance) - this is to help stability and and degeneracy. This can be switched off */ void exactOutgoing(bool onOff); bool exactOutgoing() const; //@} /**@name Functions used in primal */ //@{ /** This has the flow between re-factorizations Returns a code to say where decision to exit was made Problem status set to: -2 re-factorize -4 Looks optimal/infeasible -5 Looks unbounded +3 max iterations valuesOption has original value of valuesPass */ int whileIterating(int valuesOption); /** Do last half of an iteration. This is split out so people can force incoming variable. If solveType_ is 2 then this may re-factorize while normally it would exit to re-factorize. Return codes Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done) With solveType_ ==2 this should Pivot in a variable and choose an outgoing one. Assumes primal feasible - will not go through a bound. Returns step length in theta Returns ray in ray_ */ int pivotResult(int ifValuesPass = 0); int pivotResult4(int ifValuesPass = 0); /** The primals are updated by the given array. Returns number of infeasibilities. After rowArray will have cost changes for use next iteration */ int updatePrimalsInPrimal(CoinIndexedVector * rowArray, double theta, double & objectiveChange, int valuesPass); /** The primals are updated by the given array. costs are changed */ void updatePrimalsInPrimal(CoinIndexedVector & rowArray, double theta,bool valuesPass); /** After rowArray will have cost changes for use next iteration */ void createUpdateDuals(CoinIndexedVector & rowArray, const double * originalCost, const double extraCost[4], double & objectiveChange, int valuesPass); /** Update minor candidate vector - new reduced cost returned later try and get change in reduced cost (then may not need sequence in)*/ double updateMinorCandidate(const CoinIndexedVector & updateBy, CoinIndexedVector & candidate, int sequenceIn); /// Update partial Ftran by R update void updatePartialUpdate(CoinIndexedVector & partialUpdate); /// Do FT update as separate function for minor iterations (nonzero return code on problems) int doFTUpdate(CoinIndexedVector * vector[4]); /** Row array has pivot column This chooses pivot row. Rhs array is used for distance to next bound (for speed) For speed, we may need to go to a bucket approach when many variables go through bounds If valuesPass non-zero then compute dj for direction */ void primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, int valuesPass); typedef struct { double theta_; double alpha_; double saveDualIn_; double dualIn_; double lowerIn_; double upperIn_; double valueIn_; int sequenceIn_; int directionIn_; double dualOut_; double lowerOut_; double upperOut_; double valueOut_; int sequenceOut_; int directionOut_; int pivotRow_; int valuesPass_; } pivotStruct; void primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, pivotStruct & stuff); /** Chooses primal pivot column updateArray has cost updates (also use pivotRow_ from last iteration) Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first columns we look at */ void primalColumn(CoinPartitionedVector * updateArray, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1); /** Checks if tentative optimal actually means unbounded in primal Returns -3 if not, 2 if is unbounded */ int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, double changeCost); /** Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void statusOfProblemInPrimal(int type); /// Perturbs problem (method depends on perturbation()) void perturb(int type); /// Take off effect of perturbation and say whether to try dual bool unPerturb(); /// Unflag all variables and return number unflagged int unflag(); /** Get next superbasic -1 if none, Normal type is 1 If type is 3 then initializes sorted list if 2 uses list. */ int nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray); /// Create primal ray void primalRay(CoinIndexedVector * rowArray); /// Clears all bits and clears rowArray[1] etc void clearAll(); /// Sort of lexicographic resolve int lexSolve(); //@} }; #endif Clp-1.15.10/src/ClpNonLinearCost.cpp0000644000076600007660000024441211613504607015535 0ustar coincoin/* $Id: ClpNonLinearCost.cpp 1769 2011-07-26 09:31:51Z 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). #include "CoinPragma.hpp" #include #include #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "ClpNonLinearCost.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNonLinearCost::ClpNonLinearCost () : changeCost_(0.0), feasibleCost_(0.0), infeasibilityWeight_(-1.0), largestInfeasibility_(0.0), sumInfeasibilities_(0.0), averageTheta_(0.0), numberRows_(0), numberColumns_(0), start_(NULL), whichRange_(NULL), offset_(NULL), lower_(NULL), cost_(NULL), model_(NULL), infeasible_(NULL), numberInfeasibilities_(-1), status_(NULL), bound_(NULL), cost2_(NULL), method_(1), convex_(true), bothWays_(false) { } //#define VALIDATE #ifdef VALIDATE static double * saveLowerV = NULL; static double * saveUpperV = NULL; #ifdef NDEBUG Validate sgould not be set if no debug #endif #endif /* Constructor from simplex. This will just set up wasteful arrays for linear, but later may do dual analysis and even finding duplicate columns */ ClpNonLinearCost::ClpNonLinearCost ( ClpSimplex * model, int method) { method = 2; model_ = model; numberRows_ = model_->numberRows(); //if (numberRows_==402) { //model_->setLogLevel(63); //model_->setMaximumIterations(30000); //} numberColumns_ = model_->numberColumns(); // If gub then we need this extra int numberExtra = model_->numberExtraRows(); if (numberExtra) method = 1; int numberTotal1 = numberRows_ + numberColumns_; int numberTotal = numberTotal1 + numberExtra; convex_ = true; bothWays_ = false; method_ = method; numberInfeasibilities_ = 0; changeCost_ = 0.0; feasibleCost_ = 0.0; infeasibilityWeight_ = -1.0; double * cost = model_->costRegion(); // check if all 0 int iSequence; bool allZero = true; for (iSequence = 0; iSequence < numberTotal1; iSequence++) { if (cost[iSequence]) { allZero = false; break; } } if (allZero&&model_->clpMatrix()->type()<15) model_->setInfeasibilityCost(1.0); double infeasibilityCost = model_->infeasibilityCost(); sumInfeasibilities_ = 0.0; averageTheta_ = 0.0; largestInfeasibility_ = 0.0; // All arrays NULL to start status_ = NULL; bound_ = NULL; cost2_ = NULL; start_ = NULL; whichRange_ = NULL; offset_ = NULL; lower_ = NULL; cost_ = NULL; infeasible_ = NULL; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); // See how we are storing things bool always4 = (model_->clpMatrix()-> generalExpanded(model_, 10, iSequence) != 0); if (always4) method_ = 1; if (CLP_METHOD1) { start_ = new int [numberTotal+1]; whichRange_ = new int [numberTotal]; offset_ = new int [numberTotal]; memset(offset_, 0, numberTotal * sizeof(int)); // First see how much space we need int put = 0; // For quadratic we need -inf,0,0,+inf for (iSequence = 0; iSequence < numberTotal1; iSequence++) { if (!always4) { if (lower[iSequence] > -COIN_DBL_MAX) put++; if (upper[iSequence] < COIN_DBL_MAX) put++; put += 2; } else { put += 4; } } // and for extra put += 4 * numberExtra; #ifndef NDEBUG int kPut = put; #endif lower_ = new double [put]; cost_ = new double [put]; infeasible_ = new unsigned int[(put+31)>>5]; memset(infeasible_, 0, ((put + 31) >> 5)*sizeof(unsigned int)); put = 0; start_[0] = 0; for (iSequence = 0; iSequence < numberTotal1; iSequence++) { if (!always4) { if (lower[iSequence] > -COIN_DBL_MAX) { lower_[put] = -COIN_DBL_MAX; setInfeasible(put, true); cost_[put++] = cost[iSequence] - infeasibilityCost; } whichRange_[iSequence] = put; lower_[put] = lower[iSequence]; cost_[put++] = cost[iSequence]; lower_[put] = upper[iSequence]; cost_[put++] = cost[iSequence] + infeasibilityCost; if (upper[iSequence] < COIN_DBL_MAX) { lower_[put] = COIN_DBL_MAX; setInfeasible(put - 1, true); cost_[put++] = 1.0e50; } } else { lower_[put] = -COIN_DBL_MAX; setInfeasible(put, true); cost_[put++] = cost[iSequence] - infeasibilityCost; whichRange_[iSequence] = put; lower_[put] = lower[iSequence]; cost_[put++] = cost[iSequence]; lower_[put] = upper[iSequence]; cost_[put++] = cost[iSequence] + infeasibilityCost; lower_[put] = COIN_DBL_MAX; setInfeasible(put - 1, true); cost_[put++] = 1.0e50; } start_[iSequence+1] = put; } for (; iSequence < numberTotal; iSequence++) { lower_[put] = -COIN_DBL_MAX; setInfeasible(put, true); put++; whichRange_[iSequence] = put; lower_[put] = 0.0; cost_[put++] = 0.0; lower_[put] = 0.0; cost_[put++] = 0.0; lower_[put] = COIN_DBL_MAX; setInfeasible(put - 1, true); cost_[put++] = 1.0e50; start_[iSequence+1] = put; } assert (put <= kPut); } #ifdef FAST_CLPNON // See how we are storing things CoinAssert (model_->clpMatrix()-> generalExpanded(model_, 10, iSequence) == 0); #endif if (CLP_METHOD2) { assert (!numberExtra); bound_ = new double[numberTotal]; cost2_ = new double[numberTotal]; status_ = new unsigned char[numberTotal]; #ifdef VALIDATE delete [] saveLowerV; saveLowerV = CoinCopyOfArray(model_->lowerRegion(), numberTotal); delete [] saveUpperV; saveUpperV = CoinCopyOfArray(model_->upperRegion(), numberTotal); #endif for (iSequence = 0; iSequence < numberTotal; iSequence++) { bound_[iSequence] = 0.0; cost2_[iSequence] = cost[iSequence]; setInitialStatus(status_[iSequence]); } } } // Refresh - assuming regions OK void ClpNonLinearCost::refresh() { int numberTotal = numberRows_ + numberColumns_; numberInfeasibilities_ = 0; sumInfeasibilities_ = 0.0; largestInfeasibility_ = 0.0; double infeasibilityCost = model_->infeasibilityCost(); double primalTolerance = model_->currentPrimalTolerance(); double * cost = model_->costRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * solution = model_->solutionRegion(); for (int iSequence = 0; iSequence < numberTotal; iSequence++) { cost2_[iSequence] = cost[iSequence]; double value = solution[iSequence]; double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible status_[iSequence] = static_cast(CLP_FEASIBLE | (CLP_SAME << 4)); bound_[iSequence] = 0.0; } else { // below double infeasibility = lowerValue - value - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); cost[iSequence] -= infeasibilityCost; numberInfeasibilities_++; status_[iSequence] = static_cast(CLP_BELOW_LOWER | (CLP_SAME << 4)); bound_[iSequence] = upperValue; upper[iSequence] = lowerValue; lower[iSequence] = -COIN_DBL_MAX; } } else { // above double infeasibility = value - upperValue - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); cost[iSequence] += infeasibilityCost; numberInfeasibilities_++; status_[iSequence] = static_cast(CLP_ABOVE_UPPER | (CLP_SAME << 4)); bound_[iSequence] = lowerValue; lower[iSequence] = upperValue; upper[iSequence] = COIN_DBL_MAX; } } // checkInfeasibilities(model_->primalTolerance()); } // Refreshes costs always makes row costs zero void ClpNonLinearCost::refreshCosts(const double * columnCosts) { double * cost = model_->costRegion(); // zero row costs memset(cost + numberColumns_, 0, numberRows_ * sizeof(double)); // copy column costs CoinMemcpyN(columnCosts, numberColumns_, cost); if ((method_ & 1) != 0) { for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { int start = start_[iSequence]; int end = start_[iSequence+1] - 1; double thisFeasibleCost = cost[iSequence]; if (infeasible(start)) { cost_[start] = thisFeasibleCost - infeasibilityWeight_; cost_[start+1] = thisFeasibleCost; } else { cost_[start] = thisFeasibleCost; } if (infeasible(end - 1)) { cost_[end-1] = thisFeasibleCost + infeasibilityWeight_; } } } if (CLP_METHOD2) { for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { cost2_[iSequence] = cost[iSequence]; } } } ClpNonLinearCost::ClpNonLinearCost(ClpSimplex * model, const int * starts, const double * lowerNon, const double * costNon) { #ifndef FAST_CLPNON // what about scaling? - only try without it initially assert(!model->scalingFlag()); model_ = model; numberRows_ = model_->numberRows(); numberColumns_ = model_->numberColumns(); int numberTotal = numberRows_ + numberColumns_; convex_ = true; bothWays_ = true; start_ = new int [numberTotal+1]; whichRange_ = new int [numberTotal]; offset_ = new int [numberTotal]; memset(offset_, 0, numberTotal * sizeof(int)); double whichWay = model_->optimizationDirection(); COIN_DETAIL_PRINT(printf("Direction %g\n", whichWay)); numberInfeasibilities_ = 0; changeCost_ = 0.0; feasibleCost_ = 0.0; double infeasibilityCost = model_->infeasibilityCost(); infeasibilityWeight_ = infeasibilityCost;; largestInfeasibility_ = 0.0; sumInfeasibilities_ = 0.0; int iSequence; assert (!model_->rowObjective()); double * cost = model_->objective(); // First see how much space we need // Also set up feasible bounds int put = starts[numberColumns_]; double * columnUpper = model_->columnUpper(); double * columnLower = model_->columnLower(); for (iSequence = 0; iSequence < numberColumns_; iSequence++) { if (columnLower[iSequence] > -1.0e20) put++; if (columnUpper[iSequence] < 1.0e20) put++; } double * rowUpper = model_->rowUpper(); double * rowLower = model_->rowLower(); for (iSequence = 0; iSequence < numberRows_; iSequence++) { if (rowLower[iSequence] > -1.0e20) put++; if (rowUpper[iSequence] < 1.0e20) put++; put += 2; } lower_ = new double [put]; cost_ = new double [put]; infeasible_ = new unsigned int[(put+31)>>5]; memset(infeasible_, 0, ((put + 31) >> 5)*sizeof(unsigned int)); // now fill in put = 0; start_[0] = 0; for (iSequence = 0; iSequence < numberTotal; iSequence++) { lower_[put] = -COIN_DBL_MAX; whichRange_[iSequence] = put + 1; double thisCost; double lowerValue; double upperValue; if (iSequence >= numberColumns_) { // rows lowerValue = rowLower[iSequence-numberColumns_]; upperValue = rowUpper[iSequence-numberColumns_]; if (lowerValue > -1.0e30) { setInfeasible(put, true); cost_[put++] = -infeasibilityCost; lower_[put] = lowerValue; } cost_[put++] = 0.0; thisCost = 0.0; } else { // columns - move costs and see if convex lowerValue = columnLower[iSequence]; upperValue = columnUpper[iSequence]; if (lowerValue > -1.0e30) { setInfeasible(put, true); cost_[put++] = whichWay * cost[iSequence] - infeasibilityCost; lower_[put] = lowerValue; } int iIndex = starts[iSequence]; int end = starts[iSequence+1]; assert (fabs(columnLower[iSequence] - lowerNon[iIndex]) < 1.0e-8); thisCost = -COIN_DBL_MAX; for (; iIndex < end; iIndex++) { if (lowerNon[iIndex] < columnUpper[iSequence] - 1.0e-8) { lower_[put] = lowerNon[iIndex]; cost_[put++] = whichWay * costNon[iIndex]; // check convexity if (whichWay * costNon[iIndex] < thisCost - 1.0e-12) convex_ = false; thisCost = whichWay * costNon[iIndex]; } else { break; } } } lower_[put] = upperValue; setInfeasible(put, true); cost_[put++] = thisCost + infeasibilityCost; if (upperValue < 1.0e20) { lower_[put] = COIN_DBL_MAX; cost_[put++] = 1.0e50; } int iFirst = start_[iSequence]; if (lower_[iFirst] != -COIN_DBL_MAX) { setInfeasible(iFirst, true); whichRange_[iSequence] = iFirst + 1; } else { whichRange_[iSequence] = iFirst; } start_[iSequence+1] = put; } // can't handle non-convex at present assert(convex_); status_ = NULL; bound_ = NULL; cost2_ = NULL; method_ = 1; #else printf("recompile ClpNonLinearCost without FAST_CLPNON\n"); abort(); #endif } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNonLinearCost::ClpNonLinearCost (const ClpNonLinearCost & rhs) : changeCost_(0.0), feasibleCost_(0.0), infeasibilityWeight_(-1.0), largestInfeasibility_(0.0), sumInfeasibilities_(0.0), averageTheta_(0.0), numberRows_(rhs.numberRows_), numberColumns_(rhs.numberColumns_), start_(NULL), whichRange_(NULL), offset_(NULL), lower_(NULL), cost_(NULL), model_(NULL), infeasible_(NULL), numberInfeasibilities_(-1), status_(NULL), bound_(NULL), cost2_(NULL), method_(rhs.method_), convex_(true), bothWays_(rhs.bothWays_) { if (numberRows_) { int numberTotal = numberRows_ + numberColumns_; model_ = rhs.model_; numberInfeasibilities_ = rhs.numberInfeasibilities_; changeCost_ = rhs.changeCost_; feasibleCost_ = rhs.feasibleCost_; infeasibilityWeight_ = rhs.infeasibilityWeight_; largestInfeasibility_ = rhs.largestInfeasibility_; sumInfeasibilities_ = rhs.sumInfeasibilities_; averageTheta_ = rhs.averageTheta_; convex_ = rhs.convex_; if (CLP_METHOD1) { start_ = new int [numberTotal+1]; CoinMemcpyN(rhs.start_, (numberTotal + 1), start_); whichRange_ = new int [numberTotal]; CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_); offset_ = new int [numberTotal]; CoinMemcpyN(rhs.offset_, numberTotal, offset_); int numberEntries = start_[numberTotal]; lower_ = new double [numberEntries]; CoinMemcpyN(rhs.lower_, numberEntries, lower_); cost_ = new double [numberEntries]; CoinMemcpyN(rhs.cost_, numberEntries, cost_); infeasible_ = new unsigned int[(numberEntries+31)>>5]; CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_); } if (CLP_METHOD2) { bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal); status_ = CoinCopyOfArray(rhs.status_, numberTotal); } } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNonLinearCost::~ClpNonLinearCost () { delete [] start_; delete [] whichRange_; delete [] offset_; delete [] lower_; delete [] cost_; delete [] infeasible_; delete [] status_; delete [] bound_; delete [] cost2_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNonLinearCost & ClpNonLinearCost::operator=(const ClpNonLinearCost& rhs) { if (this != &rhs) { numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; delete [] start_; delete [] whichRange_; delete [] offset_; delete [] lower_; delete [] cost_; delete [] infeasible_; delete [] status_; delete [] bound_; delete [] cost2_; start_ = NULL; whichRange_ = NULL; lower_ = NULL; cost_ = NULL; infeasible_ = NULL; status_ = NULL; bound_ = NULL; cost2_ = NULL; method_ = rhs.method_; if (numberRows_) { int numberTotal = numberRows_ + numberColumns_; if (CLP_METHOD1) { start_ = new int [numberTotal+1]; CoinMemcpyN(rhs.start_, (numberTotal + 1), start_); whichRange_ = new int [numberTotal]; CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_); offset_ = new int [numberTotal]; CoinMemcpyN(rhs.offset_, numberTotal, offset_); int numberEntries = start_[numberTotal]; lower_ = new double [numberEntries]; CoinMemcpyN(rhs.lower_, numberEntries, lower_); cost_ = new double [numberEntries]; CoinMemcpyN(rhs.cost_, numberEntries, cost_); infeasible_ = new unsigned int[(numberEntries+31)>>5]; CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_); } if (CLP_METHOD2) { bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal); status_ = CoinCopyOfArray(rhs.status_, numberTotal); } } model_ = rhs.model_; numberInfeasibilities_ = rhs.numberInfeasibilities_; changeCost_ = rhs.changeCost_; feasibleCost_ = rhs.feasibleCost_; infeasibilityWeight_ = rhs.infeasibilityWeight_; largestInfeasibility_ = rhs.largestInfeasibility_; sumInfeasibilities_ = rhs.sumInfeasibilities_; averageTheta_ = rhs.averageTheta_; convex_ = rhs.convex_; bothWays_ = rhs.bothWays_; } return *this; } // Changes infeasible costs and computes number and cost of infeas // We will need to re-think objective offsets later // We will also need a 2 bit per variable array for some // purpose which will come to me later void ClpNonLinearCost::checkInfeasibilities(double oldTolerance) { numberInfeasibilities_ = 0; double infeasibilityCost = model_->infeasibilityCost(); changeCost_ = 0.0; largestInfeasibility_ = 0.0; sumInfeasibilities_ = 0.0; double primalTolerance = model_->currentPrimalTolerance(); int iSequence; double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); bool toNearest = oldTolerance <= 0.0; feasibleCost_ = 0.0; //bool checkCosts = (infeasibilityWeight_ != infeasibilityCost); infeasibilityWeight_ = infeasibilityCost; int numberTotal = numberColumns_ + numberRows_; //#define NONLIN_DEBUG #ifdef NONLIN_DEBUG double * saveSolution = NULL; double * saveLower = NULL; double * saveUpper = NULL; unsigned char * saveStatus = NULL; if (method_ == 3) { // Save solution as we will be checking saveSolution = CoinCopyOfArray(solution, numberTotal); saveLower = CoinCopyOfArray(lower, numberTotal); saveUpper = CoinCopyOfArray(upper, numberTotal); saveStatus = CoinCopyOfArray(model_->statusArray(), numberTotal); } #else assert (method_ != 3); #endif if (CLP_METHOD1) { // nonbasic should be at a valid bound for (iSequence = 0; iSequence < numberTotal; iSequence++) { double lowerValue; double upperValue; double value = solution[iSequence]; int iRange; // get correct place int start = start_[iSequence]; int end = start_[iSequence+1] - 1; // correct costs for this infeasibility weight // If free then true cost will be first double thisFeasibleCost = cost_[start]; if (infeasible(start)) { thisFeasibleCost = cost_[start+1]; cost_[start] = thisFeasibleCost - infeasibilityCost; } if (infeasible(end - 1)) { thisFeasibleCost = cost_[end-2]; cost_[end-1] = thisFeasibleCost + infeasibilityCost; } for (iRange = start; iRange < end; iRange++) { if (value < lower_[iRange+1] + primalTolerance) { // put in better range if infeasible if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; whichRange_[iSequence] = iRange; break; } } assert(iRange < end); lowerValue = lower_[iRange]; upperValue = lower_[iRange+1]; ClpSimplex::Status status = model_->getStatus(iSequence); if (upperValue == lowerValue && status != ClpSimplex::isFixed) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence, ClpSimplex::isFixed); status = ClpSimplex::isFixed; } } //#define PRINT_DETAIL7 2 #if PRINT_DETAIL7>1 printf("NL %d sol %g bounds %g %g\n", iSequence,solution[iSequence], lowerValue,upperValue); #endif switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: // iRange is in correct place // slot in here if (infeasible(iRange)) { if (lower_[iRange] < -1.0e50) { //cost_[iRange] = cost_[iRange+1]-infeasibilityCost; // possibly below lowerValue = lower_[iRange+1]; if (value - lowerValue < -primalTolerance) { value = lowerValue - value - primalTolerance; #ifndef NDEBUG if(value > 1.0e15) printf("nonlincostb %d %g %g %g\n", iSequence, lowerValue, solution[iSequence], lower_[iRange+2]); #endif #if PRINT_DETAIL7 printf("**NL %d sol %g below %g\n", iSequence,solution[iSequence], lowerValue); #endif sumInfeasibilities_ += value; largestInfeasibility_ = CoinMax(largestInfeasibility_, value); changeCost_ -= lowerValue * (cost_[iRange] - cost[iSequence]); numberInfeasibilities_++; } } else { //cost_[iRange] = cost_[iRange-1]+infeasibilityCost; // possibly above upperValue = lower_[iRange]; if (value - upperValue > primalTolerance) { value = value - upperValue - primalTolerance; #ifndef NDEBUG if(value > 1.0e15) printf("nonlincostu %d %g %g %g\n", iSequence, lower_[iRange-1], solution[iSequence], upperValue); #endif #if PRINT_DETAIL7 printf("**NL %d sol %g above %g\n", iSequence,solution[iSequence], upperValue); #endif sumInfeasibilities_ += value; largestInfeasibility_ = CoinMax(largestInfeasibility_, value); changeCost_ -= upperValue * (cost_[iRange] - cost[iSequence]); numberInfeasibilities_++; } } } //lower[iSequence] = lower_[iRange]; //upper[iSequence] = lower_[iRange+1]; //cost[iSequence] = cost_[iRange]; break; case ClpSimplex::isFree: //if (toNearest) //solution[iSequence] = 0.0; break; case ClpSimplex::atUpperBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value - upperValue) > oldTolerance * 1.0001) { if (fabs(value - lowerValue) <= oldTolerance * 1.0001) { if (fabs(value - lowerValue) > primalTolerance) solution[iSequence] = lowerValue; model_->setStatus(iSequence, ClpSimplex::atLowerBound); } else { model_->setStatus(iSequence, ClpSimplex::superBasic); } } else if (fabs(value - upperValue) > primalTolerance) { solution[iSequence] = upperValue; } } else { // Set to nearest and make at upper bound int kRange; iRange = -1; double nearest = COIN_DBL_MAX; for (kRange = start; kRange < end; kRange++) { if (fabs(lower_[kRange] - value) < nearest) { nearest = fabs(lower_[kRange] - value); iRange = kRange; } } assert (iRange >= 0); iRange--; whichRange_[iSequence] = iRange; solution[iSequence] = lower_[iRange+1]; } break; case ClpSimplex::atLowerBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place // below stops compiler error with gcc 3.2!!! if (iSequence == -119) printf("ZZ %g %g %g %g\n", lowerValue, value, upperValue, oldTolerance); if (fabs(value - lowerValue) > oldTolerance * 1.0001) { if (fabs(value - upperValue) <= oldTolerance * 1.0001) { if (fabs(value - upperValue) > primalTolerance) solution[iSequence] = upperValue; model_->setStatus(iSequence, ClpSimplex::atUpperBound); } else { model_->setStatus(iSequence, ClpSimplex::superBasic); } } else if (fabs(value - lowerValue) > primalTolerance) { solution[iSequence] = lowerValue; } } else { // Set to nearest and make at lower bound int kRange; iRange = -1; double nearest = COIN_DBL_MAX; for (kRange = start; kRange < end; kRange++) { if (fabs(lower_[kRange] - value) < nearest) { nearest = fabs(lower_[kRange] - value); iRange = kRange; } } assert (iRange >= 0); whichRange_[iSequence] = iRange; solution[iSequence] = lower_[iRange]; } break; case ClpSimplex::isFixed: if (toNearest) { // Set to true fixed for (iRange = start; iRange < end; iRange++) { if (lower_[iRange] == lower_[iRange+1]) break; } if (iRange == end) { // Odd - but make sensible // Set to nearest and make at lower bound int kRange; iRange = -1; double nearest = COIN_DBL_MAX; for (kRange = start; kRange < end; kRange++) { if (fabs(lower_[kRange] - value) < nearest) { nearest = fabs(lower_[kRange] - value); iRange = kRange; } } assert (iRange >= 0); whichRange_[iSequence] = iRange; if (lower_[iRange] != lower_[iRange+1]) model_->setStatus(iSequence, ClpSimplex::atLowerBound); else model_->setStatus(iSequence, ClpSimplex::atUpperBound); } solution[iSequence] = lower_[iRange]; } break; } lower[iSequence] = lower_[iRange]; upper[iSequence] = lower_[iRange+1]; cost[iSequence] = cost_[iRange]; feasibleCost_ += thisFeasibleCost * solution[iSequence]; //assert (iRange==whichRange_[iSequence]); } } #ifdef NONLIN_DEBUG double saveCost = feasibleCost_; if (method_ == 3) { feasibleCost_ = 0.0; // Put back solution as we will be checking unsigned char * statusA = model_->statusArray(); for (iSequence = 0; iSequence < numberTotal; iSequence++) { double value = solution[iSequence]; solution[iSequence] = saveSolution[iSequence]; saveSolution[iSequence] = value; value = lower[iSequence]; lower[iSequence] = saveLower[iSequence]; saveLower[iSequence] = value; value = upper[iSequence]; upper[iSequence] = saveUpper[iSequence]; saveUpper[iSequence] = value; unsigned char value2 = statusA[iSequence]; statusA[iSequence] = saveStatus[iSequence]; saveStatus[iSequence] = value2; } } #endif if (CLP_METHOD2) { //#define CLP_NON_JUST_BASIC #ifndef CLP_NON_JUST_BASIC // nonbasic should be at a valid bound for (iSequence = 0; iSequence < numberTotal; iSequence++) { #else const int * pivotVariable = model_->pivotVariable(); for (int i=0;igetStatus(iSequence); if (upperValue == lowerValue && status != ClpSimplex::isFixed) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence, ClpSimplex::isFixed); status = ClpSimplex::isFixed; } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; assert (fabs(lowerValue) < 1.0e100); double infeasibility = lowerValue - value - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); costValue = trueCost - infeasibilityCost; changeCost_ -= lowerValue * (costValue - cost[iSequence]); numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; double infeasibility = value - upperValue - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); costValue = trueCost + infeasibilityCost; changeCost_ -= upperValue * (costValue - cost[iSequence]); numberInfeasibilities_++; } break; case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value - upperValue) > oldTolerance * 1.0001) { if (fabs(value - lowerValue) <= oldTolerance * 1.0001) { if (fabs(value - lowerValue) > primalTolerance) { solution[iSequence] = lowerValue; value = lowerValue; } model_->setStatus(iSequence, ClpSimplex::atLowerBound); } else { if (value < upperValue) { if (value > lowerValue) { model_->setStatus(iSequence, ClpSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence] = lowerValue; value = lowerValue; model_->setStatus(iSequence, ClpSimplex::atLowerBound); } } else { // set to upper bound as infeasible solution[iSequence] = upperValue; value = upperValue; } } } else if (fabs(value - upperValue) > primalTolerance) { solution[iSequence] = upperValue; value = upperValue; } } else { // Set to nearest and make at bound if (fabs(value - lowerValue) < fabs(value - upperValue)) { solution[iSequence] = lowerValue; value = lowerValue; model_->setStatus(iSequence, ClpSimplex::atLowerBound); } else { solution[iSequence] = upperValue; value = upperValue; } } break; case ClpSimplex::atLowerBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value - lowerValue) > oldTolerance * 1.0001) { if (fabs(value - upperValue) <= oldTolerance * 1.0001) { if (fabs(value - upperValue) > primalTolerance) { solution[iSequence] = upperValue; value = upperValue; } model_->setStatus(iSequence, ClpSimplex::atUpperBound); } else { if (value < upperValue) { if (value > lowerValue) { model_->setStatus(iSequence, ClpSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence] = lowerValue; value = lowerValue; } } else { // set to upper bound as infeasible solution[iSequence] = upperValue; value = upperValue; model_->setStatus(iSequence, ClpSimplex::atUpperBound); } } } else if (fabs(value - lowerValue) > primalTolerance) { solution[iSequence] = lowerValue; value = lowerValue; } } else { // Set to nearest and make at bound if (fabs(value - lowerValue) < fabs(value - upperValue)) { solution[iSequence] = lowerValue; value = lowerValue; } else { solution[iSequence] = upperValue; value = upperValue; model_->setStatus(iSequence, ClpSimplex::atUpperBound); } } break; case ClpSimplex::isFixed: solution[iSequence] = lowerValue; value = lowerValue; break; } #ifdef NONLIN_DEBUG double lo = saveLower[iSequence]; double up = saveUpper[iSequence]; double cc = cost[iSequence]; unsigned char ss = saveStatus[iSequence]; unsigned char snow = model_->statusArray()[iSequence]; #endif if (iWhere != newWhere) { setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; costValue = trueCost - infeasibilityCost; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; costValue = trueCost + infeasibilityCost; } else { costValue = trueCost; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } // always do as other things may change cost[iSequence] = costValue; #ifdef NONLIN_DEBUG if (method_ == 3) { assert (ss == snow); assert (cc == cost[iSequence]); assert (lo == lower[iSequence]); assert (up == upper[iSequence]); assert (value == saveSolution[iSequence]); } #endif feasibleCost_ += trueCost * value; } } #ifdef NONLIN_DEBUG if (method_ == 3) assert (fabs(saveCost - feasibleCost_) < 0.001 * (1.0 + CoinMax(fabs(saveCost), fabs(feasibleCost_)))); delete [] saveSolution; delete [] saveLower; delete [] saveUpper; delete [] saveStatus; #endif //feasibleCost_ /= (model_->rhsScale()*model_->objScale()); } // Puts feasible bounds into lower and upper void ClpNonLinearCost::feasibleBounds() { if (CLP_METHOD2) { int iSequence; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); int numberTotal = numberColumns_ + numberRows_; for (iSequence = 0; iSequence < numberTotal; iSequence++) { unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; } setOriginalStatus(status_[iSequence], CLP_FEASIBLE); lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } } /* Goes through one bound for each variable. If array[i]*multiplier>0 goes down, otherwise up. The indices are row indices and need converting to sequences */ void ClpNonLinearCost::goThru(int numberInArray, double multiplier, const int * index, const double * array, double * rhs) { assert (model_ != NULL); abort(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double alpha = multiplier * array[iRow]; // get where in bound sequence int iRange = whichRange_[iSequence]; iRange += offset_[iSequence]; //add temporary bias double value = model_->solution(iSequence); if (alpha > 0.0) { // down one iRange--; assert(iRange >= start_[iSequence]); rhs[iRow] = value - lower_[iRange]; } else { // up one iRange++; assert(iRange < start_[iSequence+1] - 1); rhs[iRow] = lower_[iRange+1] - value; } offset_[iSequence] = iRange - whichRange_[iSequence]; } } #ifdef NONLIN_DEBUG double * saveRhs = NULL; if (method_ == 3) { int numberRows = model_->numberRows(); saveRhs = CoinCopyOfArray(rhs, numberRows); } #endif if (CLP_METHOD2) { const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double alpha = multiplier * array[iRow]; double value = solution[iSequence]; unsigned char iStatus = status_[iSequence]; int iWhere = currentStatus(iStatus); if (iWhere == CLP_SAME) iWhere = originalStatus(iStatus); if (iWhere == CLP_FEASIBLE) { if (alpha > 0.0) { // going below iWhere = CLP_BELOW_LOWER; rhs[iRow] = value - lower[iSequence]; } else { // going above iWhere = CLP_ABOVE_UPPER; rhs[iRow] = upper[iSequence] - value; } } else if(iWhere == CLP_BELOW_LOWER) { assert (alpha < 0); // going feasible iWhere = CLP_FEASIBLE; rhs[iRow] = upper[iSequence] - value; } else { assert (iWhere == CLP_ABOVE_UPPER); // going feasible iWhere = CLP_FEASIBLE; rhs[iRow] = value - lower[iSequence]; } #ifdef NONLIN_DEBUG if (method_ == 3) assert (rhs[iRow] == saveRhs[iRow]); #endif setCurrentStatus(status_[iSequence], iWhere); } } #ifdef NONLIN_DEBUG delete [] saveRhs; #endif } /* Takes off last iteration (i.e. offsets closer to 0) */ void ClpNonLinearCost::goBack(int numberInArray, const int * index, double * rhs) { assert (model_ != NULL); abort(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; // get where in bound sequence int iRange = whichRange_[iSequence]; // get closer to original if (offset_[iSequence] > 0) { offset_[iSequence]--; assert (offset_[iSequence] >= 0); iRange += offset_[iSequence]; //add temporary bias double value = model_->solution(iSequence); // up one assert(iRange < start_[iSequence+1] - 1); rhs[iRow] = lower_[iRange+1] - value; // was earlier lower_[iRange] } else { offset_[iSequence]++; assert (offset_[iSequence] <= 0); iRange += offset_[iSequence]; //add temporary bias double value = model_->solution(iSequence); // down one assert(iRange >= start_[iSequence]); rhs[iRow] = value - lower_[iRange]; // was earlier lower_[iRange+1] } } } #ifdef NONLIN_DEBUG double * saveRhs = NULL; if (method_ == 3) { int numberRows = model_->numberRows(); saveRhs = CoinCopyOfArray(rhs, numberRows); } #endif if (CLP_METHOD2) { const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double value = solution[iSequence]; unsigned char iStatus = status_[iSequence]; int iWhere = currentStatus(iStatus); int original = originalStatus(iStatus); assert (iWhere != CLP_SAME); if (iWhere == CLP_FEASIBLE) { if (original == CLP_BELOW_LOWER) { // going below iWhere = CLP_BELOW_LOWER; rhs[iRow] = lower[iSequence] - value; } else { // going above iWhere = CLP_ABOVE_UPPER; rhs[iRow] = value - upper[iSequence]; } } else if(iWhere == CLP_BELOW_LOWER) { // going feasible iWhere = CLP_FEASIBLE; rhs[iRow] = value - upper[iSequence]; } else { // going feasible iWhere = CLP_FEASIBLE; rhs[iRow] = lower[iSequence] - value; } #ifdef NONLIN_DEBUG if (method_ == 3) assert (rhs[iRow] == saveRhs[iRow]); #endif setCurrentStatus(status_[iSequence], iWhere); } } #ifdef NONLIN_DEBUG delete [] saveRhs; #endif } void ClpNonLinearCost::goBackAll(const CoinIndexedVector * update) { assert (model_ != NULL); const int * pivotVariable = model_->pivotVariable(); int number = update->getNumElements(); const int * index = update->getIndices(); if (CLP_METHOD1) { for (int i = 0; i < number; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; offset_[iSequence] = 0; } #ifdef CLP_DEBUG for (i = 0; i < numberRows_ + numberColumns_; i++) assert(!offset_[i]); #endif } if (CLP_METHOD2) { for (int i = 0; i < number; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; setSameStatus(status_[iSequence]); } } } void ClpNonLinearCost::checkInfeasibilities(int numberInArray, const int * index) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; // get where in bound sequence int iRange; int currentRange = whichRange_[iSequence]; double value = model_->solution(iSequence); int start = start_[iSequence]; int end = start_[iSequence+1] - 1; for (iRange = start; iRange < end; iRange++) { if (value < lower_[iRange+1] + primalTolerance) { // put in better range if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; break; } } assert(iRange < end); assert(model_->getStatus(iSequence) == ClpSimplex::basic); double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); whichRange_[iSequence] = iRange; if (iRange != currentRange) { if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(currentRange)) numberInfeasibilities_--; } lower = lower_[iRange]; upper = lower_[iRange+1]; cost = cost_[iRange]; } } if (CLP_METHOD2) { double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double value = solution[iSequence]; unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; assert (fabs(lowerValue) < 1.0e100); costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } } } /* Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. On input array is empty (but indices exist). On exit just changed costs will be stored as normal CoinIndexedVector */ void ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); int number = 0; int * index = update->getIndices(); double * work = update->denseVector(); if (CLP_METHOD1) { for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; // get where in bound sequence int iRange; double value = model_->solution(iSequence); int start = start_[iSequence]; int end = start_[iSequence+1] - 1; for (iRange = start; iRange < end; iRange++) { if (value < lower_[iRange+1] + primalTolerance) { // put in better range if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; break; } } assert(iRange < end); assert(model_->getStatus(iSequence) == ClpSimplex::basic); int jRange = whichRange_[iSequence]; if (iRange != jRange) { // changed work[iRow] = cost_[jRange] - cost_[iRange]; index[number++] = iRow; double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); whichRange_[iSequence] = iRange; if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(jRange)) numberInfeasibilities_--; lower = lower_[iRange]; upper = lower_[iRange+1]; cost = cost_[iRange]; } } } if (CLP_METHOD2) { double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double value = solution[iSequence]; unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { work[iRow] = cost[iSequence] - costValue; index[number++] = iRow; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } } update->setNumElements(number); } /* Sets bounds and cost for one variable - returns change in cost*/ double ClpNonLinearCost::setOne(int iSequence, double value) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference = 0.0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int currentRange = whichRange_[iSequence]; int start = start_[iSequence]; int end = start_[iSequence+1] - 1; if (!bothWays_) { // If fixed try and get feasible if (lower_[start+1] == lower_[start+2] && fabs(value - lower_[start+1]) < 1.001 * primalTolerance) { iRange = start + 1; } else { for (iRange = start; iRange < end; iRange++) { if (value <= lower_[iRange+1] + primalTolerance) { // put in better range if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; break; } } } } else { // leave in current if possible iRange = whichRange_[iSequence]; if (value < lower_[iRange] - primalTolerance || value > lower_[iRange+1] + primalTolerance) { for (iRange = start; iRange < end; iRange++) { if (value < lower_[iRange+1] + primalTolerance) { // put in better range if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; break; } } } } assert(iRange < end); whichRange_[iSequence] = iRange; if (iRange != currentRange) { if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(currentRange)) numberInfeasibilities_--; } double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); lower = lower_[iRange]; upper = lower_[iRange+1]; ClpSimplex::Status status = model_->getStatus(iSequence); if (upper == lower) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence, ClpSimplex::isFixed); status = ClpSimplex::basic; // so will skip } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: case ClpSimplex::atLowerBound: case ClpSimplex::isFixed: // set correctly if (fabs(value - lower) <= primalTolerance * 1.001) { model_->setStatus(iSequence, ClpSimplex::atLowerBound); } else if (fabs(value - upper) <= primalTolerance * 1.001) { model_->setStatus(iSequence, ClpSimplex::atUpperBound); } else { // set superBasic model_->setStatus(iSequence, ClpSimplex::superBasic); } break; } difference = cost - cost_[iRange]; cost = cost_[iRange]; } if (CLP_METHOD2) { double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { difference = cost[iSequence] - costValue; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } ClpSimplex::Status status = model_->getStatus(iSequence); if (upperValue == lowerValue) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence, ClpSimplex::isFixed); status = ClpSimplex::basic; // so will skip } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: case ClpSimplex::atLowerBound: case ClpSimplex::isFixed: // set correctly if (fabs(value - lowerValue) <= primalTolerance * 1.001) { model_->setStatus(iSequence, ClpSimplex::atLowerBound); } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { model_->setStatus(iSequence, ClpSimplex::atUpperBound); } else { // set superBasic model_->setStatus(iSequence, ClpSimplex::superBasic); } break; } } changeCost_ += value * difference; return difference; } /* Sets bounds and infeasible cost and true cost for one variable This is for gub and column generation etc */ void ClpNonLinearCost::setOne(int sequence, double solutionValue, double lowerValue, double upperValue, double costValue) { if (CLP_METHOD1) { int iRange = -1; int start = start_[sequence]; double infeasibilityCost = model_->infeasibilityCost(); cost_[start] = costValue - infeasibilityCost; lower_[start+1] = lowerValue; cost_[start+1] = costValue; lower_[start+2] = upperValue; cost_[start+2] = costValue + infeasibilityCost; double primalTolerance = model_->currentPrimalTolerance(); if (solutionValue - lowerValue >= -primalTolerance) { if (solutionValue - upperValue <= primalTolerance) { iRange = start + 1; } else { iRange = start + 2; } } else { iRange = start; } model_->costRegion()[sequence] = cost_[iRange]; whichRange_[sequence] = iRange; } if (CLP_METHOD2) { bound_[sequence]=0.0; cost2_[sequence]=costValue; setInitialStatus(status_[sequence]); } } /* Sets bounds and cost for outgoing variable may change value Returns direction */ int ClpNonLinearCost::setOneOutgoing(int iSequence, double & value) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference = 0.0; int direction = 0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int currentRange = whichRange_[iSequence]; int start = start_[iSequence]; int end = start_[iSequence+1] - 1; // Set perceived direction out if (value <= lower_[currentRange] + 1.001 * primalTolerance) { direction = 1; } else if (value >= lower_[currentRange+1] - 1.001 * primalTolerance) { direction = -1; } else { // odd direction = 0; } // If fixed try and get feasible if (lower_[start+1] == lower_[start+2] && fabs(value - lower_[start+1]) < 1.001 * primalTolerance) { iRange = start + 1; } else { // See if exact for (iRange = start; iRange < end; iRange++) { if (value == lower_[iRange+1]) { // put in better range if (infeasible(iRange) && iRange == start) iRange++; break; } } if (iRange == end) { // not exact for (iRange = start; iRange < end; iRange++) { if (value <= lower_[iRange+1] + primalTolerance) { // put in better range if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) iRange++; break; } } } } assert(iRange < end); whichRange_[iSequence] = iRange; if (iRange != currentRange) { if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(currentRange)) numberInfeasibilities_--; } double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); lower = lower_[iRange]; upper = lower_[iRange+1]; if (upper == lower) { value = upper; } else { // set correctly if (fabs(value - lower) <= primalTolerance * 1.001) { value = CoinMin(value, lower + primalTolerance); } else if (fabs(value - upper) <= primalTolerance * 1.001) { value = CoinMax(value, upper - primalTolerance); } else { //printf("*** variable wandered off bound %g %g %g!\n", // lower,value,upper); if (value - lower <= upper - value) value = lower + primalTolerance; else value = upper - primalTolerance; } } difference = cost - cost_[iRange]; cost = cost_[iRange]; } if (CLP_METHOD2) { double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; // Set perceived direction out if (value <= lowerValue + 1.001 * primalTolerance) { direction = 1; } else if (value >= upperValue - 1.001 * primalTolerance) { direction = -1; } else { // odd direction = 0; } int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place // If fixed give benefit of doubt if (lowerValue == upperValue) value = lowerValue; int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { difference = cost[iSequence] - costValue; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upper[iSequence] = lowerValue; lower[iSequence] = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lower[iSequence] = upperValue; upper[iSequence] = COIN_DBL_MAX; } else { lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } cost[iSequence] = costValue; } // set correctly if (fabs(value - lowerValue) <= primalTolerance * 1.001) { value = CoinMin(value, lowerValue + primalTolerance); } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { value = CoinMax(value, upperValue - primalTolerance); } else { //printf("*** variable wandered off bound %g %g %g!\n", // lowerValue,value,upperValue); if (value - lowerValue <= upperValue - value) value = lowerValue + primalTolerance; else value = upperValue - primalTolerance; } } changeCost_ += value * difference; return direction; } // Returns nearest bound double ClpNonLinearCost::nearest(int iSequence, double solutionValue) { assert (model_ != NULL); double nearest = 0.0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int start = start_[iSequence]; int end = start_[iSequence+1]; int jRange = -1; nearest = COIN_DBL_MAX; for (iRange = start; iRange < end; iRange++) { if (fabs(solutionValue - lower_[iRange]) < nearest) { jRange = iRange; nearest = fabs(solutionValue - lower_[iRange]); } } assert(jRange < end); nearest = lower_[jRange]; } if (CLP_METHOD2) { const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; int iWhere = originalStatus(status_[iSequence]); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; } if (fabs(solutionValue - lowerValue) < fabs(solutionValue - upperValue)) nearest = lowerValue; else nearest = upperValue; } return nearest; } /// Feasible cost with offset and direction (i.e. for reporting) double ClpNonLinearCost::feasibleReportCost() const { double value; model_->getDblParam(ClpObjOffset, value); return (feasibleCost_ + model_->objectiveAsObject()->nonlinearOffset()) * model_->optimizationDirection() / (model_->objectiveScale() * model_->rhsScale()) - value; } // Get rid of real costs (just for moment) void ClpNonLinearCost::zapCosts() { int iSequence; double infeasibilityCost = model_->infeasibilityCost(); // zero out all costs int numberTotal = numberColumns_ + numberRows_; if (CLP_METHOD1) { int n = start_[numberTotal]; memset(cost_, 0, n * sizeof(double)); for (iSequence = 0; iSequence < numberTotal; iSequence++) { int start = start_[iSequence]; int end = start_[iSequence+1] - 1; // correct costs for this infeasibility weight if (infeasible(start)) { cost_[start] = -infeasibilityCost; } if (infeasible(end - 1)) { cost_[end-1] = infeasibilityCost; } } } if (CLP_METHOD2) { } } #ifdef VALIDATE // For debug void ClpNonLinearCost::validate() { double primalTolerance = model_->currentPrimalTolerance(); int iSequence; const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); const double * cost = model_->costRegion(); double infeasibilityCost = model_->infeasibilityCost(); int numberTotal = numberRows_ + numberColumns_; int numberInfeasibilities = 0; double sumInfeasibilities = 0.0; for (iSequence = 0; iSequence < numberTotal; iSequence++) { double value = solution[iSequence]; int iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); costValue -= infeasibilityCost; assert (value <= lowerValue - primalTolerance); numberInfeasibilities++; sumInfeasibilities += lowerValue - value - primalTolerance; assert (model_->getStatus(iSequence) == ClpSimplex::basic); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; costValue += infeasibilityCost; assert (value >= upperValue + primalTolerance); numberInfeasibilities++; sumInfeasibilities += value - upperValue - primalTolerance; assert (model_->getStatus(iSequence) == ClpSimplex::basic); } else { assert (value >= lowerValue - primalTolerance && value <= upperValue + primalTolerance); } assert (lowerValue == saveLowerV[iSequence]); assert (upperValue == saveUpperV[iSequence]); assert (costValue == cost[iSequence]); } if (numberInfeasibilities) printf("JJ %d infeasibilities summing to %g\n", numberInfeasibilities, sumInfeasibilities); } #endif Clp-1.15.10/src/ClpConstraint.cpp0000644000076600007660000000457011510657452015145 0ustar coincoin/* $Id: ClpConstraint.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpConstraint.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpConstraint::ClpConstraint () : lastGradient_(NULL), functionValue_(0.0), offset_(0.0), type_(-1), rowNumber_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpConstraint::ClpConstraint (const ClpConstraint & source) : lastGradient_(NULL), functionValue_(source.functionValue_), offset_(source.offset_), type_(source.type_), rowNumber_(source.rowNumber_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpConstraint::~ClpConstraint () { delete [] lastGradient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpConstraint & ClpConstraint::operator=(const ClpConstraint& rhs) { if (this != &rhs) { functionValue_ = rhs.functionValue_; offset_ = rhs.offset_; type_ = rhs.type_; rowNumber_ = rhs.rowNumber_; delete [] lastGradient_; lastGradient_ = NULL; } return *this; } // Constraint function value double ClpConstraint::functionValue (const ClpSimplex * model, const double * solution, bool useScaling, bool refresh) const { double offset; double value; int n = model->numberColumns(); double * grad = new double [n]; gradient(model, solution, grad, value, offset, useScaling, refresh); delete [] grad; return value; } Clp-1.15.10/src/ClpDualRowDantzig.cpp0000644000076600007660000001343011571121105015676 0ustar coincoin/* $Id: ClpDualRowDantzig.cpp 1732 2011-05-31 08:09: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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpFactorization.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #ifndef CLP_DUAL_COLUMN_MULTIPLIER #define CLP_DUAL_COLUMN_MULTIPLIER 1.01 #endif //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDualRowDantzig::ClpDualRowDantzig () : ClpDualRowPivot() { type_ = 1; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDualRowDantzig::ClpDualRowDantzig (const ClpDualRowDantzig & source) : ClpDualRowPivot(source) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDualRowDantzig::~ClpDualRowDantzig () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDualRowDantzig & ClpDualRowDantzig::operator=(const ClpDualRowDantzig& rhs) { if (this != &rhs) { ClpDualRowPivot::operator=(rhs); } return *this; } // Returns pivot row, -1 if none int ClpDualRowDantzig::pivotRow() { assert(model_); int iRow; const int * pivotVariable = model_->pivotVariable(); double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error if (model_->largestPrimalError() > 1.0e-8) tolerance *= model_->largestPrimalError() / 1.0e-8; double largest = 0.0; int chosenRow = -1; int numberRows = model_->numberRows(); #ifdef CLP_DUAL_COLUMN_MULTIPLIER int numberColumns = model_->numberColumns(); #endif for (iRow = 0; iRow < numberRows; iRow++) { int iSequence = pivotVariable[iRow]; double value = model_->solution(iSequence); double lower = model_->lower(iSequence); double upper = model_->upper(iSequence); double infeas = CoinMax(value - upper , lower - value); if (infeas > tolerance) { #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iSequence < numberColumns) infeas *= CLP_DUAL_COLUMN_MULTIPLIER; #endif if (infeas > largest) { if (!model_->flagged(iSequence)) { chosenRow = iRow; largest = infeas; } } } } return chosenRow; } // FT update and returns pivot alpha double ClpDualRowDantzig::updateWeights(CoinIndexedVector * /*input*/, CoinIndexedVector * spare, CoinIndexedVector * /*spare2*/, CoinIndexedVector * updatedColumn) { // Do FT update model_->factorization()->updateColumnFT(spare, updatedColumn); // pivot element double alpha = 0.0; // look at updated column double * work = updatedColumn->denseVector(); int number = updatedColumn->getNumElements(); int * which = updatedColumn->getIndices(); int i; int pivotRow = model_->pivotRow(); if (updatedColumn->packedMode()) { for (i = 0; i < number; i++) { int iRow = which[i]; if (iRow == pivotRow) { alpha = work[i]; break; } } } else { alpha = work[pivotRow]; } return alpha; } /* Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ void ClpDualRowDantzig::updatePrimalSolution(CoinIndexedVector * primalUpdate, double primalRatio, double & objectiveChange) { double * work = primalUpdate->denseVector(); int number = primalUpdate->getNumElements(); int * which = primalUpdate->getIndices(); int i; double changeObj = 0.0; const int * pivotVariable = model_->pivotVariable(); if (primalUpdate->packedMode()) { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; double & value = model_->solutionAddress(iPivot); double cost = model_->cost(iPivot); double change = primalRatio * work[i]; value -= change; changeObj -= change * cost; work[i] = 0.0; } } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; double & value = model_->solutionAddress(iPivot); double cost = model_->cost(iPivot); double change = primalRatio * work[iRow]; value -= change; changeObj -= change * cost; work[iRow] = 0.0; } } primalUpdate->setNumElements(0); objectiveChange += changeObj; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpDualRowPivot * ClpDualRowDantzig::clone(bool CopyData) const { if (CopyData) { return new ClpDualRowDantzig(*this); } else { return new ClpDualRowDantzig(); } } Clp-1.15.10/src/ClpCholeskyDense.cpp0000644000076600007660000017562412101105055015552 0ustar coincoin/* $Id: ClpCholeskyDense.cpp 1910 2013-01-27 02:00:13Z 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). */ #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "ClpConfig.h" #include "ClpHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpCholeskyDense.hpp" #include "ClpMessage.hpp" #include "ClpQuadraticObjective.hpp" #if CLP_HAS_ABC #include "CoinAbcCommon.hpp" #endif #if CLP_HAS_ABC<3 #undef cilk_for #undef cilk_spawn #undef cilk_sync #define cilk_for for #define cilk_spawn #define cilk_sync #endif /*#############################################################################*/ /* Constructors / Destructor / Assignment*/ /*#############################################################################*/ /*-------------------------------------------------------------------*/ /* Default Constructor */ /*-------------------------------------------------------------------*/ ClpCholeskyDense::ClpCholeskyDense () : ClpCholeskyBase(), borrowSpace_(false) { type_ = 11;; } /*-------------------------------------------------------------------*/ /* Copy constructor */ /*-------------------------------------------------------------------*/ ClpCholeskyDense::ClpCholeskyDense (const ClpCholeskyDense & rhs) : ClpCholeskyBase(rhs), borrowSpace_(rhs.borrowSpace_) { assert(!rhs.borrowSpace_ || !rhs.sizeFactor_); /* can't do if borrowing space*/ } /*-------------------------------------------------------------------*/ /* Destructor */ /*-------------------------------------------------------------------*/ ClpCholeskyDense::~ClpCholeskyDense () { if (borrowSpace_) { /* set NULL*/ sparseFactor_ = NULL; workDouble_ = NULL; diagonal_ = NULL; } } /*----------------------------------------------------------------*/ /* Assignment operator */ /*-------------------------------------------------------------------*/ ClpCholeskyDense & ClpCholeskyDense::operator=(const ClpCholeskyDense& rhs) { if (this != &rhs) { assert(!rhs.borrowSpace_ || !rhs.sizeFactor_); /* can't do if borrowing space*/ ClpCholeskyBase::operator=(rhs); borrowSpace_ = rhs.borrowSpace_; } return *this; } /*-------------------------------------------------------------------*/ /* Clone*/ /*-------------------------------------------------------------------*/ ClpCholeskyBase * ClpCholeskyDense::clone() const { return new ClpCholeskyDense(*this); } /* If not power of 2 then need to redo a bit*/ #define BLOCK 16 #define BLOCKSHIFT 4 /* Block unroll if power of 2 and at least 8*/ #define BLOCKUNROLL #define BLOCKSQ ( BLOCK*BLOCK ) #define BLOCKSQSHIFT ( BLOCKSHIFT+BLOCKSHIFT ) #define number_blocks(x) (((x)+BLOCK-1)>>BLOCKSHIFT) #define number_rows(x) ((x)<> BLOCKSHIFT; /* allow one stripe extra*/ numberBlocks = numberBlocks + ((numberBlocks * (numberBlocks + 1)) / 2); sizeFactor_ = numberBlocks * BLOCKSQ; /*#define CHOL_COMPARE*/ #ifdef CHOL_COMPARE sizeFactor_ += 95000; #endif if (!factor) { sparseFactor_ = new longDouble [sizeFactor_]; rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); workDouble_ = new longDouble[numberRows_]; diagonal_ = new longDouble[numberRows_]; } else { borrowSpace_ = true; int numberFull = factor->numberRows(); sparseFactor_ = factor->sparseFactor() + (factor->size() - sizeFactor_); workDouble_ = factor->workDouble() + (numberFull - numberRows_); diagonal_ = factor->diagonal() + (numberFull - numberRows_); } numberRowsDropped_ = 0; return 0; } /* Returns space needed */ CoinBigIndex ClpCholeskyDense::space( int numberRows) const { int numberBlocks = (numberRows + BLOCK - 1) >> BLOCKSHIFT; /* allow one stripe extra*/ numberBlocks = numberBlocks + ((numberBlocks * (numberBlocks + 1)) / 2); CoinBigIndex sizeFactor = numberBlocks * BLOCKSQ; #ifdef CHOL_COMPARE sizeFactor += 95000; #endif return sizeFactor; } /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyDense::order(ClpInterior * model) { model_ = model; int numberRows; int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); if (!doKKT_) { numberRows = numberRowsModel; } else { numberRows = 2 * numberRowsModel + numberColumns; } reserveSpace(NULL, numberRows); rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); return 0; } /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyDense::symbolic() { return 0; } /* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyDense::factorize(const CoinWorkDouble * diagonal, int * rowsDropped) { assert (!borrowSpace_); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); CoinZeroN(sparseFactor_, sizeFactor_); /*perturbation*/ CoinWorkDouble perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP /*if (model_->model()->logLevel()&4) */ std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = CoinSqrt(perturbation);; perturbation = 1.0; } int iRow; int newDropped = 0; CoinWorkDouble largest = 1.0; CoinWorkDouble smallest = COIN_DBL_MAX; CoinWorkDouble delta2 = model_->delta(); /* add delta*delta to diagonal*/ delta2 *= delta2; if (!doKKT_) { longDouble * work = sparseFactor_; work--; /* skip diagonal*/ int addOffset = numberRows_ - 1; const CoinWorkDouble * diagonalSlack = diagonal + numberColumns; /* largest in initial matrix*/ CoinWorkDouble largest2 = 1.0e-20; for (iRow = 0; iRow < numberRows_; iRow++) { if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; CoinWorkDouble diagonalValue = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; CoinWorkDouble multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (!rowsDropped_[jRow]) { if (jRow > iRow) { CoinWorkDouble value = element[j] * multiplier; work[jRow] += value; } else if (jRow == iRow) { CoinWorkDouble value = element[j] * multiplier; diagonalValue += value; } } } } for (int j = iRow + 1; j < numberRows_; j++) largest2 = CoinMax(largest2, CoinAbs(work[j])); diagonal_[iRow] = diagonalValue; largest2 = CoinMax(largest2, CoinAbs(diagonalValue)); } else { /* dropped*/ diagonal_[iRow] = 1.0; } addOffset--; work += addOffset; } /*check sizes*/ largest2 *= 1.0e-20; largest = CoinMin(largest2, CHOL_SMALL_VALUE); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; /* Move to int array*/ rowsDropped[iRow] = dropped; if (!dropped) { CoinWorkDouble diagonal = diagonal_[iRow]; if (diagonal > largest2) { diagonal_[iRow] = diagonal + perturbation; } else { diagonal_[iRow] = diagonal + perturbation; rowsDropped[iRow] = 2; numberDroppedBefore++; } } } doubleParameters_[10] = CoinMax(1.0e-20, largest); integerParameters_[20] = 0; doubleParameters_[3] = 0.0; doubleParameters_[4] = COIN_DBL_MAX; integerParameters_[34] = 0; /* say all must be positive*/ #ifdef CHOL_COMPARE if (numberRows_ < 200) factorizePart3(rowsDropped); #endif factorizePart2(rowsDropped); newDropped = integerParameters_[20] + numberDroppedBefore; largest = doubleParameters_[3]; smallest = doubleParameters_[4]; if (model_->messageHandler()->logLevel() > 1) std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl; choleskyCondition_ = largest / smallest; /*drop fresh makes some formADAT easier*/ if (newDropped || numberRowsDropped_) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = static_cast(rowsDropped[i]); rowsDropped_[i] = dropped; if (dropped == 2) { /*dropped this time*/ rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(2 + newDropped); } } else { /* KKT*/ CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); /* matrix*/ int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; longDouble * work = sparseFactor_; work--; /* skip diagonal*/ int addOffset = numberRows_ - 1; int iColumn; if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); diagonal_[iColumn] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { /*choleskyRow_[numberElements]=row[j]+numberTotal;*/ /*sparseFactor_[numberElements++]=element[j];*/ work[row[j] + numberTotal] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } } else { diagonal_[iColumn] = -value; } addOffset--; work += addOffset; } } else { /* Quadratic*/ const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinWorkDouble value = diagonal[iColumn]; CoinBigIndex j; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) { work[jColumn] = -quadraticElement[j]; } else if (iColumn == jColumn) { value += quadraticElement[j]; } } largest = CoinMax(largest, CoinAbs(value)); diagonal_[iColumn] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (j = start; j < end; j++) { work[row[j] + numberTotal] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } } else { value = 1.0e100; diagonal_[iColumn] = -value; } addOffset--; work += addOffset; } } /* slacks*/ for (iColumn = numberColumns; iColumn < numberTotal; iColumn++) { CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); } else { value = 1.0e100; } diagonal_[iColumn] = -value; work[iColumn-numberColumns+numberTotal] = -1.0; addOffset--; work += addOffset; } /* Finish diagonal*/ for (iRow = 0; iRow < numberRowsModel; iRow++) { diagonal_[iRow+numberTotal] = delta2; } /*check sizes*/ largest *= 1.0e-20; largest = CoinMin(largest, CHOL_SMALL_VALUE); doubleParameters_[10] = CoinMax(1.0e-20, largest); integerParameters_[20] = 0; doubleParameters_[3] = 0.0; doubleParameters_[4] = COIN_DBL_MAX; /* Set up LDL cutoff*/ integerParameters_[34] = numberTotal; /* KKT*/ int * rowsDropped2 = new int[numberRows_]; CoinZeroN(rowsDropped2, numberRows_); #ifdef CHOL_COMPARE if (numberRows_ < 200) factorizePart3(rowsDropped2); #endif factorizePart2(rowsDropped2); newDropped = integerParameters_[20]; largest = doubleParameters_[3]; smallest = doubleParameters_[4]; if (model_->messageHandler()->logLevel() > 1) COIN_DETAIL_PRINT(std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl); choleskyCondition_ = largest / smallest; /* Should save adjustments in ..R_*/ int n1 = 0, n2 = 0; CoinWorkDouble * primalR = model_->primalR(); CoinWorkDouble * dualR = model_->dualR(); for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped2[iRow]) { n1++; /*printf("row region1 %d dropped\n",iRow);*/ /*rowsDropped_[iRow]=1;*/ rowsDropped_[iRow] = 0; primalR[iRow] = doubleParameters_[20]; } else { rowsDropped_[iRow] = 0; primalR[iRow] = 0.0; } } for (; iRow < numberRows_; iRow++) { if (rowsDropped2[iRow]) { n2++; /*printf("row region2 %d dropped\n",iRow);*/ /*rowsDropped_[iRow]=1;*/ rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = doubleParameters_[34]; } else { rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = 0.0; } } } return 0; } /* Factorize - filling in rowsDropped and returning number dropped */ void ClpCholeskyDense::factorizePart3( int * rowsDropped) { int iColumn; longDouble * xx = sparseFactor_; longDouble * yy = diagonal_; diagonal_ = sparseFactor_ + 40000; sparseFactor_ = diagonal_ + numberRows_; /*memcpy(sparseFactor_,xx,sizeFactor_*sizeof(double));*/ CoinMemcpyN(xx, 40000, sparseFactor_); CoinMemcpyN(yy, numberRows_, diagonal_); int numberDropped = 0; CoinWorkDouble largest = 0.0; CoinWorkDouble smallest = COIN_DBL_MAX; double dropValue = doubleParameters_[10]; int firstPositive = integerParameters_[34]; longDouble * work = sparseFactor_; /* Allow for triangular*/ int addOffset = numberRows_ - 1; work--; for (iColumn = 0; iColumn < numberRows_; iColumn++) { int iRow; int addOffsetNow = numberRows_ - 1;; longDouble * workNow = sparseFactor_ - 1 + iColumn; CoinWorkDouble diagonalValue = diagonal_[iColumn]; for (iRow = 0; iRow < iColumn; iRow++) { double aj = *workNow; addOffsetNow--; workNow += addOffsetNow; diagonalValue -= aj * aj * workDouble_[iRow]; } bool dropColumn = false; if (iColumn < firstPositive) { /* must be negative*/ if (diagonalValue <= -dropValue) { smallest = CoinMin(smallest, -diagonalValue); largest = CoinMax(largest, -diagonalValue); workDouble_[iColumn] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { dropColumn = true; workDouble_[iColumn] = -1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } else { /* must be positive*/ if (diagonalValue >= dropValue) { smallest = CoinMin(smallest, diagonalValue); largest = CoinMax(largest, diagonalValue); workDouble_[iColumn] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { dropColumn = true; workDouble_[iColumn] = 1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } if (!dropColumn) { diagonal_[iColumn] = diagonalValue; for (iRow = iColumn + 1; iRow < numberRows_; iRow++) { double value = work[iRow]; workNow = sparseFactor_ - 1; int addOffsetNow = numberRows_ - 1;; for (int jColumn = 0; jColumn < iColumn; jColumn++) { double aj = workNow[iColumn]; double multiplier = workDouble_[jColumn]; double ai = workNow[iRow]; addOffsetNow--; workNow += addOffsetNow; value -= aj * ai * multiplier; } work[iRow] = value * diagonalValue; } } else { /* drop column*/ rowsDropped[iColumn] = 2; numberDropped++; diagonal_[iColumn] = 0.0; for (iRow = iColumn + 1; iRow < numberRows_; iRow++) { work[iRow] = 0.0; } } addOffset--; work += addOffset; } doubleParameters_[3] = largest; doubleParameters_[4] = smallest; integerParameters_[20] = numberDropped; sparseFactor_ = xx; diagonal_ = yy; } /*#define POS_DEBUG*/ #ifdef POS_DEBUG static int counter = 0; int ClpCholeskyDense::bNumber(const longDouble * array, int &iRow, int &iCol) { int numberBlocks = (numberRows_ + BLOCK - 1) >> BLOCKSHIFT; longDouble * a = sparseFactor_ + BLOCKSQ * numberBlocks; int k = array - a; assert ((k % BLOCKSQ) == 0); iCol = 0; int kk = k >> BLOCKSQSHIFT; /*printf("%d %d %d %d\n",k,kk,BLOCKSQ,BLOCKSQSHIFT);*/ k = kk; while (k >= numberBlocks) { iCol++; k -= numberBlocks; numberBlocks--; } iRow = iCol + k; counter++; if(counter > 100000) exit(77); return kk; } #endif /* Factorize - filling in rowsDropped and returning number dropped */ void ClpCholeskyDense::factorizePart2( int * rowsDropped) { int iColumn; /*longDouble * xx = sparseFactor_;*/ /*longDouble * yy = diagonal_;*/ /*diagonal_ = sparseFactor_ + 40000;*/ /*sparseFactor_=diagonal_ + numberRows_;*/ /*memcpy(sparseFactor_,xx,sizeFactor_*sizeof(double));*/ /*memcpy(sparseFactor_,xx,40000*sizeof(double));*/ /*memcpy(diagonal_,yy,numberRows_*sizeof(double));*/ int numberBlocks = (numberRows_ + BLOCK - 1) >> BLOCKSHIFT; /* later align on boundary*/ longDouble * a = sparseFactor_ + BLOCKSQ * numberBlocks; int n = numberRows_; int nRound = numberRows_ & (~(BLOCK - 1)); /* adjust if exact*/ if (nRound == n) nRound -= BLOCK; int sizeLastBlock = n - nRound; int get = n * (n - 1) / 2; /* ? as no diagonal*/ int block = numberBlocks * (numberBlocks + 1) / 2; int ifOdd; int rowLast; if (sizeLastBlock != BLOCK) { longDouble * aa = &a[(block-1)*BLOCKSQ]; rowLast = nRound - 1; ifOdd = 1; int put = BLOCKSQ; /* do last separately*/ put -= (BLOCK - sizeLastBlock) * (BLOCK + 1); for (iColumn = numberRows_ - 1; iColumn >= nRound; iColumn--) { int put2 = put; put -= BLOCK; for (int iRow = numberRows_ - 1; iRow > iColumn; iRow--) { aa[--put2] = sparseFactor_[--get]; assert (aa + put2 >= sparseFactor_ + get); } /* save diagonal as well*/ aa[--put2] = diagonal_[iColumn]; } n = nRound; block--; } else { /* exact fit*/ rowLast = numberRows_ - 1; ifOdd = 0; } /* Now main loop*/ int nBlock = 0; for (; n > 0; n -= BLOCK) { longDouble * aa = &a[(block-1)*BLOCKSQ]; longDouble * aaLast = NULL; int put = BLOCKSQ; int putLast = 0; /* see if we have small block*/ if (ifOdd) { aaLast = &a[(block-1)*BLOCKSQ]; aa = aaLast - BLOCKSQ; putLast = BLOCKSQ - BLOCK + sizeLastBlock; } for (iColumn = n - 1; iColumn >= n - BLOCK; iColumn--) { if (aaLast) { /* last bit*/ for (int iRow = numberRows_ - 1; iRow > rowLast; iRow--) { aaLast[--putLast] = sparseFactor_[--get]; assert (aaLast + putLast >= sparseFactor_ + get); } putLast -= BLOCK - sizeLastBlock; } longDouble * aPut = aa; int j = rowLast; for (int jBlock = 0; jBlock <= nBlock; jBlock++) { int put2 = put; int last = CoinMax(j - BLOCK, iColumn); for (int iRow = j; iRow > last; iRow--) { aPut[--put2] = sparseFactor_[--get]; assert (aPut + put2 >= sparseFactor_ + get); } if (j - BLOCK < iColumn) { /* save diagonal as well*/ aPut[--put2] = diagonal_[iColumn]; } j -= BLOCK; aPut -= BLOCKSQ; } put -= BLOCK; } nBlock++; block -= nBlock + ifOdd; } ClpCholeskyDenseC info; info.diagonal_ = diagonal_; info.doubleParameters_[0] = doubleParameters_[10]; info.integerParameters_[0] = integerParameters_[34]; #ifndef CLP_CILK ClpCholeskyCfactor(&info, a, numberRows_, numberBlocks, diagonal_, workDouble_, rowsDropped); #else info.a = a; info.n = numberRows_; info.numberBlocks = numberBlocks; info.work = workDouble_; info.rowsDropped = rowsDropped; info.integerParameters_[1] = model_->numberThreads(); ClpCholeskySpawn(&info); #endif double largest = 0.0; double smallest = COIN_DBL_MAX; int numberDropped = 0; for (int i = 0; i < numberRows_; i++) { if (diagonal_[i]) { largest = CoinMax(largest, CoinAbs(diagonal_[i])); smallest = CoinMin(smallest, CoinAbs(diagonal_[i])); } else { numberDropped++; } } doubleParameters_[3] = CoinMax(doubleParameters_[3], 1.0 / smallest); doubleParameters_[4] = CoinMin(doubleParameters_[4], 1.0 / largest); integerParameters_[20] += numberDropped; } /* Non leaf recursive factor*/ void ClpCholeskyCfactor(ClpCholeskyDenseC * thisStruct, longDouble * a, int n, int numberBlocks, longDouble * diagonal, longDouble * work, int * rowsDropped) { if (n <= BLOCK) { ClpCholeskyCfactorLeaf(thisStruct, a, n, diagonal, work, rowsDropped); } else { int nb = number_blocks((n + 1) >> 1); int nThis = number_rows(nb); longDouble * aother; int nLeft = n - nThis; int nintri = (nb * (nb + 1)) >> 1; int nbelow = (numberBlocks - nb) * nb; ClpCholeskyCfactor(thisStruct, a, nThis, numberBlocks, diagonal, work, rowsDropped); ClpCholeskyCtriRec(thisStruct, a, nThis, a + number_entries(nb), diagonal, work, nLeft, nb, 0, numberBlocks); aother = a + number_entries(nintri + nbelow); ClpCholeskyCrecTri(thisStruct, a + number_entries(nb), nLeft, nThis, nb, 0, aother, diagonal, work, numberBlocks); ClpCholeskyCfactor(thisStruct, aother, nLeft, numberBlocks - nb, diagonal + nThis, work + nThis, rowsDropped); } } /* Non leaf recursive triangle rectangle update*/ void ClpCholeskyCtriRec(ClpCholeskyDenseC * thisStruct, longDouble * aTri, int nThis, longDouble * aUnder, longDouble * diagonal, longDouble * work, int nLeft, int iBlock, int jBlock, int numberBlocks) { if (nThis <= BLOCK && nLeft <= BLOCK) { ClpCholeskyCtriRecLeaf(/*thisStruct,*/ aTri, aUnder, diagonal, work, nLeft); } else if (nThis < nLeft) { int nb = number_blocks((nLeft + 1) >> 1); int nLeft2 = number_rows(nb); cilk_spawn ClpCholeskyCtriRec(thisStruct, aTri, nThis, aUnder, diagonal, work, nLeft2, iBlock, jBlock, numberBlocks); ClpCholeskyCtriRec(thisStruct, aTri, nThis, aUnder + number_entries(nb), diagonal, work, nLeft - nLeft2, iBlock + nb, jBlock, numberBlocks); cilk_sync; } else { int nb = number_blocks((nThis + 1) >> 1); int nThis2 = number_rows(nb); longDouble * aother; int kBlock = jBlock + nb; int i; int nintri = (nb * (nb + 1)) >> 1; int nbelow = (numberBlocks - nb) * nb; ClpCholeskyCtriRec(thisStruct, aTri, nThis2, aUnder, diagonal, work, nLeft, iBlock, jBlock, numberBlocks); /* and rectangular update */ i = ((numberBlocks - jBlock) * (numberBlocks - jBlock - 1) - (numberBlocks - jBlock - nb) * (numberBlocks - jBlock - nb - 1)) >> 1; aother = aUnder + number_entries(i); ClpCholeskyCrecRec(thisStruct, aTri + number_entries(nb), nThis - nThis2, nLeft, nThis2, aUnder, aother, work, kBlock, jBlock, numberBlocks); ClpCholeskyCtriRec(thisStruct, aTri + number_entries(nintri + nbelow), nThis - nThis2, aother, diagonal + nThis2, work + nThis2, nLeft, iBlock - nb, kBlock - nb, numberBlocks - nb); } } /* Non leaf recursive rectangle triangle update*/ void ClpCholeskyCrecTri(ClpCholeskyDenseC * thisStruct, longDouble * aUnder, int nTri, int nDo, int iBlock, int jBlock, longDouble * aTri, longDouble * diagonal, longDouble * work, int numberBlocks) { if (nTri <= BLOCK && nDo <= BLOCK) { ClpCholeskyCrecTriLeaf(/*thisStruct,*/ aUnder, aTri,/*diagonal,*/work, nTri); } else if (nTri < nDo) { int nb = number_blocks((nDo + 1) >> 1); int nDo2 = number_rows(nb); longDouble * aother; int i; ClpCholeskyCrecTri(thisStruct, aUnder, nTri, nDo2, iBlock, jBlock, aTri, diagonal, work, numberBlocks); i = ((numberBlocks - jBlock) * (numberBlocks - jBlock - 1) - (numberBlocks - jBlock - nb) * (numberBlocks - jBlock - nb - 1)) >> 1; aother = aUnder + number_entries(i); ClpCholeskyCrecTri(thisStruct, aother, nTri, nDo - nDo2, iBlock - nb, jBlock, aTri, diagonal + nDo2, work + nDo2, numberBlocks - nb); } else { int nb = number_blocks((nTri + 1) >> 1); int nTri2 = number_rows(nb); longDouble * aother; int i; cilk_spawn ClpCholeskyCrecTri(thisStruct, aUnder, nTri2, nDo, iBlock, jBlock, aTri, diagonal, work, numberBlocks); /* and rectangular update */ i = ((numberBlocks - iBlock) * (numberBlocks - iBlock + 1) - (numberBlocks - iBlock - nb) * (numberBlocks - iBlock - nb + 1)) >> 1; aother = aTri + number_entries(nb); ClpCholeskyCrecRec(thisStruct, aUnder, nTri2, nTri - nTri2, nDo, aUnder + number_entries(nb), aother, work, iBlock, jBlock, numberBlocks); ClpCholeskyCrecTri(thisStruct, aUnder + number_entries(nb), nTri - nTri2, nDo, iBlock + nb, jBlock, aTri + number_entries(i), diagonal, work, numberBlocks); cilk_sync; } } /* Non leaf recursive rectangle rectangle update, nUnder is number of rows in iBlock, nUnderK is number of rows in kBlock */ void ClpCholeskyCrecRec(ClpCholeskyDenseC * thisStruct, longDouble * above, int nUnder, int nUnderK, int nDo, longDouble * aUnder, longDouble *aOther, longDouble * work, int iBlock, int jBlock, int numberBlocks) { if (nDo <= BLOCK && nUnder <= BLOCK && nUnderK <= BLOCK) { assert (nDo == BLOCK && nUnder == BLOCK); ClpCholeskyCrecRecLeaf(/*thisStruct,*/ above , aUnder , aOther, work, nUnderK); } else if (nDo <= nUnderK && nUnder <= nUnderK) { int nb = number_blocks((nUnderK + 1) >> 1); int nUnder2 = number_rows(nb); cilk_spawn ClpCholeskyCrecRec(thisStruct, above, nUnder, nUnder2, nDo, aUnder, aOther, work, iBlock, jBlock, numberBlocks); ClpCholeskyCrecRec(thisStruct, above, nUnder, nUnderK - nUnder2, nDo, aUnder + number_entries(nb), aOther + number_entries(nb), work, iBlock, jBlock, numberBlocks); cilk_sync; } else if (nUnderK <= nDo && nUnder <= nDo) { int nb = number_blocks((nDo + 1) >> 1); int nDo2 = number_rows(nb); int i; ClpCholeskyCrecRec(thisStruct, above, nUnder, nUnderK, nDo2, aUnder, aOther, work, iBlock, jBlock, numberBlocks); i = ((numberBlocks - jBlock) * (numberBlocks - jBlock - 1) - (numberBlocks - jBlock - nb) * (numberBlocks - jBlock - nb - 1)) >> 1; ClpCholeskyCrecRec(thisStruct, above + number_entries(i), nUnder, nUnderK, nDo - nDo2, aUnder + number_entries(i), aOther, work + nDo2, iBlock - nb, jBlock, numberBlocks - nb); } else { int nb = number_blocks((nUnder + 1) >> 1); int nUnder2 = number_rows(nb); int i; cilk_spawn ClpCholeskyCrecRec(thisStruct, above, nUnder2, nUnderK, nDo, aUnder, aOther, work, iBlock, jBlock, numberBlocks); i = ((numberBlocks - iBlock) * (numberBlocks - iBlock - 1) - (numberBlocks - iBlock - nb) * (numberBlocks - iBlock - nb - 1)) >> 1; ClpCholeskyCrecRec(thisStruct, above + number_entries(nb), nUnder - nUnder2, nUnderK, nDo, aUnder, aOther + number_entries(i), work, iBlock + nb, jBlock, numberBlocks); cilk_sync; } } /* Leaf recursive factor*/ void ClpCholeskyCfactorLeaf(ClpCholeskyDenseC * thisStruct, longDouble * a, int n, longDouble * diagonal, longDouble * work, int * rowsDropped) { double dropValue = thisStruct->doubleParameters_[0]; int firstPositive = thisStruct->integerParameters_[0]; int rowOffset = static_cast(diagonal - thisStruct->diagonal_); int i, j, k; CoinWorkDouble t00, temp1; longDouble * aa; aa = a - BLOCK; for (j = 0; j < n; j ++) { bool dropColumn; CoinWorkDouble useT00; aa += BLOCK; t00 = aa[j]; for (k = 0; k < j; ++k) { CoinWorkDouble multiplier = work[k]; t00 -= a[j + k * BLOCK] * a[j + k * BLOCK] * multiplier; } dropColumn = false; useT00 = t00; if (j + rowOffset < firstPositive) { /* must be negative*/ if (t00 <= -dropValue) { /*aa[j]=t00;*/ t00 = 1.0 / t00; } else { dropColumn = true; /*aa[j]=-1.0e100;*/ useT00 = -1.0e-100; t00 = 0.0; } } else { /* must be positive*/ if (t00 >= dropValue) { /*aa[j]=t00;*/ t00 = 1.0 / t00; } else { dropColumn = true; /*aa[j]=1.0e100;*/ useT00 = 1.0e-100; t00 = 0.0; } } if (!dropColumn) { diagonal[j] = t00; work[j] = useT00; temp1 = t00; for (i = j + 1; i < n; i++) { t00 = aa[i]; for (k = 0; k < j; ++k) { CoinWorkDouble multiplier = work[k]; t00 -= a[i + k * BLOCK] * a[j + k * BLOCK] * multiplier; } aa[i] = t00 * temp1; } } else { /* drop column*/ rowsDropped[j+rowOffset] = 2; diagonal[j] = 0.0; /*aa[j]=1.0e100;*/ work[j] = 1.0e100; for (i = j + 1; i < n; i++) { aa[i] = 0.0; } } } } /* Leaf recursive triangle rectangle update*/ void ClpCholeskyCtriRecLeaf(/*ClpCholeskyDenseC * thisStruct,*/ longDouble * aTri, longDouble * aUnder, longDouble * diagonal, longDouble * work, int nUnder) { #ifdef POS_DEBUG int iru, icu; int iu = bNumber(aUnder, iru, icu); int irt, ict; int it = bNumber(aTri, irt, ict); /*printf("%d %d\n",iu,it);*/ printf("trirecleaf under (%d,%d), tri (%d,%d)\n", iru, icu, irt, ict); assert (diagonal == thisStruct->diagonal_ + ict * BLOCK); #endif int j; longDouble * aa; #ifdef BLOCKUNROLL if (nUnder == BLOCK) { aa = aTri - 2 * BLOCK; for (j = 0; j < BLOCK; j += 2) { int i; CoinWorkDouble temp0 = diagonal[j]; CoinWorkDouble temp1 = diagonal[j+1]; aa += 2 * BLOCK; for ( i = 0; i < BLOCK; i += 2) { CoinWorkDouble at1; CoinWorkDouble t00 = aUnder[i+j*BLOCK]; CoinWorkDouble t10 = aUnder[i+ BLOCK + j*BLOCK]; CoinWorkDouble t01 = aUnder[i+1+j*BLOCK]; CoinWorkDouble t11 = aUnder[i+1+ BLOCK + j*BLOCK]; int k; for (k = 0; k < j; ++k) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble au0 = aUnder[i + k * BLOCK] * multiplier; CoinWorkDouble au1 = aUnder[i + 1 + k * BLOCK] * multiplier; CoinWorkDouble at0 = aTri[j + k * BLOCK]; CoinWorkDouble at1 = aTri[j + 1 + k * BLOCK]; t00 -= au0 * at0; t10 -= au0 * at1; t01 -= au1 * at0; t11 -= au1 * at1; } t00 *= temp0; at1 = aTri[j + 1 + j*BLOCK] * work[j]; t10 -= t00 * at1; t01 *= temp0; t11 -= t01 * at1; aUnder[i+j*BLOCK] = t00; aUnder[i+1+j*BLOCK] = t01; aUnder[i+ BLOCK + j*BLOCK] = t10 * temp1; aUnder[i+1+ BLOCK + j*BLOCK] = t11 * temp1; } } } else { #endif aa = aTri - BLOCK; for (j = 0; j < BLOCK; j ++) { int i; CoinWorkDouble temp1 = diagonal[j]; aa += BLOCK; for (i = 0; i < nUnder; i++) { int k; CoinWorkDouble t00 = aUnder[i+j*BLOCK]; for ( k = 0; k < j; ++k) { CoinWorkDouble multiplier = work[k]; t00 -= aUnder[i + k * BLOCK] * aTri[j + k * BLOCK] * multiplier; } aUnder[i+j*BLOCK] = t00 * temp1; } } #ifdef BLOCKUNROLL } #endif } /* Leaf recursive rectangle triangle update*/ void ClpCholeskyCrecTriLeaf(/*ClpCholeskyDenseC * thisStruct,*/ longDouble * aUnder, longDouble * aTri, /*longDouble * diagonal,*/ longDouble * work, int nUnder) { #ifdef POS_DEBUG int iru, icu; int iu = bNumber(aUnder, iru, icu); int irt, ict; int it = bNumber(aTri, irt, ict); /*printf("%d %d\n",iu,it);*/ printf("rectrileaf under (%d,%d), tri (%d,%d)\n", iru, icu, irt, ict); assert (diagonal == thisStruct->diagonal_ + icu * BLOCK); #endif int i, j, k; CoinWorkDouble t00; longDouble * aa; #ifdef BLOCKUNROLL if (nUnder == BLOCK) { longDouble * aUnder2 = aUnder - 2; aa = aTri - 2 * BLOCK; for (j = 0; j < BLOCK; j += 2) { CoinWorkDouble t00, t01, t10, t11; aa += 2 * BLOCK; aUnder2 += 2; t00 = aa[j]; t01 = aa[j+1]; t10 = aa[j+1+BLOCK]; for (k = 0; k < BLOCK; ++k) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble a0 = aUnder2[k * BLOCK]; CoinWorkDouble a1 = aUnder2[1 + k * BLOCK]; CoinWorkDouble x0 = a0 * multiplier; CoinWorkDouble x1 = a1 * multiplier; t00 -= a0 * x0; t01 -= a1 * x0; t10 -= a1 * x1; } aa[j] = t00; aa[j+1] = t01; aa[j+1+BLOCK] = t10; for (i = j + 2; i < BLOCK; i += 2) { t00 = aa[i]; t01 = aa[i+BLOCK]; t10 = aa[i+1]; t11 = aa[i+1+BLOCK]; for (k = 0; k < BLOCK; ++k) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble a0 = aUnder2[k * BLOCK] * multiplier; CoinWorkDouble a1 = aUnder2[1 + k * BLOCK] * multiplier; t00 -= aUnder[i + k * BLOCK] * a0; t01 -= aUnder[i + k * BLOCK] * a1; t10 -= aUnder[i + 1 + k * BLOCK] * a0; t11 -= aUnder[i + 1 + k * BLOCK] * a1; } aa[i] = t00; aa[i+BLOCK] = t01; aa[i+1] = t10; aa[i+1+BLOCK] = t11; } } } else { #endif aa = aTri - BLOCK; for (j = 0; j < nUnder; j ++) { aa += BLOCK; for (i = j; i < nUnder; i++) { t00 = aa[i]; for (k = 0; k < BLOCK; ++k) { CoinWorkDouble multiplier = work[k]; t00 -= aUnder[i + k * BLOCK] * aUnder[j + k * BLOCK] * multiplier; } aa[i] = t00; } } #ifdef BLOCKUNROLL } #endif } /* Leaf recursive rectangle rectangle update, nUnder is number of rows in iBlock, nUnderK is number of rows in kBlock */ void ClpCholeskyCrecRecLeaf(/*ClpCholeskyDenseC * thisStruct,*/ const longDouble * COIN_RESTRICT above, const longDouble * COIN_RESTRICT aUnder, longDouble * COIN_RESTRICT aOther, const longDouble * COIN_RESTRICT work, int nUnder) { #ifdef POS_DEBUG int ira, ica; int ia = bNumber(above, ira, ica); int iru, icu; int iu = bNumber(aUnder, iru, icu); int iro, ico; int io = bNumber(aOther, iro, ico); /*printf("%d %d %d\n",ia,iu,io);*/ printf("recrecleaf above (%d,%d), under (%d,%d), other (%d,%d)\n", ira, ica, iru, icu, iro, ico); #endif int i, j, k; longDouble * aa; #ifdef BLOCKUNROLL aa = aOther - 4 * BLOCK; if (nUnder == BLOCK) { /*#define INTEL*/ #ifdef INTEL aa += 2 * BLOCK; for (j = 0; j < BLOCK; j += 2) { aa += 2 * BLOCK; for (i = 0; i < BLOCK; i += 2) { CoinWorkDouble t00 = aa[i+0*BLOCK]; CoinWorkDouble t10 = aa[i+1*BLOCK]; CoinWorkDouble t01 = aa[i+1+0*BLOCK]; CoinWorkDouble t11 = aa[i+1+1*BLOCK]; for (k = 0; k < BLOCK; k++) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble a00 = aUnder[i+k*BLOCK] * multiplier; CoinWorkDouble a01 = aUnder[i+1+k*BLOCK] * multiplier; t00 -= a00 * above[j + 0 + k * BLOCK]; t10 -= a00 * above[j + 1 + k * BLOCK]; t01 -= a01 * above[j + 0 + k * BLOCK]; t11 -= a01 * above[j + 1 + k * BLOCK]; } aa[i+0*BLOCK] = t00; aa[i+1*BLOCK] = t10; aa[i+1+0*BLOCK] = t01; aa[i+1+1*BLOCK] = t11; } } #else for (j = 0; j < BLOCK; j += 4) { aa += 4 * BLOCK; for (i = 0; i < BLOCK; i += 4) { CoinWorkDouble t00 = aa[i+0+0*BLOCK]; CoinWorkDouble t10 = aa[i+0+1*BLOCK]; CoinWorkDouble t20 = aa[i+0+2*BLOCK]; CoinWorkDouble t30 = aa[i+0+3*BLOCK]; CoinWorkDouble t01 = aa[i+1+0*BLOCK]; CoinWorkDouble t11 = aa[i+1+1*BLOCK]; CoinWorkDouble t21 = aa[i+1+2*BLOCK]; CoinWorkDouble t31 = aa[i+1+3*BLOCK]; CoinWorkDouble t02 = aa[i+2+0*BLOCK]; CoinWorkDouble t12 = aa[i+2+1*BLOCK]; CoinWorkDouble t22 = aa[i+2+2*BLOCK]; CoinWorkDouble t32 = aa[i+2+3*BLOCK]; CoinWorkDouble t03 = aa[i+3+0*BLOCK]; CoinWorkDouble t13 = aa[i+3+1*BLOCK]; CoinWorkDouble t23 = aa[i+3+2*BLOCK]; CoinWorkDouble t33 = aa[i+3+3*BLOCK]; const longDouble * COIN_RESTRICT aUnderNow = aUnder + i; const longDouble * COIN_RESTRICT aboveNow = above + j; for (k = 0; k < BLOCK; k++) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble a00 = aUnderNow[0] * multiplier; CoinWorkDouble a01 = aUnderNow[1] * multiplier; CoinWorkDouble a02 = aUnderNow[2] * multiplier; CoinWorkDouble a03 = aUnderNow[3] * multiplier; t00 -= a00 * aboveNow[0]; t10 -= a00 * aboveNow[1]; t20 -= a00 * aboveNow[2]; t30 -= a00 * aboveNow[3]; t01 -= a01 * aboveNow[0]; t11 -= a01 * aboveNow[1]; t21 -= a01 * aboveNow[2]; t31 -= a01 * aboveNow[3]; t02 -= a02 * aboveNow[0]; t12 -= a02 * aboveNow[1]; t22 -= a02 * aboveNow[2]; t32 -= a02 * aboveNow[3]; t03 -= a03 * aboveNow[0]; t13 -= a03 * aboveNow[1]; t23 -= a03 * aboveNow[2]; t33 -= a03 * aboveNow[3]; aUnderNow += BLOCK; aboveNow += BLOCK; } aa[i+0+0*BLOCK] = t00; aa[i+0+1*BLOCK] = t10; aa[i+0+2*BLOCK] = t20; aa[i+0+3*BLOCK] = t30; aa[i+1+0*BLOCK] = t01; aa[i+1+1*BLOCK] = t11; aa[i+1+2*BLOCK] = t21; aa[i+1+3*BLOCK] = t31; aa[i+2+0*BLOCK] = t02; aa[i+2+1*BLOCK] = t12; aa[i+2+2*BLOCK] = t22; aa[i+2+3*BLOCK] = t32; aa[i+3+0*BLOCK] = t03; aa[i+3+1*BLOCK] = t13; aa[i+3+2*BLOCK] = t23; aa[i+3+3*BLOCK] = t33; } } #endif } else { int odd = nUnder & 1; int n = nUnder - odd; for (j = 0; j < BLOCK; j += 4) { aa += 4 * BLOCK; for (i = 0; i < n; i += 2) { CoinWorkDouble t00 = aa[i+0*BLOCK]; CoinWorkDouble t10 = aa[i+1*BLOCK]; CoinWorkDouble t20 = aa[i+2*BLOCK]; CoinWorkDouble t30 = aa[i+3*BLOCK]; CoinWorkDouble t01 = aa[i+1+0*BLOCK]; CoinWorkDouble t11 = aa[i+1+1*BLOCK]; CoinWorkDouble t21 = aa[i+1+2*BLOCK]; CoinWorkDouble t31 = aa[i+1+3*BLOCK]; const longDouble * COIN_RESTRICT aUnderNow = aUnder + i; const longDouble * COIN_RESTRICT aboveNow = above + j; for (k = 0; k < BLOCK; k++) { CoinWorkDouble multiplier = work[k]; CoinWorkDouble a00 = aUnderNow[0] * multiplier; CoinWorkDouble a01 = aUnderNow[1] * multiplier; t00 -= a00 * aboveNow[0]; t10 -= a00 * aboveNow[1]; t20 -= a00 * aboveNow[2]; t30 -= a00 * aboveNow[3]; t01 -= a01 * aboveNow[0]; t11 -= a01 * aboveNow[1]; t21 -= a01 * aboveNow[2]; t31 -= a01 * aboveNow[3]; aUnderNow += BLOCK; aboveNow += BLOCK; } aa[i+0*BLOCK] = t00; aa[i+1*BLOCK] = t10; aa[i+2*BLOCK] = t20; aa[i+3*BLOCK] = t30; aa[i+1+0*BLOCK] = t01; aa[i+1+1*BLOCK] = t11; aa[i+1+2*BLOCK] = t21; aa[i+1+3*BLOCK] = t31; } if (odd) { CoinWorkDouble t0 = aa[n+0*BLOCK]; CoinWorkDouble t1 = aa[n+1*BLOCK]; CoinWorkDouble t2 = aa[n+2*BLOCK]; CoinWorkDouble t3 = aa[n+3*BLOCK]; CoinWorkDouble a0; for (k = 0; k < BLOCK; k++) { a0 = aUnder[n+k*BLOCK] * work[k]; t0 -= a0 * above[j + 0 + k * BLOCK]; t1 -= a0 * above[j + 1 + k * BLOCK]; t2 -= a0 * above[j + 2 + k * BLOCK]; t3 -= a0 * above[j + 3 + k * BLOCK]; } aa[n+0*BLOCK] = t0; aa[n+1*BLOCK] = t1; aa[n+2*BLOCK] = t2; aa[n+3*BLOCK] = t3; } } } #else aa = aOther - BLOCK; for (j = 0; j < BLOCK; j ++) { aa += BLOCK; for (i = 0; i < nUnder; i++) { CoinWorkDouble t00 = aa[i+0*BLOCK]; for (k = 0; k < BLOCK; k++) { CoinWorkDouble a00 = aUnder[i+k*BLOCK] * work[k]; t00 -= a00 * above[j + k * BLOCK]; } aa[i] = t00; } } #endif } /* Uses factorization to solve. */ void ClpCholeskyDense::solve (CoinWorkDouble * region) { #ifdef CHOL_COMPARE double * region2 = NULL; if (numberRows_ < 200) { longDouble * xx = sparseFactor_; longDouble * yy = diagonal_; diagonal_ = sparseFactor_ + 40000; sparseFactor_ = diagonal_ + numberRows_; region2 = ClpCopyOfArray(region, numberRows_); int iRow, iColumn; int addOffset = numberRows_ - 1; longDouble * work = sparseFactor_ - 1; for (iColumn = 0; iColumn < numberRows_; iColumn++) { double value = region2[iColumn]; for (iRow = iColumn + 1; iRow < numberRows_; iRow++) region2[iRow] -= value * work[iRow]; addOffset--; work += addOffset; } for (iColumn = numberRows_ - 1; iColumn >= 0; iColumn--) { double value = region2[iColumn] * diagonal_[iColumn]; work -= addOffset; addOffset++; for (iRow = iColumn + 1; iRow < numberRows_; iRow++) value -= region2[iRow] * work[iRow]; region2[iColumn] = value; } sparseFactor_ = xx; diagonal_ = yy; } #endif /*longDouble * xx = sparseFactor_;*/ /*longDouble * yy = diagonal_;*/ /*diagonal_ = sparseFactor_ + 40000;*/ /*sparseFactor_=diagonal_ + numberRows_;*/ int numberBlocks = (numberRows_ + BLOCK - 1) >> BLOCKSHIFT; /* later align on boundary*/ longDouble * a = sparseFactor_ + BLOCKSQ * numberBlocks; int iBlock; longDouble * aa = a; int iColumn; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int nChunk; int jBlock; int iDo = iBlock * BLOCK; int base = iDo; if (iDo + BLOCK > numberRows_) { nChunk = numberRows_ - iDo; } else { nChunk = BLOCK; } solveF1(aa, nChunk, region + iDo); for (jBlock = iBlock + 1; jBlock < numberBlocks; jBlock++) { base += BLOCK; aa += BLOCKSQ; if (base + BLOCK > numberRows_) { nChunk = numberRows_ - base; } else { nChunk = BLOCK; } solveF2(aa, nChunk, region + iDo, region + base); } aa += BLOCKSQ; } /* do diagonal outside*/ for (iColumn = 0; iColumn < numberRows_; iColumn++) region[iColumn] *= diagonal_[iColumn]; int offset = ((numberBlocks * (numberBlocks + 1)) >> 1); aa = a + number_entries(offset - 1); int lBase = (numberBlocks - 1) * BLOCK; for (iBlock = numberBlocks - 1; iBlock >= 0; iBlock--) { int nChunk; int jBlock; int triBase = iBlock * BLOCK; int iBase = lBase; for (jBlock = iBlock + 1; jBlock < numberBlocks; jBlock++) { if (iBase + BLOCK > numberRows_) { nChunk = numberRows_ - iBase; } else { nChunk = BLOCK; } solveB2(aa, nChunk, region + triBase, region + iBase); iBase -= BLOCK; aa -= BLOCKSQ; } if (triBase + BLOCK > numberRows_) { nChunk = numberRows_ - triBase; } else { nChunk = BLOCK; } solveB1(aa, nChunk, region + triBase); aa -= BLOCKSQ; } #ifdef CHOL_COMPARE if (numberRows_ < 200) { for (int i = 0; i < numberRows_; i++) { assert(CoinAbs(region[i] - region2[i]) < 1.0e-3); } delete [] region2; } #endif } /* Forward part of solve 1*/ void ClpCholeskyDense::solveF1(longDouble * a, int n, CoinWorkDouble * region) { int j, k; CoinWorkDouble t00; for (j = 0; j < n; j ++) { t00 = region[j]; for (k = 0; k < j; ++k) { t00 -= region[k] * a[j + k * BLOCK]; } /*t00*=a[j + j * BLOCK];*/ region[j] = t00; } } /* Forward part of solve 2*/ void ClpCholeskyDense::solveF2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2) { int j, k; #ifdef BLOCKUNROLL if (n == BLOCK) { for (k = 0; k < BLOCK; k += 4) { CoinWorkDouble t0 = region2[0]; CoinWorkDouble t1 = region2[1]; CoinWorkDouble t2 = region2[2]; CoinWorkDouble t3 = region2[3]; t0 -= region[0] * a[0 + 0 * BLOCK]; t1 -= region[0] * a[1 + 0 * BLOCK]; t2 -= region[0] * a[2 + 0 * BLOCK]; t3 -= region[0] * a[3 + 0 * BLOCK]; t0 -= region[1] * a[0 + 1 * BLOCK]; t1 -= region[1] * a[1 + 1 * BLOCK]; t2 -= region[1] * a[2 + 1 * BLOCK]; t3 -= region[1] * a[3 + 1 * BLOCK]; t0 -= region[2] * a[0 + 2 * BLOCK]; t1 -= region[2] * a[1 + 2 * BLOCK]; t2 -= region[2] * a[2 + 2 * BLOCK]; t3 -= region[2] * a[3 + 2 * BLOCK]; t0 -= region[3] * a[0 + 3 * BLOCK]; t1 -= region[3] * a[1 + 3 * BLOCK]; t2 -= region[3] * a[2 + 3 * BLOCK]; t3 -= region[3] * a[3 + 3 * BLOCK]; t0 -= region[4] * a[0 + 4 * BLOCK]; t1 -= region[4] * a[1 + 4 * BLOCK]; t2 -= region[4] * a[2 + 4 * BLOCK]; t3 -= region[4] * a[3 + 4 * BLOCK]; t0 -= region[5] * a[0 + 5 * BLOCK]; t1 -= region[5] * a[1 + 5 * BLOCK]; t2 -= region[5] * a[2 + 5 * BLOCK]; t3 -= region[5] * a[3 + 5 * BLOCK]; t0 -= region[6] * a[0 + 6 * BLOCK]; t1 -= region[6] * a[1 + 6 * BLOCK]; t2 -= region[6] * a[2 + 6 * BLOCK]; t3 -= region[6] * a[3 + 6 * BLOCK]; t0 -= region[7] * a[0 + 7 * BLOCK]; t1 -= region[7] * a[1 + 7 * BLOCK]; t2 -= region[7] * a[2 + 7 * BLOCK]; t3 -= region[7] * a[3 + 7 * BLOCK]; #if BLOCK>8 t0 -= region[8] * a[0 + 8 * BLOCK]; t1 -= region[8] * a[1 + 8 * BLOCK]; t2 -= region[8] * a[2 + 8 * BLOCK]; t3 -= region[8] * a[3 + 8 * BLOCK]; t0 -= region[9] * a[0 + 9 * BLOCK]; t1 -= region[9] * a[1 + 9 * BLOCK]; t2 -= region[9] * a[2 + 9 * BLOCK]; t3 -= region[9] * a[3 + 9 * BLOCK]; t0 -= region[10] * a[0 + 10 * BLOCK]; t1 -= region[10] * a[1 + 10 * BLOCK]; t2 -= region[10] * a[2 + 10 * BLOCK]; t3 -= region[10] * a[3 + 10 * BLOCK]; t0 -= region[11] * a[0 + 11 * BLOCK]; t1 -= region[11] * a[1 + 11 * BLOCK]; t2 -= region[11] * a[2 + 11 * BLOCK]; t3 -= region[11] * a[3 + 11 * BLOCK]; t0 -= region[12] * a[0 + 12 * BLOCK]; t1 -= region[12] * a[1 + 12 * BLOCK]; t2 -= region[12] * a[2 + 12 * BLOCK]; t3 -= region[12] * a[3 + 12 * BLOCK]; t0 -= region[13] * a[0 + 13 * BLOCK]; t1 -= region[13] * a[1 + 13 * BLOCK]; t2 -= region[13] * a[2 + 13 * BLOCK]; t3 -= region[13] * a[3 + 13 * BLOCK]; t0 -= region[14] * a[0 + 14 * BLOCK]; t1 -= region[14] * a[1 + 14 * BLOCK]; t2 -= region[14] * a[2 + 14 * BLOCK]; t3 -= region[14] * a[3 + 14 * BLOCK]; t0 -= region[15] * a[0 + 15 * BLOCK]; t1 -= region[15] * a[1 + 15 * BLOCK]; t2 -= region[15] * a[2 + 15 * BLOCK]; t3 -= region[15] * a[3 + 15 * BLOCK]; #endif region2[0] = t0; region2[1] = t1; region2[2] = t2; region2[3] = t3; region2 += 4; a += 4; } } else { #endif for (k = 0; k < n; ++k) { CoinWorkDouble t00 = region2[k]; for (j = 0; j < BLOCK; j ++) { t00 -= region[j] * a[k + j * BLOCK]; } region2[k] = t00; } #ifdef BLOCKUNROLL } #endif } /* Backward part of solve 1*/ void ClpCholeskyDense::solveB1(longDouble * a, int n, CoinWorkDouble * region) { int j, k; CoinWorkDouble t00; for (j = n - 1; j >= 0; j --) { t00 = region[j]; for (k = j + 1; k < n; ++k) { t00 -= region[k] * a[k + j * BLOCK]; } /*t00*=a[j + j * BLOCK];*/ region[j] = t00; } } /* Backward part of solve 2*/ void ClpCholeskyDense::solveB2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2) { int j, k; #ifdef BLOCKUNROLL if (n == BLOCK) { for (j = 0; j < BLOCK; j += 4) { CoinWorkDouble t0 = region[0]; CoinWorkDouble t1 = region[1]; CoinWorkDouble t2 = region[2]; CoinWorkDouble t3 = region[3]; t0 -= region2[0] * a[0 + 0*BLOCK]; t1 -= region2[0] * a[0 + 1*BLOCK]; t2 -= region2[0] * a[0 + 2*BLOCK]; t3 -= region2[0] * a[0 + 3*BLOCK]; t0 -= region2[1] * a[1 + 0*BLOCK]; t1 -= region2[1] * a[1 + 1*BLOCK]; t2 -= region2[1] * a[1 + 2*BLOCK]; t3 -= region2[1] * a[1 + 3*BLOCK]; t0 -= region2[2] * a[2 + 0*BLOCK]; t1 -= region2[2] * a[2 + 1*BLOCK]; t2 -= region2[2] * a[2 + 2*BLOCK]; t3 -= region2[2] * a[2 + 3*BLOCK]; t0 -= region2[3] * a[3 + 0*BLOCK]; t1 -= region2[3] * a[3 + 1*BLOCK]; t2 -= region2[3] * a[3 + 2*BLOCK]; t3 -= region2[3] * a[3 + 3*BLOCK]; t0 -= region2[4] * a[4 + 0*BLOCK]; t1 -= region2[4] * a[4 + 1*BLOCK]; t2 -= region2[4] * a[4 + 2*BLOCK]; t3 -= region2[4] * a[4 + 3*BLOCK]; t0 -= region2[5] * a[5 + 0*BLOCK]; t1 -= region2[5] * a[5 + 1*BLOCK]; t2 -= region2[5] * a[5 + 2*BLOCK]; t3 -= region2[5] * a[5 + 3*BLOCK]; t0 -= region2[6] * a[6 + 0*BLOCK]; t1 -= region2[6] * a[6 + 1*BLOCK]; t2 -= region2[6] * a[6 + 2*BLOCK]; t3 -= region2[6] * a[6 + 3*BLOCK]; t0 -= region2[7] * a[7 + 0*BLOCK]; t1 -= region2[7] * a[7 + 1*BLOCK]; t2 -= region2[7] * a[7 + 2*BLOCK]; t3 -= region2[7] * a[7 + 3*BLOCK]; #if BLOCK>8 t0 -= region2[8] * a[8 + 0*BLOCK]; t1 -= region2[8] * a[8 + 1*BLOCK]; t2 -= region2[8] * a[8 + 2*BLOCK]; t3 -= region2[8] * a[8 + 3*BLOCK]; t0 -= region2[9] * a[9 + 0*BLOCK]; t1 -= region2[9] * a[9 + 1*BLOCK]; t2 -= region2[9] * a[9 + 2*BLOCK]; t3 -= region2[9] * a[9 + 3*BLOCK]; t0 -= region2[10] * a[10 + 0*BLOCK]; t1 -= region2[10] * a[10 + 1*BLOCK]; t2 -= region2[10] * a[10 + 2*BLOCK]; t3 -= region2[10] * a[10 + 3*BLOCK]; t0 -= region2[11] * a[11 + 0*BLOCK]; t1 -= region2[11] * a[11 + 1*BLOCK]; t2 -= region2[11] * a[11 + 2*BLOCK]; t3 -= region2[11] * a[11 + 3*BLOCK]; t0 -= region2[12] * a[12 + 0*BLOCK]; t1 -= region2[12] * a[12 + 1*BLOCK]; t2 -= region2[12] * a[12 + 2*BLOCK]; t3 -= region2[12] * a[12 + 3*BLOCK]; t0 -= region2[13] * a[13 + 0*BLOCK]; t1 -= region2[13] * a[13 + 1*BLOCK]; t2 -= region2[13] * a[13 + 2*BLOCK]; t3 -= region2[13] * a[13 + 3*BLOCK]; t0 -= region2[14] * a[14 + 0*BLOCK]; t1 -= region2[14] * a[14 + 1*BLOCK]; t2 -= region2[14] * a[14 + 2*BLOCK]; t3 -= region2[14] * a[14 + 3*BLOCK]; t0 -= region2[15] * a[15 + 0*BLOCK]; t1 -= region2[15] * a[15 + 1*BLOCK]; t2 -= region2[15] * a[15 + 2*BLOCK]; t3 -= region2[15] * a[15 + 3*BLOCK]; #endif region[0] = t0; region[1] = t1; region[2] = t2; region[3] = t3; a += 4 * BLOCK; region += 4; } } else { #endif for (j = 0; j < BLOCK; j ++) { CoinWorkDouble t00 = region[j]; for (k = 0; k < n; ++k) { t00 -= region2[k] * a[k + j * BLOCK]; } region[j] = t00; } #ifdef BLOCKUNROLL } #endif } Clp-1.15.10/src/ClpConstraintQuadratic.hpp0000644000076600007660000000706611510657452017013 0ustar coincoin/* $Id: ClpConstraintQuadratic.hpp 1665 2011-01-04 17:55:54Z 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). #ifndef ClpConstraintQuadratic_H #define ClpConstraintQuadratic_H #include "ClpConstraint.hpp" //############################################################################# /** Quadratic Constraint Class */ class ClpConstraintQuadratic : public ClpConstraint { public: ///@name Stuff //@{ /** Fills gradient. If Quadratic 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 nonquadratic columns to 1. Returns number of nonquadratic 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; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpConstraintQuadratic(); /// Constructor from quadratic ClpConstraintQuadratic(int row, int numberQuadraticColumns, int numberColumns, const CoinBigIndex * start, const int * column, const double * element); /** Copy constructor . */ ClpConstraintQuadratic(const ClpConstraintQuadratic & rhs); /// Assignment operator ClpConstraintQuadratic & operator=(const ClpConstraintQuadratic& rhs); /// Destructor virtual ~ClpConstraintQuadratic (); /// Clone virtual ClpConstraint * clone() const; //@} ///@name Gets and sets //@{ /// Number of coefficients virtual int numberCoefficients() const; /// Number of columns in constraint inline int numberColumns() const { return numberColumns_; } /// Column starts inline CoinBigIndex * start() const { return start_; } /// Columns inline const int * column() const { return column_; } /// Coefficients inline const double * coefficient() const { return coefficient_; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Column starts CoinBigIndex * start_; /// Column (if -1 then linear coefficient) int * column_; /// Coefficients double * coefficient_; /// Useful to have number of columns about int numberColumns_; /// Number of coefficients in gradient int numberCoefficients_; /// Number of quadratic columns int numberQuadraticColumns_; //@} }; #endif Clp-1.15.10/src/unitTest.cpp0000644000076600007660000034555612017705027014210 0ustar coincoin/* $Id: unitTest.cpp 1878 2012-08-30 15:43:19Z 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). #ifdef NDEBUG #undef NDEBUG #endif #include "ClpConfig.h" #include "CoinPragma.hpp" #include #include #include #include #include #include #include #include "CoinMpsIO.hpp" #include "CoinPackedMatrix.hpp" #include "CoinPackedVector.hpp" #include "CoinStructuredModel.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "CoinFloatEqual.hpp" #if CLP_HAS_ABC #include "CoinAbcCommon.hpp" #endif #ifdef ABC_INHERIT #include "CoinAbcFactorization.hpp" #endif #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #include "ClpSimplexNonlinear.hpp" #include "ClpInterior.hpp" #include "ClpLinearObjective.hpp" #include "ClpDualRowSteepest.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpParameters.hpp" #include "ClpNetworkMatrix.hpp" #include "ClpPlusMinusOneMatrix.hpp" #include "MyMessageHandler.hpp" #include "MyEventHandler.hpp" #include "ClpPresolve.hpp" #include "Idiot.hpp" #if FACTORIZATION_STATISTICS extern double ftranTwiddleFactor1X; extern double ftranTwiddleFactor2X; extern double ftranFTTwiddleFactor1X; extern double ftranFTTwiddleFactor2X; extern double btranTwiddleFactor1X; extern double btranTwiddleFactor2X; extern double ftranFullTwiddleFactor1X; extern double ftranFullTwiddleFactor2X; extern double btranFullTwiddleFactor1X; extern double btranFullTwiddleFactor2X; extern double denseThresholdX; extern double twoThresholdX; extern double minRowsSparse; extern double largeRowsSparse; extern double mediumRowsDivider; extern double mediumRowsMinCount; extern double largeRowsCount; #endif //############################################################################# // Function Prototypes. Function definitions is in this file. void testingMessage( const char * const msg ); #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK) static int barrierAvailable = 1; static std::string nameBarrier = "barrier-UFL"; #elif COIN_HAS_WSMP static int barrierAvailable = 2; static std::string nameBarrier = "barrier-WSSMP"; #elif defined(COIN_HAS_MUMPS) static int barrierAvailable = 3; static std::string nameBarrier = "barrier-MUMPS"; #else static int barrierAvailable = 0; static std::string nameBarrier = "barrier-slow"; #endif #define NUMBER_ALGORITHMS 12 // If you just want a subset then set some to 1 static int switchOff[NUMBER_ALGORITHMS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // shortName - 0 no , 1 yes ClpSolve setupForSolve(int algorithm, std::string & nameAlgorithm, int shortName) { ClpSolve solveOptions; /* algorithms are 0 barrier 1 dual with volumne crash 2,3 dual with and without crash 4,5 primal with and without 6,7 automatic with and without 8,9 primal with idiot 1 and 5 10,11 primal with 70, dual with volume */ switch (algorithm) { case 0: if (shortName) nameAlgorithm = "ba"; else nameAlgorithm = "nameBarrier"; solveOptions.setSolveType(ClpSolve::useBarrier); if (barrierAvailable == 1) solveOptions.setSpecialOption(4, 4); else if (barrierAvailable == 2) solveOptions.setSpecialOption(4, 2); break; case 1: #ifdef COIN_HAS_VOL if (shortName) nameAlgorithm = "du-vol-50"; else nameAlgorithm = "dual-volume-50"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0, 2, 50); // volume #else solveOptions.setSolveType(ClpSolve::notImplemented); #endif break; case 2: if (shortName) nameAlgorithm = "du-cr"; else nameAlgorithm = "dual-crash"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0, 1); break; case 3: if (shortName) nameAlgorithm = "du"; else nameAlgorithm = "dual"; solveOptions.setSolveType(ClpSolve::useDual); break; case 4: if (shortName) nameAlgorithm = "pr-cr"; else nameAlgorithm = "primal-crash"; solveOptions.setSolveType(ClpSolve::usePrimal); solveOptions.setSpecialOption(1, 1); break; case 5: if (shortName) nameAlgorithm = "pr"; else nameAlgorithm = "primal"; solveOptions.setSolveType(ClpSolve::usePrimal); break; case 6: if (shortName) nameAlgorithm = "au-cr"; else nameAlgorithm = "either-crash"; solveOptions.setSolveType(ClpSolve::automatic); solveOptions.setSpecialOption(1, 1); break; case 7: if (shortName) nameAlgorithm = "au"; else nameAlgorithm = "either"; solveOptions.setSolveType(ClpSolve::automatic); break; case 8: if (shortName) nameAlgorithm = "pr-id-1"; else nameAlgorithm = "primal-idiot-1"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1, 2, 1); // idiot break; case 9: if (shortName) nameAlgorithm = "pr-id-5"; else nameAlgorithm = "primal-idiot-5"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1, 2, 5); // idiot break; case 10: if (shortName) nameAlgorithm = "pr-id-70"; else nameAlgorithm = "primal-idiot-70"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1, 2, 70); // idiot break; case 11: #ifdef COIN_HAS_VOL if (shortName) nameAlgorithm = "du-vol"; else nameAlgorithm = "dual-volume"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0, 2, 3000); // volume #else solveOptions.setSolveType(ClpSolve::notImplemented); #endif break; default: abort(); } if (shortName) { // can switch off if (switchOff[algorithm]) solveOptions.setSolveType(ClpSolve::notImplemented); } return solveOptions; } static void printSol(ClpSimplex & model) { int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); double * rowPrimal = model.primalRowSolution(); double * rowDual = model.dualRowSolution(); double * rowLower = model.rowLower(); double * rowUpper = model.rowUpper(); int iRow; double objValue = model.getObjValue(); printf("Objvalue %g Rows (%d)\n", objValue, numberRows); for (iRow = 0; iRow < numberRows; iRow++) { printf("%d primal %g dual %g low %g up %g\n", iRow, rowPrimal[iRow], rowDual[iRow], rowLower[iRow], rowUpper[iRow]); } double * columnPrimal = model.primalColumnSolution(); double * columnDual = model.dualColumnSolution(); double * columnLower = model.columnLower(); double * columnUpper = model.columnUpper(); double offset; //const double * gradient = model.objectiveAsObject()->gradient(&model, // columnPrimal,offset,true,1); const double * gradient = model.objective(columnPrimal, offset); int iColumn; objValue = -offset - model.objectiveOffset(); printf("offset %g (%g)\n", offset, model.objectiveOffset()); printf("Columns (%d)\n", numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { printf("%d primal %g dual %g low %g up %g\n", iColumn, columnPrimal[iColumn], columnDual[iColumn], columnLower[iColumn], columnUpper[iColumn]); objValue += columnPrimal[iColumn] * gradient[iColumn]; if (fabs(columnPrimal[iColumn]*gradient[iColumn]) > 1.0e-8) printf("obj -> %g gradient %g\n", objValue, gradient[iColumn]); } printf("Computed objective %g\n", objValue); } void usage(const std::string& key) { std::cerr << "Undefined parameter \"" << key << "\".\n" << "Correct usage: \n" << " clp [-dirSample=V1] [-dirNetlib=V2] [-netlib]\n" << " where:\n" << " -dirSample: directory containing mps test files\n" << " Default value V1=\"../../Data/Sample\"\n" << " -dirNetlib: directory containing netlib files\"\n" << " Default value V2=\"../../Data/Netlib\"\n" << " -netlib\n" << " If specified, then netlib testset run as well as the nitTest.\n"; } #if FACTORIZATION_STATISTICS int loSizeX=-1; int hiSizeX=1000000; #endif //---------------------------------------------------------------- #ifndef ABC_INHERIT #define AnySimplex ClpSimplex #else #include "AbcSimplex.hpp" #define AnySimplex AbcSimplex #endif int mainTest (int argc, const char *argv[], int algorithm, AnySimplex empty, ClpSolve solveOptionsIn, int switchOffValue, bool doVector) { int i; if (switchOffValue > 0) { // switch off some int iTest; for (iTest = 0; iTest < NUMBER_ALGORITHMS; iTest++) { #ifndef NDEBUG int bottom = switchOffValue % 10; assert (bottom == 0 || bottom == 1); #endif switchOffValue /= 10; switchOff[iTest] = 0; } } int numberFailures=0; // define valid parameter keywords std::set definedKeyWords; definedKeyWords.insert("-dirSample"); definedKeyWords.insert("-dirNetlib"); definedKeyWords.insert("-netlib"); // 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; std::string::size_type 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 usage(key); return 1; } parms[key] = value; } const char dirsep = CoinFindDirSeparator(); // Set directory containing mps data files. std::string dirSample; if (parms.find("-dirSample") != parms.end()) dirSample = parms["-dirSample"]; else dirSample = dirsep == '/' ? "../../Data/Sample/" : "..\\..\\Data\\Sample\\"; // Set directory containing netlib data files. std::string dirNetlib; if (parms.find("-dirNetlib") != parms.end()) dirNetlib = parms["-dirNetlib"]; else dirNetlib = dirsep == '/' ? "../../Data/Netlib/" : "..\\..\\Data\\Netlib\\"; #if 0 //FACTORIZATION_STATISTICS==0 if (!empty.numberRows()) { testingMessage( "Testing ClpSimplex\n" ); ClpSimplexUnitTest(dirSample); } #endif if (parms.find("-netlib") != parms.end() || empty.numberRows()) { unsigned int m; std::string sizeLoHi; #if FACTORIZATION_STATISTICS double ftranTwiddleFactor1XChoice[3]={0.9,1.0,1.1}; double ftranTwiddleFactor2XChoice[3]={0.9,1.0,1.1}; double ftranFTTwiddleFactor1XChoice[3]={0.9,1.0,1.1}; double ftranFTTwiddleFactor2XChoice[3]={0.9,1.0,1.1}; double btranTwiddleFactor1XChoice[3]={0.9,1.0,1.1}; double btranTwiddleFactor2XChoice[3]={0.9,1.0,1.1}; double ftranFullTwiddleFactor1XChoice[3]={0.9,1.0,1.1}; double ftranFullTwiddleFactor2XChoice[3]={0.9,1.0,1.1}; double btranFullTwiddleFactor1XChoice[3]={0.9,1.0,1.1}; double btranFullTwiddleFactor2XChoice[3]={0.9,1.0,1.1}; double denseThresholdXChoice[3]={2,20,40}; double twoThresholdXChoice[3]={800,1000,1200}; double minRowsSparseChoice[3]={250,300,350}; double largeRowsSparseChoice[3]={8000,10000,12000}; double mediumRowsDividerChoice[3]={5,6,7}; double mediumRowsMinCountChoice[3]={300,500,600}; double largeRowsCountChoice[3]={700,1000,1300}; double times[3*3*3*3*3]; memset(times,0,sizeof(times)); #define whichParam(za,zname) const char * choice##za=#zname; \ const double * use##za=zname##Choice; \ double * external##za=&zname whichParam(A,denseThresholdX); whichParam(B,twoThresholdX); whichParam(C,minRowsSparse); whichParam(D,mediumRowsDivider); whichParam(E,mediumRowsMinCount); #endif // Define test problems: // mps names, // maximization or minimization, // Number of rows and columns in problem, and // objective function value std::vector mpsName; std::vector min; std::vector nRows; std::vector nCols; std::vector objValue; std::vector objValueTol; // 100 added means no presolve std::vector bestStrategy; if(empty.numberRows()) { std::string alg; for (int iTest = 0; iTest < NUMBER_ALGORITHMS; iTest++) { ClpSolve solveOptions = setupForSolve(iTest, alg, 0); printf("%d %s ", iTest, alg.c_str()); if (switchOff[iTest]) printf("skipped by user\n"); else if(solveOptions.getSolveType() == ClpSolve::notImplemented) printf("skipped as not available\n"); else printf("will be tested\n"); } } if (!empty.numberRows()) { #if 1 mpsName.push_back("25fv47"); min.push_back(true); nRows.push_back(822); nCols.push_back(1571); objValueTol.push_back(1.E-10); objValue.push_back(5.5018458883E+03); bestStrategy.push_back(0); mpsName.push_back("80bau3b"); min.push_back(true); nRows.push_back(2263); nCols.push_back(9799); objValueTol.push_back(1.e-8); objValue.push_back(9.8722419241E+05); bestStrategy.push_back(3); mpsName.push_back("blend"); min.push_back(true); nRows.push_back(75); nCols.push_back(83); objValueTol.push_back(1.e-8); objValue.push_back(-3.0812149846e+01); bestStrategy.push_back(3); mpsName.push_back("pilotnov"); min.push_back(true); nRows.push_back(976); nCols.push_back(2172); objValueTol.push_back(1.e-10); objValue.push_back(-4.4972761882e+03); bestStrategy.push_back(3); mpsName.push_back("maros-r7"); min.push_back(true); nRows.push_back(3137); nCols.push_back(9408); objValueTol.push_back(1.e-10); objValue.push_back(1.4971851665e+06); bestStrategy.push_back(2); mpsName.push_back("pilot"); min.push_back(true); nRows.push_back(1442); nCols.push_back(3652); objValueTol.push_back(1.e-5); objValue.push_back(/*-5.5740430007e+02*/ -557.48972927292); bestStrategy.push_back(3); mpsName.push_back("pilot4"); min.push_back(true); nRows.push_back(411); nCols.push_back(1000); objValueTol.push_back(5.e-5); objValue.push_back(-2.5811392641e+03); bestStrategy.push_back(3); #endif mpsName.push_back("pilot87"); min.push_back(true); nRows.push_back(2031); nCols.push_back(4883); objValueTol.push_back(1.e-4); objValue.push_back(3.0171072827e+02); bestStrategy.push_back(0); #if 1 mpsName.push_back("adlittle"); min.push_back(true); nRows.push_back(57); nCols.push_back(97); objValueTol.push_back(1.e-10); objValue.push_back(2.2549496316e+05); bestStrategy.push_back(3); mpsName.push_back("afiro"); min.push_back(true); nRows.push_back(28); nCols.push_back(32); objValueTol.push_back(1.e-10); objValue.push_back(-4.6475314286e+02); bestStrategy.push_back(3); mpsName.push_back("agg"); min.push_back(true); nRows.push_back(489); nCols.push_back(163); objValueTol.push_back(1.e-10); objValue.push_back(-3.5991767287e+07); bestStrategy.push_back(3); mpsName.push_back("agg2"); min.push_back(true); nRows.push_back(517); nCols.push_back(302); objValueTol.push_back(1.e-10); objValue.push_back(-2.0239252356e+07); bestStrategy.push_back(3); mpsName.push_back("agg3"); min.push_back(true); nRows.push_back(517); nCols.push_back(302); objValueTol.push_back(1.e-10); objValue.push_back(1.0312115935e+07); bestStrategy.push_back(4); mpsName.push_back("bandm"); min.push_back(true); nRows.push_back(306); nCols.push_back(472); objValueTol.push_back(1.e-10); objValue.push_back(-1.5862801845e+02); bestStrategy.push_back(2); mpsName.push_back("beaconfd"); min.push_back(true); nRows.push_back(174); nCols.push_back(262); objValueTol.push_back(1.e-10); objValue.push_back(3.3592485807e+04); bestStrategy.push_back(0); mpsName.push_back("bnl1"); min.push_back(true); nRows.push_back(644); nCols.push_back(1175); objValueTol.push_back(1.e-10); objValue.push_back(1.9776295615E+03); bestStrategy.push_back(3); mpsName.push_back("bnl2"); min.push_back(true); nRows.push_back(2325); nCols.push_back(3489); objValueTol.push_back(1.e-10); objValue.push_back(1.8112365404e+03); bestStrategy.push_back(3); mpsName.push_back("boeing1"); min.push_back(true); nRows.push_back(/*351*/352); nCols.push_back(384); objValueTol.push_back(1.e-10); objValue.push_back(-3.3521356751e+02); bestStrategy.push_back(3); mpsName.push_back("boeing2"); min.push_back(true); nRows.push_back(167); nCols.push_back(143); objValueTol.push_back(1.e-10); objValue.push_back(-3.1501872802e+02); bestStrategy.push_back(3); mpsName.push_back("bore3d"); min.push_back(true); nRows.push_back(234); nCols.push_back(315); objValueTol.push_back(1.e-10); objValue.push_back(1.3730803942e+03); bestStrategy.push_back(3); mpsName.push_back("brandy"); min.push_back(true); nRows.push_back(221); nCols.push_back(249); objValueTol.push_back(1.e-10); objValue.push_back(1.5185098965e+03); bestStrategy.push_back(3); mpsName.push_back("capri"); min.push_back(true); nRows.push_back(272); nCols.push_back(353); objValueTol.push_back(1.e-10); objValue.push_back(2.6900129138e+03); bestStrategy.push_back(3); mpsName.push_back("cycle"); min.push_back(true); nRows.push_back(1904); nCols.push_back(2857); objValueTol.push_back(1.e-9); objValue.push_back(-5.2263930249e+00); bestStrategy.push_back(3); mpsName.push_back("czprob"); min.push_back(true); nRows.push_back(930); nCols.push_back(3523); objValueTol.push_back(1.e-10); objValue.push_back(2.1851966989e+06); bestStrategy.push_back(3); mpsName.push_back("d2q06c"); min.push_back(true); nRows.push_back(2172); nCols.push_back(5167); objValueTol.push_back(1.e-7); objValue.push_back(122784.21557456); bestStrategy.push_back(0); mpsName.push_back("d6cube"); min.push_back(true); nRows.push_back(416); nCols.push_back(6184); objValueTol.push_back(1.e-7); objValue.push_back(3.1549166667e+02); bestStrategy.push_back(3); mpsName.push_back("degen2"); min.push_back(true); nRows.push_back(445); nCols.push_back(534); objValueTol.push_back(1.e-10); objValue.push_back(-1.4351780000e+03); bestStrategy.push_back(3); mpsName.push_back("degen3"); min.push_back(true); nRows.push_back(1504); nCols.push_back(1818); objValueTol.push_back(1.e-10); objValue.push_back(-9.8729400000e+02); bestStrategy.push_back(2); mpsName.push_back("dfl001"); min.push_back(true); nRows.push_back(6072); nCols.push_back(12230); objValueTol.push_back(1.e-5); objValue.push_back(1.1266396047E+07); bestStrategy.push_back(5); mpsName.push_back("e226"); min.push_back(true); nRows.push_back(224); nCols.push_back(282); objValueTol.push_back(1.e-10); objValue.push_back(-1.8751929066e+01 + 7.113); bestStrategy.push_back(3); // The correct answer includes -7.113 term. This is a constant in the objective function. See line 1683 of the mps file. mpsName.push_back("etamacro"); min.push_back(true); nRows.push_back(401); nCols.push_back(688); objValueTol.push_back(1.e-6); objValue.push_back(-7.5571521774e+02 ); bestStrategy.push_back(3); mpsName.push_back("fffff800"); min.push_back(true); nRows.push_back(525); nCols.push_back(854); objValueTol.push_back(1.e-6); objValue.push_back(5.5567961165e+05); bestStrategy.push_back(3); mpsName.push_back("finnis"); min.push_back(true); nRows.push_back(498); nCols.push_back(614); objValueTol.push_back(1.e-6); objValue.push_back(1.7279096547e+05); bestStrategy.push_back(3); mpsName.push_back("fit1d"); min.push_back(true); nRows.push_back(25); nCols.push_back(1026); objValueTol.push_back(1.e-10); objValue.push_back(-9.1463780924e+03); bestStrategy.push_back(3 + 100); mpsName.push_back("fit1p"); min.push_back(true); nRows.push_back(628); nCols.push_back(1677); objValueTol.push_back(1.e-10); objValue.push_back(9.1463780924e+03); bestStrategy.push_back(5 + 100); mpsName.push_back("fit2d"); min.push_back(true); nRows.push_back(26); nCols.push_back(10500); objValueTol.push_back(1.e-10); objValue.push_back(-6.8464293294e+04); bestStrategy.push_back(3 + 100); mpsName.push_back("fit2p"); min.push_back(true); nRows.push_back(3001); nCols.push_back(13525); objValueTol.push_back(1.e-9); objValue.push_back(6.8464293232e+04); bestStrategy.push_back(5 + 100); mpsName.push_back("forplan"); min.push_back(true); nRows.push_back(162); nCols.push_back(421); objValueTol.push_back(1.e-6); objValue.push_back(-6.6421873953e+02); bestStrategy.push_back(3); mpsName.push_back("ganges"); min.push_back(true); nRows.push_back(1310); nCols.push_back(1681); objValueTol.push_back(1.e-5); objValue.push_back(-1.0958636356e+05); bestStrategy.push_back(3); mpsName.push_back("gfrd-pnc"); min.push_back(true); nRows.push_back(617); nCols.push_back(1092); objValueTol.push_back(1.e-10); objValue.push_back(6.9022359995e+06); bestStrategy.push_back(3); mpsName.push_back("greenbea"); min.push_back(true); nRows.push_back(2393); nCols.push_back(5405); objValueTol.push_back(1.e-10); objValue.push_back(/*-7.2462405908e+07*/ -72555248.129846); bestStrategy.push_back(3); mpsName.push_back("greenbeb"); min.push_back(true); nRows.push_back(2393); nCols.push_back(5405); objValueTol.push_back(1.e-10); objValue.push_back(/*-4.3021476065e+06*/ -4302260.2612066); bestStrategy.push_back(3); mpsName.push_back("grow15"); min.push_back(true); nRows.push_back(301); nCols.push_back(645); objValueTol.push_back(1.e-10); objValue.push_back(-1.0687094129e+08); bestStrategy.push_back(4 + 100); mpsName.push_back("grow22"); min.push_back(true); nRows.push_back(441); nCols.push_back(946); objValueTol.push_back(1.e-10); objValue.push_back(-1.6083433648e+08); bestStrategy.push_back(4 + 100); mpsName.push_back("grow7"); min.push_back(true); nRows.push_back(141); nCols.push_back(301); objValueTol.push_back(1.e-10); objValue.push_back(-4.7787811815e+07); bestStrategy.push_back(4 + 100); mpsName.push_back("israel"); min.push_back(true); nRows.push_back(175); nCols.push_back(142); objValueTol.push_back(1.e-10); objValue.push_back(-8.9664482186e+05); bestStrategy.push_back(2); mpsName.push_back("kb2"); min.push_back(true); nRows.push_back(44); nCols.push_back(41); objValueTol.push_back(1.e-10); objValue.push_back(-1.7499001299e+03); bestStrategy.push_back(3); mpsName.push_back("lotfi"); min.push_back(true); nRows.push_back(154); nCols.push_back(308); objValueTol.push_back(1.e-10); objValue.push_back(-2.5264706062e+01); bestStrategy.push_back(3); mpsName.push_back("maros"); min.push_back(true); nRows.push_back(847); nCols.push_back(1443); objValueTol.push_back(1.e-10); objValue.push_back(-5.8063743701e+04); bestStrategy.push_back(3); mpsName.push_back("modszk1"); min.push_back(true); nRows.push_back(688); nCols.push_back(1620); objValueTol.push_back(1.e-10); objValue.push_back(3.2061972906e+02); bestStrategy.push_back(3); mpsName.push_back("nesm"); min.push_back(true); nRows.push_back(663); nCols.push_back(2923); objValueTol.push_back(1.e-5); objValue.push_back(1.4076073035e+07); bestStrategy.push_back(2); mpsName.push_back("perold"); min.push_back(true); nRows.push_back(626); nCols.push_back(1376); objValueTol.push_back(1.e-6); objValue.push_back(-9.3807580773e+03); bestStrategy.push_back(3); //mpsName.push_back("qap12");min.push_back(true);nRows.push_back(3193);nCols.push_back(8856);objValueTol.push_back(1.e-6);objValue.push_back(5.2289435056e+02);bestStrategy.push_back(3); //mpsName.push_back("qap15");min.push_back(true);nRows.push_back(6331);nCols.push_back(22275);objValueTol.push_back(1.e-10);objValue.push_back(1.0409940410e+03);bestStrategy.push_back(3); mpsName.push_back("recipe"); min.push_back(true); nRows.push_back(92); nCols.push_back(180); objValueTol.push_back(1.e-10); objValue.push_back(-2.6661600000e+02); bestStrategy.push_back(3); mpsName.push_back("sc105"); min.push_back(true); nRows.push_back(106); nCols.push_back(103); objValueTol.push_back(1.e-10); objValue.push_back(-5.2202061212e+01); bestStrategy.push_back(3); mpsName.push_back("sc205"); min.push_back(true); nRows.push_back(206); nCols.push_back(203); objValueTol.push_back(1.e-10); objValue.push_back(-5.2202061212e+01); bestStrategy.push_back(3); mpsName.push_back("sc50a"); min.push_back(true); nRows.push_back(51); nCols.push_back(48); objValueTol.push_back(1.e-10); objValue.push_back(-6.4575077059e+01); bestStrategy.push_back(3); mpsName.push_back("sc50b"); min.push_back(true); nRows.push_back(51); nCols.push_back(48); objValueTol.push_back(1.e-10); objValue.push_back(-7.0000000000e+01); bestStrategy.push_back(3); mpsName.push_back("scagr25"); min.push_back(true); nRows.push_back(472); nCols.push_back(500); objValueTol.push_back(1.e-10); objValue.push_back(-1.4753433061e+07); bestStrategy.push_back(3); mpsName.push_back("scagr7"); min.push_back(true); nRows.push_back(130); nCols.push_back(140); objValueTol.push_back(1.e-6); objValue.push_back(-2.3313892548e+06); bestStrategy.push_back(3); mpsName.push_back("scfxm1"); min.push_back(true); nRows.push_back(331); nCols.push_back(457); objValueTol.push_back(1.e-10); objValue.push_back(1.8416759028e+04); bestStrategy.push_back(3); mpsName.push_back("scfxm2"); min.push_back(true); nRows.push_back(661); nCols.push_back(914); objValueTol.push_back(1.e-10); objValue.push_back(3.6660261565e+04); bestStrategy.push_back(3); mpsName.push_back("scfxm3"); min.push_back(true); nRows.push_back(991); nCols.push_back(1371); objValueTol.push_back(1.e-10); objValue.push_back(5.4901254550e+04); bestStrategy.push_back(3); mpsName.push_back("scorpion"); min.push_back(true); nRows.push_back(389); nCols.push_back(358); objValueTol.push_back(1.e-10); objValue.push_back(1.8781248227e+03); bestStrategy.push_back(3); mpsName.push_back("scrs8"); min.push_back(true); nRows.push_back(491); nCols.push_back(1169); objValueTol.push_back(1.e-5); objValue.push_back(9.0429998619e+02); bestStrategy.push_back(2); mpsName.push_back("scsd1"); min.push_back(true); nRows.push_back(78); nCols.push_back(760); objValueTol.push_back(1.e-10); objValue.push_back(8.6666666743e+00); bestStrategy.push_back(3 + 100); mpsName.push_back("scsd6"); min.push_back(true); nRows.push_back(148); nCols.push_back(1350); objValueTol.push_back(1.e-10); objValue.push_back(5.0500000078e+01); bestStrategy.push_back(3 + 100); mpsName.push_back("scsd8"); min.push_back(true); nRows.push_back(398); nCols.push_back(2750); objValueTol.push_back(1.e-10); objValue.push_back(9.0499999993e+02); bestStrategy.push_back(1 + 100); mpsName.push_back("sctap1"); min.push_back(true); nRows.push_back(301); nCols.push_back(480); objValueTol.push_back(1.e-10); objValue.push_back(1.4122500000e+03); bestStrategy.push_back(3); mpsName.push_back("sctap2"); min.push_back(true); nRows.push_back(1091); nCols.push_back(1880); objValueTol.push_back(1.e-10); objValue.push_back(1.7248071429e+03); bestStrategy.push_back(3); mpsName.push_back("sctap3"); min.push_back(true); nRows.push_back(1481); nCols.push_back(2480); objValueTol.push_back(1.e-10); objValue.push_back(1.4240000000e+03); bestStrategy.push_back(3); mpsName.push_back("seba"); min.push_back(true); nRows.push_back(516); nCols.push_back(1028); objValueTol.push_back(1.e-10); objValue.push_back(1.5711600000e+04); bestStrategy.push_back(3); mpsName.push_back("share1b"); min.push_back(true); nRows.push_back(118); nCols.push_back(225); objValueTol.push_back(1.e-10); objValue.push_back(-7.6589318579e+04); bestStrategy.push_back(3); mpsName.push_back("share2b"); min.push_back(true); nRows.push_back(97); nCols.push_back(79); objValueTol.push_back(1.e-10); objValue.push_back(-4.1573224074e+02); bestStrategy.push_back(3); mpsName.push_back("shell"); min.push_back(true); nRows.push_back(537); nCols.push_back(1775); objValueTol.push_back(1.e-10); objValue.push_back(1.2088253460e+09); bestStrategy.push_back(3); mpsName.push_back("ship04l"); min.push_back(true); nRows.push_back(403); nCols.push_back(2118); objValueTol.push_back(1.e-10); objValue.push_back(1.7933245380e+06); bestStrategy.push_back(3); mpsName.push_back("ship04s"); min.push_back(true); nRows.push_back(403); nCols.push_back(1458); objValueTol.push_back(1.e-10); objValue.push_back(1.7987147004e+06); bestStrategy.push_back(3); mpsName.push_back("ship08l"); min.push_back(true); nRows.push_back(779); nCols.push_back(4283); objValueTol.push_back(1.e-10); objValue.push_back(1.9090552114e+06); bestStrategy.push_back(3); mpsName.push_back("ship08s"); min.push_back(true); nRows.push_back(779); nCols.push_back(2387); objValueTol.push_back(1.e-10); objValue.push_back(1.9200982105e+06); bestStrategy.push_back(2); mpsName.push_back("ship12l"); min.push_back(true); nRows.push_back(1152); nCols.push_back(5427); objValueTol.push_back(1.e-10); objValue.push_back(1.4701879193e+06); bestStrategy.push_back(3); mpsName.push_back("ship12s"); min.push_back(true); nRows.push_back(1152); nCols.push_back(2763); objValueTol.push_back(1.e-10); objValue.push_back(1.4892361344e+06); bestStrategy.push_back(2); mpsName.push_back("sierra"); min.push_back(true); nRows.push_back(1228); nCols.push_back(2036); objValueTol.push_back(1.e-10); objValue.push_back(1.5394362184e+07); bestStrategy.push_back(3); mpsName.push_back("stair"); min.push_back(true); nRows.push_back(357); nCols.push_back(467); objValueTol.push_back(1.e-10); objValue.push_back(-2.5126695119e+02); bestStrategy.push_back(3); mpsName.push_back("standata"); min.push_back(true); nRows.push_back(360); nCols.push_back(1075); objValueTol.push_back(1.e-10); objValue.push_back(1.2576995000e+03); bestStrategy.push_back(3); //mpsName.push_back("standgub");min.push_back(true);nRows.push_back(362);nCols.push_back(1184);objValueTol.push_back(1.e-10);objValue.push_back(1257.6995); bestStrategy.push_back(3); mpsName.push_back("standmps"); min.push_back(true); nRows.push_back(468); nCols.push_back(1075); objValueTol.push_back(1.e-10); objValue.push_back(1.4060175000E+03); bestStrategy.push_back(3); mpsName.push_back("stocfor1"); min.push_back(true); nRows.push_back(118); nCols.push_back(111); objValueTol.push_back(1.e-10); objValue.push_back(-4.1131976219E+04); bestStrategy.push_back(3); mpsName.push_back("stocfor2"); min.push_back(true); nRows.push_back(2158); nCols.push_back(2031); objValueTol.push_back(1.e-10); objValue.push_back(-3.9024408538e+04); bestStrategy.push_back(3); //mpsName.push_back("stocfor3");min.push_back(true);nRows.push_back(16676);nCols.push_back(15695);objValueTol.push_back(1.e-10);objValue.push_back(-3.9976661576e+04);bestStrategy.push_back(3); //mpsName.push_back("truss");min.push_back(true);nRows.push_back(1001);nCols.push_back(8806);objValueTol.push_back(1.e-10);objValue.push_back(4.5881584719e+05);bestStrategy.push_back(3); mpsName.push_back("tuff"); min.push_back(true); nRows.push_back(334); nCols.push_back(587); objValueTol.push_back(1.e-10); objValue.push_back(2.9214776509e-01); bestStrategy.push_back(3); mpsName.push_back("vtpbase"); min.push_back(true); nRows.push_back(199); nCols.push_back(203); objValueTol.push_back(1.e-10); objValue.push_back(1.2983146246e+05); bestStrategy.push_back(3); mpsName.push_back("wood1p"); min.push_back(true); nRows.push_back(245); nCols.push_back(2594); objValueTol.push_back(5.e-5); objValue.push_back(1.4429024116e+00); bestStrategy.push_back(3); mpsName.push_back("woodw"); min.push_back(true); nRows.push_back(1099); nCols.push_back(8405); objValueTol.push_back(1.e-10); objValue.push_back(1.3044763331E+00); bestStrategy.push_back(3); #endif } else { // Just testing one mpsName.push_back(empty.problemName()); min.push_back(true); nRows.push_back(-1); nCols.push_back(-1); objValueTol.push_back(1.e-10); objValue.push_back(0.0); bestStrategy.push_back(0); int iTest; std::string alg; for (iTest = 0; iTest < NUMBER_ALGORITHMS; iTest++) { ClpSolve solveOptions = setupForSolve(iTest, alg, 0); printf("%d %s ", iTest, alg.c_str()); if (switchOff[iTest]) printf("skipped by user\n"); else if(solveOptions.getSolveType() == ClpSolve::notImplemented) printf("skipped as not available\n"); else printf("will be tested\n"); } } double timeTaken = 0.0; if( !barrierAvailable) switchOff[0] = 1; // Loop once for each Mps File for (m = 0; m < mpsName.size(); m++ ) { #if FACTORIZATION_STATISTICS if (nRows[m]=hiSizeX) { std::cerr << " skipping mps file: " << mpsName[m] <<" as "<(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } solution.initialSolve(solveOptions); double time2 = CoinCpuTime() - time1; testTime[iTest] = time2; printf("Finished %s Took %g seconds (%d iterations) - status %d\n", mpsName[m].c_str(),time2, solution.problemStatus(),solution.numberIterations()); if (solution.problemStatus()) testTime[iTest] = 1.0e20; } else { testTime[iTest] = 1.0e30; } } int iBest = -1; double dBest = 1.0e10; printf("%s", fn.c_str()); for (iTest = 0; iTest < NUMBER_ALGORITHMS; iTest++) { if (testTime[iTest] < 1.0e30) { printf(" %s %g", alg[iTest].c_str(), testTime[iTest]); if (testTime[iTest] < dBest) { dBest = testTime[iTest]; iBest = iTest; } } } printf("\n"); if (iBest >= 0) printf("Best strategy for %s is %s (%d) which takes %g seconds\n", fn.c_str(), alg[iBest].c_str(), iBest, testTime[iBest]); else printf("No strategy finished in time limit\n"); continue; } double time1 = CoinCpuTime(); AnySimplex solution = solutionBase; #if 0 solution.setOptimizationDirection(-1); { int j; double * obj = solution.objective(); int n = solution.numberColumns(); for (j = 0; j < n; j++) obj[j] *= -1.0; } #endif ClpSolve::SolveType method; ClpSolve solveOptions = solveOptionsIn; std::string nameAlgorithm; if (algorithm != 5) { if (algorithm == 0) { method = ClpSolve::useDual; nameAlgorithm = "dual"; } else if (algorithm == 1) { method = ClpSolve::usePrimalorSprint; nameAlgorithm = "primal"; } else if (algorithm == 3) { method = ClpSolve::automatic; nameAlgorithm = "either"; } else { nameAlgorithm = "barrier-slow"; #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK) solveOptions.setSpecialOption(4, 4); nameAlgorithm = "barrier-UFL"; #endif #ifdef COIN_HAS_WSMP solveOptions.setSpecialOption(4, 2); nameAlgorithm = "barrier-WSSMP"; #endif #ifdef COIN_HAS_MUMPS solveOptions.setSpecialOption(4, 6); nameAlgorithm = "barrier-MUMPS"; #endif method = ClpSolve::useBarrier; } solveOptions.setSolveType(method); } else { int iAlg = bestStrategy[m]; int presolveOff = iAlg / 100; iAlg = iAlg % 100; if( !barrierAvailable && iAlg == 0) { if (nRows[m] != 2172) iAlg = 5; // try primal else iAlg = 3; // d2q06c } solveOptions = setupForSolve(iAlg, nameAlgorithm, 0); if (presolveOff) solveOptions.setPresolveType(ClpSolve::presolveOff); } if (doVector) { ClpMatrixBase * matrix = solution.clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } #if FACTORIZATION_STATISTICS double timesOne[3*3*3*3*3]; memset(timesOne,0,sizeof(timesOne)); int iterationsOne[3*3*3*3*3]; memset(iterationsOne,0,sizeof(iterationsOne)); AnySimplex saveModel(solution); double time2; #if 0 solution.initialSolve(solveOptions); time2 = CoinCpuTime() - time1; timeTaken += time2; printf("%s took %g seconds using algorithm %s\n", fn.c_str(), time2, nameAlgorithm.c_str()); #endif #define loA 1 #define loB 0 #define loC 0 #define loD 1 #define loE 1 #define hiA 2 #define hiB 1 #define hiC 1 #define hiD 2 #define hiE 2 time2 = CoinCpuTime(); for (int iA=loA;iA(iterationsOne[i]); if (timesOne[i]setDetailMessage(1, 102); model.setFactorizationFrequency(10); model.primal(); model.primal(0, 3); model.setObjCoeff(3, -2.9473684210526314); model.primal(0, 3); // Write saved solutions int nc = model.getNumCols(); size_t s; std::deque fep = messageHandler.getFeasibleExtremePoints(); size_t numSavedSolutions = fep.size(); for ( s = 0; s < numSavedSolutions; ++s ) { const StdVectorDouble & solnVec = fep[s]; for ( int c = 0; c < nc; ++c ) { if (fabs(solnVec[c]) > 1.0e-8) std::cout << "Saved Solution: " << s << " ColNum: " << c << " Value: " << solnVec[c] << std::endl; } } // Solve again without scaling // and maximize then minimize messageHandler.clearFeasibleExtremePoints(); model.scaling(0); model.setOptimizationDirection(-1); model.primal(); model.setOptimizationDirection(1); model.primal(); fep = messageHandler.getFeasibleExtremePoints(); numSavedSolutions = fep.size(); for ( s = 0; s < numSavedSolutions; ++s ) { const StdVectorDouble & solnVec = fep[s]; for ( int c = 0; c < nc; ++c ) { if (fabs(solnVec[c]) > 1.0e-8) std::cout << "Saved Solution: " << s << " ColNum: " << c << " Value: " << solnVec[c] << std::endl; } } } else { std::cerr << "Error reading exmip1 from sample data. Skipping test." << std::endl; } } #endif // Test dual ranging { CoinMpsIO m; std::string fn = dirSample + "exmip1"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model.primal(); int which[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; double costIncrease[13]; int sequenceIncrease[13]; double costDecrease[13]; int sequenceDecrease[13]; // ranging model.dualRanging(13, which, costIncrease, sequenceIncrease, costDecrease, sequenceDecrease); int i; for ( i = 0; i < 13; i++) printf("%d increase %g %d, decrease %g %d\n", i, costIncrease[i], sequenceIncrease[i], costDecrease[i], sequenceDecrease[i]); assert (fabs(costDecrease[3]) < 1.0e-4); assert (fabs(costIncrease[7] - 1.0) < 1.0e-4); model.setOptimizationDirection(-1); { int j; double * obj = model.objective(); int n = model.numberColumns(); for (j = 0; j < n; j++) obj[j] *= -1.0; } double costIncrease2[13]; int sequenceIncrease2[13]; double costDecrease2[13]; int sequenceDecrease2[13]; // ranging model.dualRanging(13, which, costIncrease2, sequenceIncrease2, costDecrease2, sequenceDecrease2); for (i = 0; i < 13; i++) { assert (fabs(costIncrease[i] - costDecrease2[i]) < 1.0e-6); assert (fabs(costDecrease[i] - costIncrease2[i]) < 1.0e-6); assert (sequenceIncrease[i] == sequenceDecrease2[i]); assert (sequenceDecrease[i] == sequenceIncrease2[i]); } // Now delete all rows and see what happens model.deleteRows(model.numberRows(), which); model.primal(); // ranging if (!model.dualRanging(8, which, costIncrease, sequenceIncrease, costDecrease, sequenceDecrease)) { for (i = 0; i < 8; i++) { printf("%d increase %g %d, decrease %g %d\n", i, costIncrease[i], sequenceIncrease[i], costDecrease[i], sequenceDecrease[i]); } } } else { std::cerr << "Error reading exmip1 from sample data. Skipping test." << std::endl; } } // Test primal ranging { CoinMpsIO m; std::string fn = dirSample + "exmip1"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model.primal(); int which[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; double valueIncrease[13]; int sequenceIncrease[13]; double valueDecrease[13]; int sequenceDecrease[13]; // ranging model.primalRanging(13, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); int i; for ( i = 0; i < 13; i++) printf("%d increase %g %d, decrease %g %d\n", i, valueIncrease[i], sequenceIncrease[i], valueDecrease[i], sequenceDecrease[i]); assert (fabs(valueIncrease[3] - 0.642857) < 1.0e-4); assert (fabs(valueIncrease[8] - 2.95113) < 1.0e-4); } else { std::cerr << "Error reading exmip1 from sample data. Skipping test." << std::endl; } #if 0 // out until I find optimization bug // Test parametrics ClpSimplexOther * model2 = (ClpSimplexOther *) (&model); double rhs[] = { 1.0, 2.0, 3.0, 4.0, 5.0}; double endingTheta = 1.0; model2->scaling(0); model2->setLogLevel(63); model2->parametrics(0.0, endingTheta, 0.1, NULL, NULL, rhs, rhs, NULL); #endif } // Test binv etc { /* Wolsey : Page 130 max 4x1 - x2 7x1 - 2x2 <= 14 x2 <= 3 2x1 - 2x2 <= 3 x1 in Z+, x2 >= 0 note slacks are -1 in Clp so signs may be different */ int n_cols = 2; int n_rows = 3; double obj[2] = { -4.0, 1.0}; double collb[2] = {0.0, 0.0}; double colub[2] = {COIN_DBL_MAX, COIN_DBL_MAX}; double rowlb[3] = { -COIN_DBL_MAX, -COIN_DBL_MAX, -COIN_DBL_MAX}; double rowub[3] = {14.0, 3.0, 3.0}; int rowIndices[5] = {0, 2, 0, 1, 2}; int colIndices[5] = {0, 0, 1, 1, 1}; double elements[5] = {7.0, 2.0, -2.0, 1.0, -2.0}; CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5); ClpSimplex model; model.loadProblem(M, collb, colub, obj, rowlb, rowub); model.dual(0, 1); // keep factorization //check that the tableau matches wolsey (B-1 A) // slacks in second part of binvA double * binvA = reinterpret_cast (malloc((n_cols + n_rows) * sizeof(double))); printf("B-1 A by row\n"); int i; for( i = 0; i < n_rows; i++) { model.getBInvARow(i, binvA, binvA + n_cols); printf("row: %d -> ", i); for(int j = 0; j < n_cols + n_rows; j++) { printf("%g, ", binvA[j]); } printf("\n"); } // See if can re-use factorization AND arrays model.primal(0, 3 + 4); // keep factorization // And do by column printf("B-1 A by column\n"); for( i = 0; i < n_rows + n_cols; i++) { model.getBInvACol(i, binvA); printf("column: %d -> ", i); for(int j = 0; j < n_rows; j++) { printf("%g, ", binvA[j]); } printf("\n"); } /* Do twice - without and with scaling */ // set scaling off model.scaling(0); for (int iPass = 0; iPass < 2; iPass++) { model.primal(0, 3 + 4); // keep factorization const double * rowScale = model.rowScale(); const double * columnScale = model.columnScale(); if (!iPass) assert (!rowScale); else assert (rowScale); // only true for this example /* has to be exactly correct as in OsiClpsolverInterface.cpp (also redo each pass as may change */ printf("B-1 A"); for( i = 0; i < n_rows; i++) { model.getBInvARow(i, binvA, binvA + n_cols); printf("\nrow: %d -> ", i); int j; // First columns for(j = 0; j < n_cols; j++) { if (binvA[j]) { printf("(%d %g), ", j, binvA[j]); } } // now rows for(j = 0; j < n_rows; j++) { if (binvA[j+n_cols]) { printf("(%d %g), ", j + n_cols, binvA[j+n_cols]); } } } printf("\n"); printf("And by column (trickier)"); const int * pivotVariable = model.pivotVariable(); for( i = 0; i < n_cols + n_rows; i++) { model.getBInvACol(i, binvA); printf("\ncolumn: %d -> ", i); for(int j = 0; j < n_rows; j++) { if (binvA[j]) { // need to know pivot variable for +1/-1 (slack) and row/column scaling int pivot = pivotVariable[j]; if (pivot < n_cols) { // scaled coding is in just in case if (!columnScale) { printf("(%d %g), ", j, binvA[j]); } else { printf("(%d %g), ", j, binvA[j]*columnScale[pivot]); } } else { if (!rowScale) { printf("(%d %g), ", j, binvA[j]); } else { printf("(%d %g), ", j, binvA[j] / rowScale[pivot-n_cols]); } } } } } printf("\n"); printf("binvrow"); for( i = 0; i < n_rows; i++) { model.getBInvRow(i, binvA); printf("\nrow: %d -> ", i); int j; for (j = 0; j < n_rows; j++) { if (binvA[j]) printf("(%d %g), ", j, binvA[j]); } } printf("\n"); printf("And by column "); for( i = 0; i < n_rows; i++) { model.getBInvCol(i, binvA); printf("\ncol: %d -> ", i); int j; for (j = 0; j < n_rows; j++) { if (binvA[j]) printf("(%d %g), ", j, binvA[j]); } } printf("\n"); // now deal with next pass if (!iPass) { // get scaling for testing model.scaling(1); } } free(binvA); model.setColUpper(1, 2.0); model.dual(0, 2 + 4); // use factorization and arrays model.dual(0, 2); // hopefully will not use factorization model.primal(0, 3 + 4); // keep factorization // but say basis has changed model.setWhatsChanged(model.whatsChanged()&(~512)); model.dual(0, 2); // hopefully will not use factorization } // test steepest edge { CoinMpsIO m; std::string fn = dirSample + "finnis"; int returnCode = m.readMps(fn.c_str(), "mps"); if (returnCode) { // probable cause is that gz not there fprintf(stderr, "Unable to open finnis.mps in %s\n", dirSample.c_str()); fprintf(stderr, "Most probable cause is that sample data is not available, or finnis.mps is gzipped i.e. finnis.mps.gz and libz has not been activated\n"); fprintf(stderr, "Either gunzip files or edit Makefiles/Makefile.location to get libz\n"); } else { ClpModel model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); ClpSimplex solution(model); solution.scaling(1); solution.setDualBound(1.0e8); //solution.factorization()->maximumPivots(1); //solution.setLogLevel(3); solution.setDualTolerance(1.0e-7); // set objective sense, ClpDualRowSteepest steep; solution.setDualRowPivotAlgorithm(steep); solution.setDblParam(ClpObjOffset, m.objectiveOffset()); solution.dual(); } } // test normal solution { CoinMpsIO m; std::string fn = dirSample + "afiro"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; ClpModel model; // do twice - without and with scaling int iPass; for (iPass = 0; iPass < 2; iPass++) { // explicit row objective for testing int nr = m.getNumRows(); double * rowObj = new double[nr]; CoinFillN(rowObj, nr, 0.0); model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper(), rowObj); delete [] rowObj; solution = ClpSimplex(model); if (iPass) { solution.scaling(); } solution.dual(); solution.dual(); // test optimal assert (solution.status() == 0); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); CoinPackedVector colsol(numberColumns, solution.primalColumnSolution()); double * objective = solution.objective(); #ifndef NDEBUG double objValue = colsol.dotProduct(objective); #endif CoinRelFltEq eq(1.0e-8); assert(eq(objValue, -4.6475314286e+02)); solution.dual(); assert(eq(solution.objectiveValue(), -4.6475314286e+02)); double * lower = solution.columnLower(); double * upper = solution.columnUpper(); double * sol = solution.primalColumnSolution(); double * result = new double[numberColumns]; CoinFillN ( result, numberColumns, 0.0); solution.matrix()->transposeTimes(solution.dualRowSolution(), result); int iRow , iColumn; // see if feasible and dual feasible for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = sol[iColumn]; assert(value < upper[iColumn] + 1.0e-8); assert(value > lower[iColumn] - 1.0e-8); value = objective[iColumn] - result[iColumn]; assert (value > -1.0e-5); if (sol[iColumn] > 1.0e-5) assert (value < 1.0e-5); } delete [] result; result = new double[numberRows]; CoinFillN ( result, numberRows, 0.0); solution.matrix()->times(colsol, result); lower = solution.rowLower(); upper = solution.rowUpper(); sol = solution.primalRowSolution(); #ifndef NDEBUG for (iRow = 0; iRow < numberRows; iRow++) { double value = result[iRow]; assert(eq(value, sol[iRow])); assert(value < upper[iRow] + 1.0e-8); assert(value > lower[iRow] - 1.0e-8); } #endif delete [] result; // test row objective double * rowObjective = solution.rowObjective(); CoinDisjointCopyN(solution.dualRowSolution(), numberRows, rowObjective); CoinDisjointCopyN(solution.dualColumnSolution(), numberColumns, objective); // this sets up all slack basis solution.createStatus(); solution.dual(); CoinFillN(rowObjective, numberRows, 0.0); CoinDisjointCopyN(m.getObjCoefficients(), numberColumns, objective); solution.dual(); } } else { std::cerr << "Error reading afiro from sample data. Skipping test." << std::endl; } } // test unbounded { CoinMpsIO m; std::string fn = dirSample + "brandy"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; // do twice - without and with scaling int iPass; for (iPass = 0; iPass < 2; iPass++) { solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (iPass) solution.scaling(); solution.setOptimizationDirection(-1); // test unbounded and ray #ifdef DUAL solution.setDualBound(100.0); solution.dual(); #else solution.primal(); #endif assert (solution.status() == 2); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); double * lower = solution.columnLower(); double * upper = solution.columnUpper(); double * sol = solution.primalColumnSolution(); double * ray = solution.unboundedRay(); double * objective = solution.objective(); double objChange = 0.0; int iRow , iColumn; // make sure feasible and columns form ray for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = sol[iColumn]; assert(value < upper[iColumn] + 1.0e-8); assert(value > lower[iColumn] - 1.0e-8); value = ray[iColumn]; if (value > 0.0) assert(upper[iColumn] > 1.0e30); else if (value < 0.0) assert(lower[iColumn] < -1.0e30); objChange += value * objective[iColumn]; } // make sure increasing objective assert(objChange > 0.0); double * result = new double[numberRows]; CoinFillN ( result, numberRows, 0.0); solution.matrix()->times(sol, result); lower = solution.rowLower(); upper = solution.rowUpper(); sol = solution.primalRowSolution(); #ifndef NDEBUG for (iRow = 0; iRow < numberRows; iRow++) { double value = result[iRow]; assert(eq(value, sol[iRow])); assert(value < upper[iRow] + 2.0e-8); assert(value > lower[iRow] - 2.0e-8); } #endif CoinFillN ( result, numberRows, 0.0); solution.matrix()->times(ray, result); // there may be small differences (especially if scaled) for (iRow = 0; iRow < numberRows; iRow++) { double value = result[iRow]; if (value > 1.0e-8) assert(upper[iRow] > 1.0e30); else if (value < -1.0e-8) assert(lower[iRow] < -1.0e30); } delete [] result; delete [] ray; } } else { std::cerr << "Error reading brandy from sample data. Skipping test." << std::endl; } } // test infeasible { CoinMpsIO m; std::string fn = dirSample + "brandy"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; // do twice - without and with scaling int iPass; for (iPass = 0; iPass < 2; iPass++) { solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (iPass) solution.scaling(); // test infeasible and ray solution.columnUpper()[0] = 0.0; #ifdef DUAL solution.setDualBound(100.0); solution.dual(); #else solution.primal(); #endif assert (solution.status() == 1); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); double * lower = solution.rowLower(); double * upper = solution.rowUpper(); double * ray = solution.infeasibilityRay(); assert(ray); // construct proof of infeasibility int iRow , iColumn; double lo = 0.0, up = 0.0; int nl = 0, nu = 0; for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > -1.0e20) { lo += ray[iRow] * lower[iRow]; } else { if (ray[iRow] > 1.0e-8) nl++; } if (upper[iRow] < 1.0e20) { up += ray[iRow] * upper[iRow]; } else { if (ray[iRow] > 1.0e-8) nu++; } } if (nl) lo = -1.0e100; if (nu) up = 1.0e100; double * result = new double[numberColumns]; double lo2 = 0.0, up2 = 0.0; CoinFillN ( result, numberColumns, 0.0); solution.matrix()->transposeTimes(ray, result); lower = solution.columnLower(); upper = solution.columnUpper(); nl = nu = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (result[iColumn] > 1.0e-8) { if (lower[iColumn] > -1.0e20) lo2 += result[iColumn] * lower[iColumn]; else nl++; if (upper[iColumn] < 1.0e20) up2 += result[iColumn] * upper[iColumn]; else nu++; } else if (result[iColumn] < -1.0e-8) { if (lower[iColumn] > -1.0e20) up2 += result[iColumn] * lower[iColumn]; else nu++; if (upper[iColumn] < 1.0e20) lo2 += result[iColumn] * upper[iColumn]; else nl++; } } if (nl) lo2 = -1.0e100; if (nu) up2 = 1.0e100; // make sure inconsistency assert(lo2 > up || up2 < lo); delete [] result; delete [] ray; } } else { std::cerr << "Error reading brandy from sample data. Skipping test." << std::endl; } } // test delete and add { CoinMpsIO m; std::string fn = dirSample + "brandy"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); solution.dual(); CoinRelFltEq eq(1.0e-8); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); double * saveObj = new double [numberColumns]; double * saveLower = new double[numberRows+numberColumns]; double * saveUpper = new double[numberRows+numberColumns]; int * which = new int [numberRows+numberColumns]; int numberElements = m.getMatrixByCol()->getNumElements(); int * starts = new int[numberRows+numberColumns]; int * index = new int[numberElements]; double * element = new double[numberElements]; const CoinBigIndex * startM; const int * lengthM; const int * indexM; const double * elementM; int n, nel; // delete non basic columns n = 0; nel = 0; int iRow , iColumn; const double * lower = m.getColLower(); const double * upper = m.getColUpper(); const double * objective = m.getObjCoefficients(); startM = m.getMatrixByCol()->getVectorStarts(); lengthM = m.getMatrixByCol()->getVectorLengths(); indexM = m.getMatrixByCol()->getIndices(); elementM = m.getMatrixByCol()->getElements(); starts[0] = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (solution.getColumnStatus(iColumn) != ClpSimplex::basic) { saveObj[n] = objective[iColumn]; saveLower[n] = lower[iColumn]; saveUpper[n] = upper[iColumn]; int j; for (j = startM[iColumn]; j < startM[iColumn] + lengthM[iColumn]; j++) { index[nel] = indexM[j]; element[nel++] = elementM[j]; } which[n++] = iColumn; starts[n] = nel; } } solution.deleteColumns(n, which); solution.dual(); // Put back solution.addColumns(n, saveLower, saveUpper, saveObj, starts, index, element); solution.dual(); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); // Delete all columns and add back n = 0; nel = 0; starts[0] = 0; lower = m.getColLower(); upper = m.getColUpper(); objective = m.getObjCoefficients(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { saveObj[n] = objective[iColumn]; saveLower[n] = lower[iColumn]; saveUpper[n] = upper[iColumn]; int j; for (j = startM[iColumn]; j < startM[iColumn] + lengthM[iColumn]; j++) { index[nel] = indexM[j]; element[nel++] = elementM[j]; } which[n++] = iColumn; starts[n] = nel; } solution.deleteColumns(n, which); solution.dual(); // Put back solution.addColumns(n, saveLower, saveUpper, saveObj, starts, index, element); solution.dual(); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); // reload with original solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); // delete half rows n = 0; nel = 0; lower = m.getRowLower(); upper = m.getRowUpper(); startM = m.getMatrixByRow()->getVectorStarts(); lengthM = m.getMatrixByRow()->getVectorLengths(); indexM = m.getMatrixByRow()->getIndices(); elementM = m.getMatrixByRow()->getElements(); starts[0] = 0; for (iRow = 0; iRow < numberRows; iRow++) { if ((iRow & 1) == 0) { saveLower[n] = lower[iRow]; saveUpper[n] = upper[iRow]; int j; for (j = startM[iRow]; j < startM[iRow] + lengthM[iRow]; j++) { index[nel] = indexM[j]; element[nel++] = elementM[j]; } which[n++] = iRow; starts[n] = nel; } } solution.deleteRows(n, which); solution.dual(); // Put back solution.addRows(n, saveLower, saveUpper, starts, index, element); solution.dual(); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); solution.writeMps("yy.mps"); // Delete all rows n = 0; nel = 0; lower = m.getRowLower(); upper = m.getRowUpper(); starts[0] = 0; for (iRow = 0; iRow < numberRows; iRow++) { saveLower[n] = lower[iRow]; saveUpper[n] = upper[iRow]; int j; for (j = startM[iRow]; j < startM[iRow] + lengthM[iRow]; j++) { index[nel] = indexM[j]; element[nel++] = elementM[j]; } which[n++] = iRow; starts[n] = nel; } solution.deleteRows(n, which); solution.dual(); // Put back solution.addRows(n, saveLower, saveUpper, starts, index, element); solution.dual(); solution.writeMps("xx.mps"); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); // Zero out status array to give some interest memset(solution.statusArray() + numberColumns, 0, numberRows); solution.primal(1); assert(eq(solution.objectiveValue(), 1.5185098965e+03)); // Delete all columns and rows n = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { which[n++] = iColumn; starts[n] = nel; } solution.deleteColumns(n, which); n = 0; for (iRow = 0; iRow < numberRows; iRow++) { which[n++] = iRow; starts[n] = nel; } solution.deleteRows(n, which); delete [] saveObj; delete [] saveLower; delete [] saveUpper; delete [] which; delete [] starts; delete [] index; delete [] element; } else { std::cerr << "Error reading brandy from sample data. Skipping test." << std::endl; } } #if 1 // Test barrier { CoinMpsIO m; std::string fn = dirSample + "exmip1"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpInterior solution; solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); solution.primalDual(); } else { std::cerr << "Error reading exmip1 from sample data. Skipping test." << std::endl; } } #endif // test network #define QUADRATIC if (1) { std::string fn = dirSample + "input.130"; int numberColumns; int numberRows; FILE * fp = fopen(fn.c_str(), "r"); if (!fp) { // Try in Data/Sample fn = "Data/Sample/input.130"; fp = fopen(fn.c_str(), "r"); } if (!fp) { fprintf(stderr, "Unable to open file input.130 in dirSample or Data/Sample directory\n"); } else { int problem; char temp[100]; // read and skip int x = fscanf(fp, "%s", temp); if (x < 0) throw("bad fscanf"); assert (!strcmp(temp, "BEGIN")); x = fscanf(fp, "%*s %*s %d %d %*s %*s %d %*s", &problem, &numberRows, &numberColumns); if (x < 0) throw("bad fscanf"); // scan down to SUPPLY while (fgets(temp, 100, fp)) { if (!strncmp(temp, "SUPPLY", 6)) break; } if (strncmp(temp, "SUPPLY", 6)) { fprintf(stderr, "Unable to find SUPPLY\n"); exit(2); } // get space for rhs double * lower = new double[numberRows]; double * upper = new double[numberRows]; int i; for (i = 0; i < numberRows; i++) { lower[i] = 0.0; upper[i] = 0.0; } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "ARCS", 4)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = -value; lower[row-1] = -value; } if (strncmp(temp, "ARCS", 4)) { fprintf(stderr, "Unable to find ARCS\n"); exit(2); } // number of columns may be underestimate int * head = new int[2*numberColumns]; int * tail = new int[2*numberColumns]; int * ub = new int[2*numberColumns]; int * cost = new int[2*numberColumns]; // ***** Remember to convert to C notation numberColumns = 0; while (fgets(temp, 100, fp)) { int iHead; int iTail; int iUb; int iCost; if (!strncmp(temp, "DEMAND", 6)) break; sscanf(temp, "%d %d %d %d", &iHead, &iTail, &iCost, &iUb); iHead--; iTail--; head[numberColumns] = iHead; tail[numberColumns] = iTail; ub[numberColumns] = iUb; cost[numberColumns] = iCost; numberColumns++; } if (strncmp(temp, "DEMAND", 6)) { fprintf(stderr, "Unable to find DEMAND\n"); exit(2); } // ***** Remember to convert to C notation while (fgets(temp, 100, fp)) { int row; int value; if (!strncmp(temp, "END", 3)) break; sscanf(temp, "%d %d", &row, &value); upper[row-1] = value; lower[row-1] = value; } if (strncmp(temp, "END", 3)) { fprintf(stderr, "Unable to find END\n"); exit(2); } printf("Problem %d has %d rows and %d columns\n", problem, numberRows, numberColumns); fclose(fp); ClpSimplex model; // now build model double * objective = new double[numberColumns]; double * lowerColumn = new double[numberColumns]; double * upperColumn = new double[numberColumns]; double * element = new double [2*numberColumns]; CoinBigIndex * start = new CoinBigIndex [numberColumns+1]; int * row = new int[2*numberColumns]; start[numberColumns] = 2 * numberColumns; for (i = 0; i < numberColumns; i++) { start[i] = 2 * i; element[2*i] = -1.0; element[2*i+1] = 1.0; row[2*i] = head[i]; row[2*i+1] = tail[i]; lowerColumn[i] = 0.0; upperColumn[i] = ub[i]; objective[i] = cost[i]; } // Create Packed Matrix CoinPackedMatrix matrix; int * lengths = NULL; matrix.assignMatrix(true, numberRows, numberColumns, 2 * numberColumns, element, row, start, lengths); // load model model.loadProblem(matrix, lowerColumn, upperColumn, objective, lower, upper); model.factorization()->maximumPivots(200 + model.numberRows() / 100); model.createStatus(); double time1 = CoinCpuTime(); model.dual(); std::cout << "Network problem, ClpPackedMatrix took " << CoinCpuTime() - time1 << " seconds" << std::endl; ClpPlusMinusOneMatrix * plusMinus = new ClpPlusMinusOneMatrix(matrix); assert (plusMinus->getIndices()); // would be zero if not +- one //ClpPlusMinusOneMatrix *plusminus_matrix; //plusminus_matrix = new ClpPlusMinusOneMatrix; //plusminus_matrix->passInCopy(numberRows, numberColumns, true, plusMinus->getMutableIndices(), // plusMinus->startPositive(),plusMinus->startNegative()); model.loadProblem(*plusMinus, lowerColumn, upperColumn, objective, lower, upper); //model.replaceMatrix( plusminus_matrix , true); delete plusMinus; //model.createStatus(); //model.initialSolve(); //model.writeMps("xx.mps"); model.factorization()->maximumPivots(200 + model.numberRows() / 100); model.createStatus(); time1 = CoinCpuTime(); model.dual(); std::cout << "Network problem, ClpPlusMinusOneMatrix took " << CoinCpuTime() - time1 << " seconds" << std::endl; ClpNetworkMatrix network(numberColumns, head, tail); model.loadProblem(network, lowerColumn, upperColumn, objective, lower, upper); model.factorization()->maximumPivots(200 + model.numberRows() / 100); model.createStatus(); time1 = CoinCpuTime(); model.dual(); std::cout << "Network problem, ClpNetworkMatrix took " << CoinCpuTime() - time1 << " seconds" << std::endl; delete [] lower; delete [] upper; delete [] head; delete [] tail; delete [] ub; delete [] cost; delete [] objective; delete [] lowerColumn; delete [] upperColumn; } } #ifdef QUADRATIC // Test quadratic to solve linear if (1) { CoinMpsIO m; std::string fn = dirSample + "exmip1"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); //solution.dual(); // get quadratic part int numberColumns = solution.numberColumns(); int * start = new int [numberColumns+1]; int * column = new int[numberColumns]; double * element = new double[numberColumns]; int i; start[0] = 0; int n = 0; int kk = numberColumns - 1; int kk2 = numberColumns - 1; for (i = 0; i < numberColumns; i++) { if (i >= kk) { column[n] = i; if (i >= kk2) element[n] = 1.0e-1; else element[n] = 0.0; n++; } start[i+1] = n; } // Load up objective solution.loadQuadraticObjective(numberColumns, start, column, element); delete [] start; delete [] column; delete [] element; //solution.quadraticSLP(50,1.0e-4); CoinRelFltEq eq(1.0e-4); //assert(eq(objValue,820.0)); //solution.setLogLevel(63); solution.primal(); printSol(solution); //assert(eq(objValue,3.2368421)); //exit(77); } else { std::cerr << "Error reading exmip1 from sample data. Skipping test." << std::endl; } } // Test quadratic if (1) { CoinMpsIO m; std::string fn = dirSample + "share2qp"; //fn = "share2qpb"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model.dual(); // get quadratic part int * start = NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL, start, column, element, 2); int column2[200]; double element2[200]; int start2[80]; int j; start2[0] = 0; int nel = 0; bool good = false; for (j = 0; j < 79; j++) { if (start[j] == start[j+1]) { column2[nel] = j; element2[nel] = 0.0; nel++; } else { int i; for (i = start[j]; i < start[j+1]; i++) { column2[nel] = column[i]; element2[nel++] = element[i]; } } start2[j+1] = nel; } // Load up objective if (good) model.loadQuadraticObjective(model.numberColumns(), start2, column2, element2); else model.loadQuadraticObjective(model.numberColumns(), start, column, element); delete [] start; delete [] column; delete [] element; int numberColumns = model.numberColumns(); model.scaling(0); #if 0 model.nonlinearSLP(50, 1.0e-4); #else // Get feasible ClpObjective * saveObjective = model.objectiveAsObject()->clone(); ClpLinearObjective zeroObjective(NULL, numberColumns); model.setObjective(&zeroObjective); model.dual(); model.setObjective(saveObjective); delete saveObjective; #endif //model.setLogLevel(63); //exit(77); model.setFactorizationFrequency(10); model.primal(); printSol(model); #ifndef NDEBUG double objValue = model.getObjValue(); #endif CoinRelFltEq eq(1.0e-4); assert(eq(objValue, -400.92)); // and again for barrier model.barrier(false); //printSol(model); model.allSlackBasis(); model.primal(); //printSol(model); } else { std::cerr << "Error reading share2qp from sample data. Skipping test." << std::endl; } } if (0) { CoinMpsIO m; std::string fn = "./beale"; //fn = "./jensen"; if (m.readMps(fn.c_str(), "mps") == 0) { ClpSimplex solution; solution.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); solution.setDblParam(ClpObjOffset, m.objectiveOffset()); solution.dual(); // get quadratic part int * start = NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL, start, column, element, 2); // Load up objective solution.loadQuadraticObjective(solution.numberColumns(), start, column, element); delete [] start; delete [] column; delete [] element; solution.primal(1); solution.nonlinearSLP(50, 1.0e-4); double objValue = solution.getObjValue(); CoinRelFltEq eq(1.0e-4); assert(eq(objValue, 0.5)); solution.primal(); objValue = solution.getObjValue(); assert(eq(objValue, 0.5)); } else { std::cerr << "Error reading beale.mps. Skipping test." << std::endl; } } #endif // Test CoinStructuredModel { // Sub block CoinModel sub; { // matrix data //deliberate hiccup of 2 between 0 and 1 CoinBigIndex start[5] = {0, 4, 7, 8, 9}; int length[5] = {2, 3, 1, 1, 1}; int rows[11] = {0, 2, -1, -1, 0, 1, 2, 0, 1, 2}; double elements[11] = {7.0, 2.0, 1.0e10, 1.0e10, -2.0, 1.0, -2.0, 1, 1, 1}; CoinPackedMatrix matrix(true, 3, 5, 8, elements, rows, start, length); // by row matrix.reverseOrdering(); const double * element = matrix.getElements(); const int * column = matrix.getIndices(); const CoinBigIndex * rowStart = matrix.getVectorStarts(); const int * rowLength = matrix.getVectorLengths(); // rim data //double objective[5]={-4.0,1.0,0.0,0.0,0.0}; double rowLower[3] = {14.0, 3.0, 3.0}; double rowUpper[3] = {14.0, 3.0, 3.0}; //double columnLower[5]={0.0,0.0,0.0,0.0,0.0}; //double columnUpper[5]={100.0,100.0,100.0,100.0,100.0}; for (int i = 0; i < 3; i++) { sub.addRow(rowLength[i], column + rowStart[i], element + rowStart[i], rowLower[i], rowUpper[i]); } //for (int i=0;i<5;i++) { //sub.setColumnBounds(i,columnLower[i],columnUpper[i]); //sub.setColumnObjective(i,objective[i]); //} sub.convertMatrix(); } // Top CoinModel top; { // matrix data CoinBigIndex start[5] = {0, 2, 4, 6, 8}; int length[5] = {2, 2, 2, 2, 2}; int rows[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; double elements[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; CoinPackedMatrix matrix(true, 2, 5, 8, elements, rows, start, length); // by row matrix.reverseOrdering(); const double * element = matrix.getElements(); const int * column = matrix.getIndices(); const CoinBigIndex * rowStart = matrix.getVectorStarts(); const int * rowLength = matrix.getVectorLengths(); // rim data double objective[5] = { -4.0, 1.0, 0.0, 0.0, 0.0}; //double rowLower[3]={14.0,3.0,3.0}; //double rowUpper[3]={14.0,3.0,3.0}; double columnLower[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; double columnUpper[5] = {100.0, 100.0, 100.0, 100.0, 100.0}; for (int i = 0; i < 2; i++) { top.addRow(rowLength[i], column + rowStart[i], element + rowStart[i], -COIN_DBL_MAX, COIN_DBL_MAX); } for (int i = 0; i < 5; i++) { top.setColumnBounds(i, columnLower[i], columnUpper[i]); top.setColumnObjective(i, objective[i]); } top.convertMatrix(); } // Create a structured model CoinStructuredModel structured; int numberBlocks = 5; for (int i = 0; i < numberBlocks; i++) { std::string topName = "row_master"; std::string blockName = "block_"; char bName = static_cast('a' + static_cast(i)); blockName.append(1, bName); structured.addBlock(topName, blockName, top); structured.addBlock(blockName, blockName, sub); } // Set rhs on first block CoinModel * first = structured.coinBlock(0); for (int i = 0; i < 2; i++) { first->setRowLower(i, 0.0); first->setRowUpper(i, 100.0); } // Refresh whats set structured.refresh(0); // Could perturb stuff, but for first go don't bother ClpSimplex fullModel; // There is no original stuff set - think fullModel.loadProblem(structured, false); fullModel.dual(); fullModel.dropNames(); fullModel.writeMps("test.mps"); // Make up very simple nested model - not realistic // Create a structured model CoinStructuredModel structured2; numberBlocks = 3; for (int i = 0; i < numberBlocks; i++) { std::string blockName = "block_"; char bName = static_cast('a' + static_cast(i)); blockName.append(1, bName); structured2.addBlock(blockName, blockName, structured); } fullModel.loadProblem(structured2, false); fullModel.dual(); fullModel.dropNames(); fullModel.writeMps("test2.mps"); } } Clp-1.15.10/src/AbcMatrix.hpp0000644000076600007660000005232312101105055014220 0ustar coincoin/* $Id: AbcMatrix.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcMatrix_H #define AbcMatrix_H #include "CoinPragma.hpp" #include "ClpMatrixBase.hpp" #include "AbcSimplex.hpp" #include "CoinAbcHelperFunctions.hpp" /** This implements a scaled version of CoinPackedMatrix It may have THREE! copies 1) scaled CoinPackedMatrix without gaps 2) row copy non-basic,basic, fixed 3) vector copy */ class AbcMatrix2; class AbcMatrix3; class AbcMatrix { public: /**@name Useful methods */ //@{ /// Return a complete CoinPackedMatrix inline CoinPackedMatrix * getPackedMatrix() const { return matrix_; } /** Whether the packed matrix is column major ordered or not. */ inline bool isColOrdered() const { return true; } /** Number of entries in the packed matrix. */ inline CoinBigIndex getNumElements() const { return matrix_->getNumElements(); } /** Number of columns. */ inline int getNumCols() const { assert(matrix_->getNumCols()==model_->numberColumns());return matrix_->getNumCols(); } /** Number of rows. */ inline int getNumRows() const { assert(matrix_->getNumRows()==model_->numberRows());return matrix_->getNumRows(); } /// Sets model void setModel(AbcSimplex * model); /// A vector containing the elements in the packed matrix. inline const double * getElements() const { return matrix_->getElements(); } /// Mutable elements inline double * getMutableElements() const { return matrix_->getMutableElements(); } /// A vector containing the minor indices of the elements in the packed matrix. inline const int * getIndices() const { return matrix_->getIndices(); } /// A vector containing the minor indices of the elements in the packed matrix. inline int * getMutableIndices() const { return matrix_->getMutableIndices(); } /// Starts inline const CoinBigIndex * getVectorStarts() const { return matrix_->getVectorStarts(); } inline CoinBigIndex * getMutableVectorStarts() const { return matrix_->getMutableVectorStarts(); } /** The lengths of the major-dimension vectors. */ inline const int * getVectorLengths() const { return matrix_->getVectorLengths(); } /** The lengths of the major-dimension vectors. */ inline int * getMutableVectorLengths() const { return matrix_->getMutableVectorLengths(); } /// Row starts CoinBigIndex * rowStart() const; /// Row ends CoinBigIndex * rowEnd() const; /// Row elements double * rowElements() const; /// Row columns CoinSimplexInt * rowColumns() const; /** Returns a new matrix in reverse order without gaps */ CoinPackedMatrix * reverseOrderedCopy() const; /// Returns number of elements in column part of basis CoinBigIndex countBasis(const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis void fillBasis(const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinSimplexDouble * element); /// Fills in column part of basis void fillBasis(const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, long double * element); /** Scales and creates row copy */ void scale(int numberRowsAlreadyScaled); /// Creates row copy void createRowCopy(); /// Take out of useful void takeOutOfUseful(int sequence,CoinIndexedVector & spare); /// Put into useful void putIntofUseful(int sequence,CoinIndexedVector & spare); /// Put in and out for useful void inOutUseful(int sequenceIn,int sequenceOut); /// Make all useful void makeAllUseful(CoinIndexedVector & spare); /// Sort into useful void sortUseful(CoinIndexedVector & spare); /// Move largest in column to beginning (not used as doesn't help factorization) void moveLargestToStart(); /** Unpacks a column into an CoinIndexedVector */ void unpack(CoinIndexedVector & rowArray, int column) const ; /** Adds multiple of a column (or slack) into an CoinIndexedvector You can use quickAdd to add to vector */ void add(CoinIndexedVector & rowArray, int column, double multiplier) const ; //@} /**@name Matrix times vector methods */ //@{ /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ void timesModifyExcludingSlacks(double scalar, const double * x, double * y) const; /** Return y + A * scalar(+-1) *x in y. @pre x must be of size numColumns()+numRows() @pre y must be of size numRows() */ void timesModifyIncludingSlacks(double scalar, const double * x, double * y) const; /** Return A * scalar(+-1) *x in y. @pre x must be of size numColumns()+numRows() @pre y must be of size numRows() */ void timesIncludingSlacks(double scalar, const double * x, double * y) const; /** Return A * scalar(+-1) *x + y in y. @pre x must be of size numRows() @pre y must be of size numRows()+numColumns() */ void transposeTimesNonBasic(double scalar, const double * x, double * y) const; /** Return y - A * x in y. @pre x must be of size numRows() @pre y must be of size numRows()+numColumns() */ void transposeTimesAll(const double * x, double * y) const; /** Return y + A * scalar(+-1) *x in y. @pre x must be of size numRows() @pre y must be of size numRows() */ void transposeTimesBasic(double scalar, const double * x, double * y) const; /** Return x * scalar * A/code> in z. Note - x unpacked mode - z packed mode including slacks All these return atLo/atUp first then free/superbasic number of first set returned pivotVariable is extended to have that order reversePivotVariable used to update that list free/superbasic only stored in normal format can use spare array to get this effect may put djs alongside atLo/atUp Squashes small elements and knows about AbcSimplex */ int transposeTimesNonBasic(double scalar, const CoinIndexedVector & x, CoinIndexedVector & z) const; /// gets sorted tableau row and a possible value of theta double dualColumn1(const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /// gets sorted tableau row and a possible value of theta double dualColumn1Row(int iBlock, double upperThetaSlack, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /// gets sorted tableau row and a possible value of theta double dualColumn1RowFew(int iBlock, double upperThetaSlack, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /// gets sorted tableau row and a possible value of theta double dualColumn1Row2(double upperThetaSlack, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /// gets sorted tableau row and a possible value of theta double dualColumn1Row1(double upperThetaSlack, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /** gets sorted tableau row and a possible value of theta On input first,last give what to scan On output is number in tableauRow and candidateList */ void dualColumn1Part(int iBlock,int & sequenceIn, double & upperTheta, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const; /// rebalance for parallel void rebalance() const; /// Get sequenceIn when Dantzig int pivotColumnDantzig(const CoinIndexedVector & updates, CoinPartitionedVector & spare) const; /// Get sequenceIn when Dantzig (One block) int pivotColumnDantzig(int iBlock,bool doByRow,const CoinIndexedVector & updates, CoinPartitionedVector & spare, double & bestValue) const; /// gets tableau row - returns number of slacks in block int primalColumnRow(int iBlock,bool doByRow,const CoinIndexedVector & update, CoinPartitionedVector & tableauRow) const; /// gets tableau row and dj row - returns number of slacks in block int primalColumnRowAndDjs(int iBlock,const CoinIndexedVector & updateTableau, const CoinIndexedVector & updateDjs, CoinPartitionedVector & tableauRow) const; /** Chooses best weighted dj */ int chooseBestDj(int iBlock,const CoinIndexedVector & infeasibilities, const double * weights) const; /** does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs Returns best sequence */ int primalColumnDouble(int iBlock,CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, double * infeasibilities, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const; /** does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs Returns best sequence */ int primalColumnSparseDouble(int iBlock,CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, double * infeasibilities, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const; /** does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs Returns best sequence */ int primalColumnDouble(CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, CoinIndexedVector & infeasible, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const; /// gets subset updates void primalColumnSubset(int iBlock,const CoinIndexedVector & update, const CoinPartitionedVector & tableauRow, CoinPartitionedVector & weights) const; /// Partial pricing void partialPricing(double startFraction, double endFraction, int & bestSequence, int & numberWanted); /** Return x *A in z but just for indices Already in z. Note - z always packed mode */ void subsetTransposeTimes(const CoinIndexedVector & x, CoinIndexedVector & z) const; /// Return -x *A in z void transposeTimes(const CoinIndexedVector & x, CoinIndexedVector & z) const; //@} /**@name Other */ //@{ /// Returns CoinPackedMatrix (non const) inline CoinPackedMatrix * matrix() const { return matrix_; } /** Partial pricing tuning parameter - minimum number of "objects" to scan. e.g. number of Gub sets but could be number of variables */ inline int minimumObjectsScan() const { return minimumObjectsScan_; } inline void setMinimumObjectsScan(int value) { minimumObjectsScan_ = value; } /// Partial pricing tuning parameter - minimum number of negative reduced costs to get inline int minimumGoodReducedCosts() const { return minimumGoodReducedCosts_; } inline void setMinimumGoodReducedCosts(int value) { minimumGoodReducedCosts_ = value; } /// Current start of search space in matrix (as fraction) inline double startFraction() const { return startFraction_; } inline void setStartFraction(double value) { startFraction_ = value; } /// Current end of search space in matrix (as fraction) inline double endFraction() const { return endFraction_; } inline void setEndFraction(double value) { endFraction_ = value; } /// Current best reduced cost inline double savedBestDj() const { return savedBestDj_; } inline void setSavedBestDj(double value) { savedBestDj_ = value; } /// Initial number of negative reduced costs wanted inline int originalWanted() const { return originalWanted_; } inline void setOriginalWanted(int value) { originalWanted_ = value; } /// Current number of negative reduced costs which we still need inline int currentWanted() const { return currentWanted_; } inline void setCurrentWanted(int value) { currentWanted_ = value; } /// Current best sequence inline int savedBestSequence() const { return savedBestSequence_; } inline void setSavedBestSequence(int value) { savedBestSequence_ = value; } /// Start of each column block inline int * startColumnBlock() const {return startColumnBlock_;} /// Start of each block (in stored) inline const int * blockStart() const { return blockStart_;} inline bool gotRowCopy() const { return rowStart_!=0;} /// Start of each block (in stored) inline int blockStart(int block) const { return blockStart_[block];} /// Number of actual column blocks inline int numberColumnBlocks() const { return numberColumnBlocks_;} /// Number of actual row blocks inline int numberRowBlocks() const { return numberRowBlocks_;} //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ AbcMatrix(); /** Destructor */ ~AbcMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ AbcMatrix(const AbcMatrix&); /** The copy constructor from an CoinPackedMatrix. */ AbcMatrix(const CoinPackedMatrix&); /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ AbcMatrix (const AbcMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); AbcMatrix (const CoinPackedMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); AbcMatrix& operator=(const AbcMatrix&); /// Copy contents - resizing if necessary - otherwise re-use memory void copy(const AbcMatrix * from); //@} private: protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Data CoinPackedMatrix * matrix_; /// Model mutable AbcSimplex * model_; #if ABC_PARALLEL==0 #define NUMBER_ROW_BLOCKS 1 #define NUMBER_COLUMN_BLOCKS 1 #elif ABC_PARALLEL==1 #define NUMBER_ROW_BLOCKS 4 #define NUMBER_COLUMN_BLOCKS 4 #else #define NUMBER_ROW_BLOCKS 8 #define NUMBER_COLUMN_BLOCKS 8 #endif /** Start of each row (per block) - last lot are useless first all row starts for block 0, then for block2 so NUMBER_ROW_BLOCKS+2 times number rows */ CoinBigIndex * rowStart_; /// Values by row double * element_; /// Columns int * column_; /// Start of each column block mutable int startColumnBlock_[NUMBER_COLUMN_BLOCKS+1]; /// Start of each block (in stored) int blockStart_[NUMBER_ROW_BLOCKS+1]; /// Number of actual column blocks mutable int numberColumnBlocks_; /// Number of actual row blocks int numberRowBlocks_; //#define COUNT_COPY #ifdef COUNT_COPY #define MAX_COUNT 13 /// Start in elements etc CoinBigIndex countStart_[MAX_COUNT+1]; /// First column int countFirst_[MAX_COUNT+1]; // later int countEndUseful_[MAX_COUNT+1]; int * countRealColumn_; // later int * countInverseRealColumn_; CoinBigIndex * countStartLarge_; int * countRow_; double * countElement_; int smallestCount_; int largestCount_; #endif /// Special row copy //AbcMatrix2 * rowCopy_; /// Special column copy //AbcMatrix3 * columnCopy_; /// Current start of search space in matrix (as fraction) double startFraction_; /// Current end of search space in matrix (as fraction) double endFraction_; /// Best reduced cost so far double savedBestDj_; /// Initial number of negative reduced costs wanted int originalWanted_; /// Current number of negative reduced costs which we still need int currentWanted_; /// Saved best sequence in pricing int savedBestSequence_; /// Partial pricing tuning parameter - minimum number of "objects" to scan int minimumObjectsScan_; /// Partial pricing tuning parameter - minimum number of negative reduced costs to get int minimumGoodReducedCosts_; //@} }; #ifdef THREAD #include typedef struct { double acceptablePivot; const AbcSimplex * model; double * spare; int * spareIndex; double * arrayTemp; int * indexTemp; int * numberInPtr; double * bestPossiblePtr; double * upperThetaPtr; int * posFreePtr; double * freePivotPtr; int * numberOutPtr; const unsigned short * count; const double * pi; const CoinBigIndex * rowStart; const double * element; const unsigned short * column; int offset; int numberInRowArray; int numberLook; } dualColumn0Struct; #endif class AbcMatrix2 { public: /**@name Useful methods */ //@{ /** Return x * -1 * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about AbcSimplex */ void transposeTimes(const AbcSimplex * model, const CoinPackedMatrix * rowCopy, const CoinIndexedVector & x, CoinIndexedVector & spareArray, CoinIndexedVector & z) const; /// Returns true if copy has useful information inline bool usefulInfo() const { return rowStart_ != NULL; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ AbcMatrix2(); /** Constructor from copy. */ AbcMatrix2(AbcSimplex * model, const CoinPackedMatrix * rowCopy); /** Destructor */ ~AbcMatrix2(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ AbcMatrix2(const AbcMatrix2&); AbcMatrix2& operator=(const AbcMatrix2&); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Number of blocks int numberBlocks_; /// Number of rows int numberRows_; /// Column offset for each block (plus one at end) int * offset_; /// Counts of elements in each part of row mutable unsigned short * count_; /// Row starts mutable CoinBigIndex * rowStart_; /// columns within block unsigned short * column_; /// work arrays double * work_; #ifdef THREAD pthread_t * threadId_; dualColumn0Struct * info_; #endif //@} }; typedef struct { CoinBigIndex startElements_; // point to data int startIndices_; // point to column_ int numberInBlock_; int numberPrice_; // at beginning int numberElements_; // number elements per column } blockStruct3; class AbcMatrix3 { public: /**@name Useful methods */ //@{ /** Return x * -1 * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about AbcSimplex */ void transposeTimes(const AbcSimplex * model, const double * pi, CoinIndexedVector & output) const; /// Updates two arrays for steepest void transposeTimes2(const AbcSimplex * model, const double * pi, CoinIndexedVector & dj1, const double * piWeight, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ AbcMatrix3(); /** Constructor from copy. */ AbcMatrix3(AbcSimplex * model, const CoinPackedMatrix * columnCopy); /** Destructor */ ~AbcMatrix3(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ AbcMatrix3(const AbcMatrix3&); AbcMatrix3& operator=(const AbcMatrix3&); //@} /**@name Sort methods */ //@{ /** Sort blocks */ void sortBlocks(const AbcSimplex * model); /// Swap one variable void swapOne(const AbcSimplex * model, const AbcMatrix * matrix, int iColumn); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Number of blocks int numberBlocks_; /// Number of columns int numberColumns_; /// Column indices and reverse lookup (within block) int * column_; /// Starts for odd/long vectors CoinBigIndex * start_; /// Rows int * row_; /// Elements double * element_; /// Blocks (ordinary start at 0 and go to first block) blockStruct * block_; //@} }; #endif Clp-1.15.10/src/AbcDualRowSteepest.hpp0000644000076600007660000001115012101105055016037 0ustar coincoin/* $Id: AbcDualRowSteepest.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcDualRowSteepest_H #define AbcDualRowSteepest_H #include "AbcDualRowPivot.hpp" class CoinIndexedVector; //############################################################################# /** Dual Row Pivot Steepest Edge Algorithm Class See Forrest-Goldfarb paper for algorithm */ class AbcDualRowSteepest : public AbcDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow(); /** Updates weights and returns pivot alpha. Also does FT update */ virtual double updateWeights(CoinIndexedVector & input,CoinIndexedVector & updatedColumn); virtual double updateWeights1(CoinIndexedVector & input,CoinIndexedVector & updateColumn); virtual void updateWeightsOnly(CoinIndexedVector & input); /// Actually updates weights virtual void updateWeights2(CoinIndexedVector & input,CoinIndexedVector & updateColumn); /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes */ virtual void updatePrimalSolution(CoinIndexedVector & input, double theta); virtual void updatePrimalSolutionAndWeights(CoinIndexedVector & weightsVector, CoinIndexedVector & updateColumn, double theta); /** Saves any weights round factorization as pivot rows may change Save model May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) for strong branching - initialize (uninitialized) , infeasibilities */ virtual void saveWeights(AbcSimplex * model, int mode); /// Recompute infeasibilities virtual void recomputeInfeasibilities(); /// Gets rid of all arrays virtual void clearArrays(); /// Returns true if would not find any row virtual bool looksOptimal() const; //@} /** enums for persistence */ enum Persistence { normal = 0x00, // create (if necessary) and destroy keep = 0x01 // create (if necessary) and leave }; ///@name Constructors and destructors //@{ /** Default Constructor 0 is uninitialized, 1 full, 2 is partial uninitialized, 3 starts as 2 but may switch to 1. By partial is meant that the weights are updated as normal but only part of the infeasible basic variables are scanned. This can be faster on very easy problems. */ AbcDualRowSteepest(int mode = 3); /// Copy constructor AbcDualRowSteepest(const AbcDualRowSteepest &); /// Assignment operator AbcDualRowSteepest & operator=(const AbcDualRowSteepest& rhs); /// Fill most values void fill(const AbcDualRowSteepest& rhs); /// Destructor virtual ~AbcDualRowSteepest (); /// Clone virtual AbcDualRowPivot * clone(bool copyData = true) const; //@} /**@name gets and sets */ //@{ /// Mode inline int mode() const { return mode_; } /// Set/ get persistence inline void setPersistence(Persistence life) { persistence_ = life; } inline Persistence persistence() const { return persistence_ ; } /// Infeasible vector inline CoinIndexedVector * infeasible() const { return infeasible_;} /// Weights vector inline CoinIndexedVector * weights() const { return weights_;} /// Model inline AbcSimplex * model() const { return model_;} //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// norm saved before going into update double norm_; /// Ratio of size of factorization to number of rows double factorizationRatio_; /** Status 0) Normal -1) Needs initialization 1) Weights are stored by sequence number */ int state_; /** If 0 then we are using uninitialized weights, 1 then full, if 2 then uninitialized partial, 3 switchable */ int mode_; /// Life of weights Persistence persistence_; /// weight array CoinIndexedVector * weights_; /// square of infeasibility array (just for infeasible rows) CoinIndexedVector * infeasible_; /// save weight array (so we can use checkpoint) CoinIndexedVector * savedWeights_; //@} }; // For Devex stuff #undef DEVEX_TRY_NORM #define DEVEX_TRY_NORM 1.0e-8 #define DEVEX_ADD_ONE 1.0 #endif Clp-1.15.10/src/CoinAbcFactorization2.cpp0000644000076600007660000000101712101105055016450 0ustar coincoin/* $Id: CoinAbcFactorization2.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -2 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization2.cpp" #endif Clp-1.15.10/src/CoinAbcOrderedFactorization2.cpp0000644000076600007660000000107712101105055017763 0ustar coincoin/* $Id: CoinAbcOrderedFactorization2.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -2 #define ABC_ORDERED_FACTORIZATION #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization2.cpp" #endif Clp-1.15.10/src/ClpConstraintLinear.cpp0000644000076600007660000001555511510657452016305 0ustar coincoin/* $Id: ClpConstraintLinear.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "ClpConstraintLinear.hpp" #include "CoinSort.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpConstraintLinear::ClpConstraintLinear () : ClpConstraint() { type_ = 0; column_ = NULL; coefficient_ = NULL; numberColumns_ = 0; numberCoefficients_ = 0; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpConstraintLinear::ClpConstraintLinear (int row, int numberCoefficents , int numberColumns, const int * column, const double * coefficient) : ClpConstraint() { type_ = 0; rowNumber_ = row; numberColumns_ = numberColumns; numberCoefficients_ = numberCoefficents; column_ = CoinCopyOfArray(column, numberCoefficients_); coefficient_ = CoinCopyOfArray(coefficient, numberCoefficients_); CoinSort_2(column_, column_ + numberCoefficients_, coefficient_); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpConstraintLinear::ClpConstraintLinear (const ClpConstraintLinear & rhs) : ClpConstraint(rhs) { numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; column_ = CoinCopyOfArray(rhs.column_, numberCoefficients_); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberCoefficients_); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpConstraintLinear::~ClpConstraintLinear () { delete [] column_; delete [] coefficient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpConstraintLinear & ClpConstraintLinear::operator=(const ClpConstraintLinear& rhs) { if (this != &rhs) { delete [] column_; delete [] coefficient_; numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; column_ = CoinCopyOfArray(rhs.column_, numberCoefficients_); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberCoefficients_); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpConstraint * ClpConstraintLinear::clone() const { return new ClpConstraintLinear(*this); } // Returns gradient int ClpConstraintLinear::gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue, double & offset, bool useScaling, bool refresh) const { if (refresh || !lastGradient_) { functionValue_ = 0.0; if (!lastGradient_) lastGradient_ = new double[numberColumns_]; CoinZeroN(lastGradient_, numberColumns_); bool scaling = (model && model->rowScale() && useScaling); if (!scaling) { for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; double coefficient = coefficient_[i]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } else { // do scaling const double * columnScale = model->columnScale(); for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; // already scaled double coefficient = coefficient_[i] * columnScale[iColumn]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } } functionValue = functionValue_; offset = 0.0; CoinMemcpyN(lastGradient_, numberColumns_, gradient); return 0; } // Resize constraint void ClpConstraintLinear::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { #ifndef NDEBUG int lastColumn = column_[numberCoefficients_-1]; #endif assert (newNumberColumns > lastColumn); delete [] lastGradient_; lastGradient_ = NULL; numberColumns_ = newNumberColumns; } } // Delete columns in constraint void ClpConstraintLinear::deleteSome(int numberToDelete, const int * which) { if (numberToDelete) { int i ; char * deleted = new char[numberColumns_]; memset(deleted, 0, numberColumns_ * sizeof(char)); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { deleted[j] = 1; } } int n = 0; for (i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; if (!deleted[iColumn]) { column_[n] = iColumn; coefficient_[n++] = coefficient_[i]; } } numberCoefficients_ = n; } } // Scale constraint void ClpConstraintLinear::reallyScale(const double * columnScale) { for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; coefficient_[i] *= columnScale[iColumn]; } } /* Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ int ClpConstraintLinear::markNonlinear(char *) const { return 0; } /* Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ int ClpConstraintLinear::markNonzero(char * which) const { for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; which[iColumn] = 1; } return numberCoefficients_; } // Number of coefficients int ClpConstraintLinear::numberCoefficients() const { return numberCoefficients_; } Clp-1.15.10/src/CoinAbcBaseFactorization1.cpp0000644000076600007660000046612112252354371017273 0ustar coincoin/* $Id: CoinAbcBaseFactorization1.cpp 2006 2013-12-12 15:40:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinFinite.hpp" #define _mm256_broadcast_sd(x) static_cast<__m256d> (__builtin_ia32_vbroadcastsd256 (x)) #define _mm256_load_pd(x) *(__m256d *)(x) #define _mm256_store_pd (s, x) *((__m256d *)s)=x //:class CoinAbcTypeFactorization. Deals with Factorization and Updates // CoinAbcTypeFactorization. Constructor CoinAbcTypeFactorization::CoinAbcTypeFactorization ( ) : CoinAbcAnyFactorization() { gutsOfInitialize(7); } /// Copy constructor CoinAbcTypeFactorization::CoinAbcTypeFactorization ( const CoinAbcTypeFactorization &other) : CoinAbcAnyFactorization(other) { gutsOfInitialize(3); gutsOfCopy(other); } /// Clone CoinAbcAnyFactorization * CoinAbcTypeFactorization::clone() const { return new CoinAbcTypeFactorization(*this); } /// Copy constructor CoinAbcTypeFactorization::CoinAbcTypeFactorization ( const CoinFactorization & /*other*/) : CoinAbcAnyFactorization() { gutsOfInitialize(3); //gutsOfCopy(other); abort(); } /// The real work of constructors etc void CoinAbcTypeFactorization::gutsOfDestructor(CoinSimplexInt ) { numberCompressions_ = 0; numberRows_ = 0; numberRowsExtra_ = 0; maximumRowsExtra_ = 0; numberGoodU_ = 0; numberGoodL_ = 0; totalElements_ = 0; factorElements_ = 0; status_ = -1; numberSlacks_ = 0; lastSlack_ = 0; numberU_ = 0; maximumU_=0; lengthU_ = 0; lastEntryByColumnU_=0; lastEntryByRowU_=0; lengthAreaU_ = 0; numberL_ = 0; baseL_ = 0; lengthL_ = 0; lengthAreaL_ = 0; numberR_ = 0; lengthR_ = 0; lengthAreaR_ = 0; #if ABC_SMALL<4 numberDense_=0; #endif } #if FACTORIZATION_STATISTICS extern double denseThresholdX; #endif // type - 1 bit tolerances etc, 2 rest void CoinAbcTypeFactorization::gutsOfInitialize(CoinSimplexInt type) { if ((type&2)!=0) { numberCompressions_ = 0; numberRows_ = 0; numberRowsExtra_ = 0; maximumRowsExtra_ = 0; numberGoodU_ = 0; numberGoodL_ = 0; totalElements_ = 0; factorElements_ = 0; status_ = -1; numberPivots_ = 0; numberSlacks_ = 0; lastSlack_ = 0; numberU_ = 0; maximumU_=0; lengthU_ = 0; lastEntryByColumnU_=0; lastEntryByRowU_=0; lengthAreaU_ = 0; #ifdef ABC_USE_FUNCTION_POINTERS lengthAreaUPlus_ = 0; #endif numberL_ = 0; baseL_ = 0; lengthL_ = 0; lengthAreaL_ = 0; numberR_ = 0; lengthR_ = 0; lengthAreaR_ = 0; elementRAddress_ = NULL; indexRowRAddress_ = NULL; #if ABC_SMALL<2 // always switch off sparse sparseThreshold_=0; #endif state_= 0; // Maximum rows (ever) maximumRows_=0; // Rows first time nonzero initialNumberRows_=0; // Maximum maximum pivots maximumMaximumPivots_=0; #if ABC_SMALL<4 numberDense_=0; #endif } // after 2 if ((type&1)!=0) { areaFactor_ = 0.0; pivotTolerance_ = 1.0e-1; numberDense_=0; #ifndef USE_FIXED_ZERO_TOLERANCE zeroTolerance_ = 1.0e-13; #else zeroTolerance_ = pow(0.5,43); #endif messageLevel_=0; maximumPivots_=200; maximumMaximumPivots_=200; numberTrials_ = 4; relaxCheck_=1.0; #if ABC_SMALL<4 #if ABC_DENSE_CODE>0 denseThreshold_=4;//16; //31; //denseThreshold_=71; #else denseThreshold_=-16; #endif #if FACTORIZATION_STATISTICS denseThreshold_=denseThresholdX; #endif //denseThreshold_=0; // temp (? ABC_PARALLEL) #endif } #if ABC_SMALL<4 //denseThreshold_=10000; #endif if ((type&4)!=0) { #if COIN_BIG_DOUBLE==1 for (int i=0;i1 convertColumnToRowU_.switchOn(); #endif #endif #if ABC_SMALL<2 elementRowU_.switchOn(); #endif elementL_.switchOn(); indexRowL_.switchOn(); startColumnL_.switchOn(); #if ABC_SMALL<4 denseArea_.switchOn(7); #endif workArea_.switchOn(); workArea2_.switchOn(); #if ABC_SMALL<2 startRowL_.switchOn(); indexColumnL_.switchOn(); elementByRowL_.switchOn(); sparse_.switchOn(); // Below are all to collect ftranCountInput_=0.0; ftranCountAfterL_=0.0; ftranCountAfterR_=0.0; ftranCountAfterU_=0.0; ftranFTCountInput_=0.0; ftranFTCountAfterL_=0.0; ftranFTCountAfterR_=0.0; ftranFTCountAfterU_=0.0; btranCountInput_=0.0; btranCountAfterU_=0.0; btranCountAfterR_=0.0; btranCountAfterL_=0.0; ftranFullCountInput_=0.0; ftranFullCountAfterL_=0.0; ftranFullCountAfterR_=0.0; ftranFullCountAfterU_=0.0; btranFullCountInput_=0.0; btranFullCountAfterL_=0.0; btranFullCountAfterR_=0.0; btranFullCountAfterU_=0.0; #if FACTORIZATION_STATISTICS ftranTwiddleFactor1_=1.0; ftranFTTwiddleFactor1_=1.0; btranTwiddleFactor1_=1.0; ftranFullTwiddleFactor1_=1.0; btranFullTwiddleFactor1_=1.0; ftranTwiddleFactor2_=1.0; ftranFTTwiddleFactor2_=1.0; btranTwiddleFactor2_=1.0; ftranFullTwiddleFactor2_=1.0; btranFullTwiddleFactor2_=1.0; #endif // We can roll over factorizations numberFtranCounts_=0; numberFtranFTCounts_=0; numberBtranCounts_=0; numberFtranFullCounts_=0; numberFtranFullCounts_=0; // While these are averages collected over last ftranAverageAfterL_=INITIAL_AVERAGE; ftranAverageAfterR_=INITIAL_AVERAGE; ftranAverageAfterU_=INITIAL_AVERAGE; ftranFTAverageAfterL_=INITIAL_AVERAGE; ftranFTAverageAfterR_=INITIAL_AVERAGE; ftranFTAverageAfterU_=INITIAL_AVERAGE; btranAverageAfterU_=INITIAL_AVERAGE; btranAverageAfterR_=INITIAL_AVERAGE; btranAverageAfterL_=INITIAL_AVERAGE; ftranFullAverageAfterL_=INITIAL_AVERAGE; ftranFullAverageAfterR_=INITIAL_AVERAGE; ftranFullAverageAfterU_=INITIAL_AVERAGE; btranFullAverageAfterL_=INITIAL_AVERAGE; btranFullAverageAfterR_=INITIAL_AVERAGE; btranFullAverageAfterU_=INITIAL_AVERAGE; #endif } } // ~CoinAbcTypeFactorization. Destructor CoinAbcTypeFactorization::~CoinAbcTypeFactorization ( ) { gutsOfDestructor(); } // = CoinAbcTypeFactorization & CoinAbcTypeFactorization::operator = ( const CoinAbcTypeFactorization & other ) { if (this != &other) { gutsOfDestructor(); CoinAbcAnyFactorization::operator=(other); gutsOfInitialize(3); gutsOfCopy(other); } return *this; } void CoinAbcTypeFactorization::gutsOfCopy(const CoinAbcTypeFactorization &other) { #ifdef ABC_USE_FUNCTION_POINTERS elementU_.allocate(other.elementU_, other.lengthAreaUPlus_ *CoinSizeofAsInt(CoinFactorizationDouble)); #else elementU_.allocate(other.elementU_, other.lengthAreaU_ *CoinSizeofAsInt(CoinFactorizationDouble)); #endif indexRowU_.allocate(other.indexRowU_, (other.lengthAreaU_+1)*CoinSizeofAsInt(CoinSimplexInt) ); elementL_.allocate(other.elementL_, other.lengthAreaL_*CoinSizeofAsInt(CoinFactorizationDouble) ); indexRowL_.allocate(other.indexRowL_, other.lengthAreaL_*CoinSizeofAsInt(CoinSimplexInt) ); startColumnL_.allocate(other.startColumnL_,(other.numberRows_ + 1)*CoinSizeofAsInt(CoinBigIndex) ); pivotRegion_.allocate(other.pivotRegion_, (other.numberRows_+2 )*CoinSizeofAsInt(CoinFactorizationDouble)); #ifndef ABC_ORDERED_FACTORIZATION permute_.allocate(other.permute_,(other.maximumRowsExtra_ + 1)*CoinSizeofAsInt(CoinSimplexInt)); #else //temp permute_.allocate(other.permute_,(other.maximumRowsExtra_+2*numberRows_ + 1)*CoinSizeofAsInt(CoinSimplexInt)); #endif firstCount_.allocate(other.firstCount_, ( CoinMax(5*numberRows_,4*numberRows_+2*maximumPivots_+4)+2) *CoinSizeofAsInt(CoinSimplexInt)); nextCountAddress_=nextCount(); lastCountAddress_=lastCount(); startColumnU_.allocate(other.startColumnU_, (other.numberRows_ + 1 )*CoinSizeofAsInt(CoinBigIndex)); numberInColumn_.allocate(other.numberInColumn_, (other.numberRows_ + 1 )*CoinSizeofAsInt(CoinSimplexInt)); #if COIN_BIG_DOUBLE==1 for (int i=0;i1 convertColumnToRowU_.allocate(other.convertColumnToRowU_, other.lengthAreaU_*CoinSizeofAsInt(CoinBigIndex) ); #if CONVERTROW>2 const CoinBigIndex * convertUOther2 = other.convertColumnToRowUAddress_; #endif #endif #endif #if ABC_SMALL<2 const CoinFactorizationDouble * elementRowUOther = other.elementRowUAddress_; #if COIN_ONE_ETA_COPY if (elementRowUOther) { #endif #ifdef ABC_USE_FUNCTION_POINTERS elementRowU_.allocate(other.elementRowU_, other.lengthAreaUPlus_*CoinSizeofAsInt(CoinFactorizationDouble) ); #else elementRowU_.allocate(other.elementRowU_, other.lengthAreaU_*CoinSizeofAsInt(CoinFactorizationDouble) ); #endif startRowU_.allocate(other.startRowU_,(other.numberRows_ + 1)*CoinSizeofAsInt(CoinBigIndex)); numberInRow_.allocate(other.numberInRow_, (other.numberRows_ + 1 )*CoinSizeofAsInt(CoinSimplexInt)); #if COIN_ONE_ETA_COPY } #endif if (other.sparseThreshold_) { elementByRowL_.allocate(other.elementByRowL_, other.lengthAreaL_ ); indexColumnL_.allocate(other.indexColumnL_, other.lengthAreaL_ ); startRowL_.allocate(other.startRowL_,other.numberRows_+1); } #endif numberTrials_ = other.numberTrials_; relaxCheck_ = other.relaxCheck_; numberSlacks_ = other.numberSlacks_; lastSlack_ = other.lastSlack_; numberU_ = other.numberU_; maximumU_=other.maximumU_; lengthU_ = other.lengthU_; lastEntryByColumnU_=other.lastEntryByColumnU_; lastEntryByRowU_=other.lastEntryByRowU_; lengthAreaU_ = other.lengthAreaU_; #ifdef ABC_USE_FUNCTION_POINTERS lengthAreaUPlus_ = other.lengthAreaUPlus_; #endif numberL_ = other.numberL_; baseL_ = other.baseL_; lengthL_ = other.lengthL_; lengthAreaL_ = other.lengthAreaL_; numberR_ = other.numberR_; lengthR_ = other.lengthR_; lengthAreaR_ = other.lengthAreaR_; pivotTolerance_ = other.pivotTolerance_; zeroTolerance_ = other.zeroTolerance_; areaFactor_ = other.areaFactor_; numberRows_ = other.numberRows_; numberRowsExtra_ = other.numberRowsExtra_; maximumRowsExtra_ = other.maximumRowsExtra_; maximumPivots_=other.maximumPivots_; numberGoodU_ = other.numberGoodU_; numberGoodL_ = other.numberGoodL_; numberPivots_ = other.numberPivots_; messageLevel_ = other.messageLevel_; totalElements_ = other.totalElements_; factorElements_ = other.factorElements_; status_ = other.status_; #if ABC_SMALL<2 //doForrestTomlin_ = other.doForrestTomlin_; ftranCountInput_=other.ftranCountInput_; ftranCountAfterL_=other.ftranCountAfterL_; ftranCountAfterR_=other.ftranCountAfterR_; ftranCountAfterU_=other.ftranCountAfterU_; ftranFTCountInput_=other.ftranFTCountInput_; ftranFTCountAfterL_=other.ftranFTCountAfterL_; ftranFTCountAfterR_=other.ftranFTCountAfterR_; ftranFTCountAfterU_=other.ftranFTCountAfterU_; btranCountInput_=other.btranCountInput_; btranCountAfterU_=other.btranCountAfterU_; btranCountAfterR_=other.btranCountAfterR_; btranCountAfterL_=other.btranCountAfterL_; ftranFullCountInput_=other.ftranFullCountInput_; ftranFullCountAfterL_=other.ftranFullCountAfterL_; ftranFullCountAfterR_=other.ftranFullCountAfterR_; ftranFullCountAfterU_=other.ftranFullCountAfterU_; btranFullCountInput_=other.btranFullCountInput_; btranFullCountAfterL_=other.btranFullCountAfterL_; btranFullCountAfterR_=other.btranFullCountAfterR_; btranFullCountAfterU_=other.btranFullCountAfterU_; numberFtranCounts_=other.numberFtranCounts_; numberFtranFTCounts_=other.numberFtranFTCounts_; numberBtranCounts_=other.numberBtranCounts_; numberFtranFullCounts_=other.numberFtranFullCounts_; numberFtranFullCounts_=other.numberFtranFullCounts_; ftranAverageAfterL_=other.ftranAverageAfterL_; ftranAverageAfterR_=other.ftranAverageAfterR_; ftranAverageAfterU_=other.ftranAverageAfterU_; ftranFTAverageAfterL_=other.ftranFTAverageAfterL_; ftranFTAverageAfterR_=other.ftranFTAverageAfterR_; ftranFTAverageAfterU_=other.ftranFTAverageAfterU_; btranAverageAfterU_=other.btranAverageAfterU_; btranAverageAfterR_=other.btranAverageAfterR_; btranAverageAfterL_=other.btranAverageAfterL_; ftranFullAverageAfterL_=other.ftranFullAverageAfterL_; ftranFullAverageAfterR_=other.ftranFullAverageAfterR_; ftranFullAverageAfterU_=other.ftranFullAverageAfterU_; btranFullAverageAfterL_=other.btranFullAverageAfterL_; btranFullAverageAfterR_=other.btranFullAverageAfterR_; btranFullAverageAfterU_=other.btranFullAverageAfterU_; #if FACTORIZATION_STATISTICS ftranTwiddleFactor1_=other.ftranTwiddleFactor1_; ftranFTTwiddleFactor1_=other.ftranFTTwiddleFactor1_; btranTwiddleFactor1_=other.btranTwiddleFactor1_; ftranFullTwiddleFactor1_=other.ftranFullTwiddleFactor1_; btranFullTwiddleFactor1_=other.btranFullTwiddleFactor1_; ftranTwiddleFactor2_=other.ftranTwiddleFactor2_; ftranFTTwiddleFactor2_=other.ftranFTTwiddleFactor2_; btranTwiddleFactor2_=other.btranTwiddleFactor2_; ftranFullTwiddleFactor2_=other.ftranFullTwiddleFactor2_; btranFullTwiddleFactor2_=other.btranFullTwiddleFactor2_; #endif sparseThreshold_=other.sparseThreshold_; #endif state_=other.state_; // Maximum rows (ever) maximumRows_=other.maximumRows_; // Rows first time nonzero initialNumberRows_=other.initialNumberRows_; // Maximum maximum pivots maximumMaximumPivots_=other.maximumMaximumPivots_; CoinBigIndex space = lengthAreaL_ - lengthL_; #if ABC_SMALL<4 numberDense_ = other.numberDense_; denseThreshold_=other.denseThreshold_; #endif lengthAreaR_ = space; elementRAddress_ = elementL_.array() + lengthL_; indexRowRAddress_ = indexRowL_.array() + lengthL_; workArea_ = other.workArea_; workArea2_ = other.workArea2_; //now copy everything //assuming numberRowsExtra==numberColumnsExtra if (numberRowsExtra_) { if (startRowU_.array()) { CoinAbcMemcpy( startRowU_.array() , other.startRowU_.array(), numberRows_ + 1); CoinAbcMemcpy( numberInRow_.array() , other.numberInRow_.array(), numberRows_ + 1); //startRowU_.array()[maximumRowsExtra_] = other.startRowU_.array()[maximumRowsExtra_]; } CoinAbcMemcpy( pivotRegion_.array() , other.pivotRegion_.array(), numberRows_+2 ); #ifndef ABC_ORDERED_FACTORIZATION CoinAbcMemcpy( permute_.array() , other.permute_.array(), numberRowsExtra_ + 1); #else //temp CoinAbcMemcpy( permute_.array() , other.permute_.array(), maximumRowsExtra_+2*numberRows_ + 1); #endif CoinAbcMemcpy( firstCount_.array() , other.firstCount_.array(),CoinMax(5*numberRows_,4*numberRows_+2*maximumPivots_+4)+2); CoinAbcMemcpy( startColumnU_.array() , other.startColumnU_.array(), numberRows_ + 1); CoinAbcMemcpy( numberInColumn_.array() , other.numberInColumn_.array(), numberRows_ + 1); CoinAbcMemcpy( pivotColumn_.array() , other.pivotColumn_.array(), numberRowsExtra_ + 1); CoinAbcMemcpy( nextColumn_.array() , other.nextColumn_.array(), numberRowsExtra_ + 1); CoinAbcMemcpy( lastColumn_.array() , other.lastColumn_.array(), numberRowsExtra_ + 1); CoinAbcMemcpy (startColumnR() , other.startColumnR() , numberRowsExtra_ - numberRows_ + 1); //extra one at end //startColumnU_.array()[maximumRowsExtra_] = //other.startColumnU_.array()[maximumRowsExtra_]; nextColumn_.array()[maximumRowsExtra_] = other.nextColumn_.array()[maximumRowsExtra_]; lastColumn_.array()[maximumRowsExtra_] = other.lastColumn_.array()[maximumRowsExtra_]; CoinAbcMemcpy( nextRow_.array() , other.nextRow_.array(), numberRows_ + 1); CoinAbcMemcpy( lastRow_.array() , other.lastRow_.array(), numberRows_ + 1); nextRow_.array()[numberRows_] = other.nextRow_.array()[numberRows_]; lastRow_.array()[numberRows_] = other.lastRow_.array()[numberRows_]; } CoinAbcMemcpy( elementRAddress_ , other.elementRAddress_, lengthR_); CoinAbcMemcpy( indexRowRAddress_ , other.indexRowRAddress_, lengthR_); //row and column copies of U /* as elements of U may have been zeroed but column counts zero copy all elements */ const CoinBigIndex * COIN_RESTRICT startColumnU = startColumnU_.array(); const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumn_.array(); #ifndef NDEBUG CoinSimplexInt maxU=0; for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++ ) { CoinBigIndex start = startColumnU[iRow]; CoinSimplexInt numberIn = numberInColumn[iRow]; maxU = CoinMax(maxU,start+numberIn); } //assert (maximumU_>=maxU); #endif CoinAbcMemcpy( elementU_.array() , other.elementU_.array() , maximumU_); #if ABC_SMALL<2 #if COIN_ONE_ETA_COPY if (elementRowUOther) { #endif const CoinSimplexInt * COIN_RESTRICT indexColumnUOther = other.indexColumnU_.array(); #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertU = convertRowToColumnU_.array(); #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertU2 = convertColumnToRowU_.array(); #endif #endif CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowU_.array(); CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnU_.array(); const CoinBigIndex * COIN_RESTRICT startRowU = startRowU_.array(); const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRow_.array(); for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++ ) { //row CoinBigIndex start = startRowU[iRow]; CoinSimplexInt numberIn = numberInRow[iRow]; CoinAbcMemcpy( indexColumnU + start , indexColumnUOther + start, numberIn); #if CONVERTROW CoinAbcMemcpy( convertU + start ,convertUOther + start , numberIn); #if CONVERTROW>2 CoinAbcMemcpy( convertU2 + start ,convertUOther2 + start , numberIn); #endif #endif CoinAbcMemcpy( elementRowU + start ,elementRowUOther + start , numberIn); } #if COIN_ONE_ETA_COPY } #endif #endif const CoinSimplexInt * COIN_RESTRICT indexRowUOther = other.indexRowU_.array(); CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowU_.array(); for (CoinSimplexInt iRow = 0; iRow < numberRows_; iRow++ ) { //column CoinBigIndex start = startColumnU[iRow]; CoinSimplexInt numberIn = numberInColumn[iRow]; if (numberIn>0) CoinAbcMemcpy( indexRowU + start , indexRowUOther + start, numberIn); } // L is contiguous if (numberRows_) CoinAbcMemcpy( startColumnL_.array() , other.startColumnL_.array(), numberRows_ + 1); CoinAbcMemcpy( elementL_.array() , other.elementL_.array(), lengthL_); CoinAbcMemcpy( indexRowL_.array() , other.indexRowL_.array(), lengthL_); #if ABC_SMALL<2 if (other.sparseThreshold_) { goSparse(); } #endif doAddresses(); } // getAreas. Gets space for a factorization //called by constructors void CoinAbcTypeFactorization::getAreas ( CoinSimplexInt numberOfRows, CoinSimplexInt /*numberOfColumns*/, CoinBigIndex maximumL, CoinBigIndex maximumU ) { gutsOfInitialize(2); numberRows_ = numberOfRows; numberRowsSmall_ = numberOfRows; maximumRows_ = CoinMax(maximumRows_,numberRows_); maximumRowsExtra_ = numberRows_ + maximumPivots_; numberRowsExtra_ = numberRows_; lengthAreaU_ = maximumU; lengthAreaL_ = maximumL; if ( !areaFactor_ ) { areaFactor_ = 1.0; } if ( areaFactor_ != 1.0 ) { if ((messageLevel_&16)!=0) printf("Increasing factorization areas by %g\n",areaFactor_); lengthAreaU_ = static_cast (areaFactor_*lengthAreaU_); lengthAreaL_ = static_cast (areaFactor_*lengthAreaL_); } #ifdef ABC_USE_FUNCTION_POINTERS lengthAreaUPlus_ = (lengthAreaU_*3)/2+maximumRowsExtra_ ; elementU_.conditionalNew( lengthAreaUPlus_ ); #else elementU_.conditionalNew( lengthAreaU_ ); #endif indexRowU_.conditionalNew( lengthAreaU_+1 ); indexColumnU_.conditionalNew( lengthAreaU_+1 ); elementL_.conditionalNew( lengthAreaL_ ); indexRowL_.conditionalNew( lengthAreaL_ ); // But we can use all we have if bigger CoinBigIndex length; length = CoinMin(elementU_.getSize(),indexRowU_.getSize()); if (length>lengthAreaU_) { lengthAreaU_=length; assert (indexColumnU_.getSize()==indexRowU_.getSize()); } length = CoinMin(elementL_.getSize(),indexRowL_.getSize()); if (length>lengthAreaL_) { lengthAreaL_=length; } startColumnL_.conditionalNew( numberRows_ + 1 ); startColumnL_.array()[0] = 0; startRowU_.conditionalNew( maximumRowsExtra_ + 1); // make sure this is valid (Needed for row links????) startRowU_.array()[maximumRowsExtra_]=0; lastEntryByRowU_ = 0; numberInRow_.conditionalNew( maximumRowsExtra_ + 1 ); markRow_.conditionalNew( numberRows_ ); nextRow_.conditionalNew( maximumRowsExtra_ + 1 ); lastRow_.conditionalNew( maximumRowsExtra_ + 1 ); #ifndef ABC_ORDERED_FACTORIZATION permute_.conditionalNew( maximumRowsExtra_ + 1 ); #else //temp permute_.conditionalNew( maximumRowsExtra_+2*numberRows_ + 1 ); #endif permuteAddress_ = permute_.array(); pivotRegion_.conditionalNew( maximumRows_ + 2 ); startColumnU_.conditionalNew( maximumRowsExtra_ + 1 ); numberInColumn_.conditionalNew( maximumRowsExtra_ + 1 ); numberInColumnPlus_.conditionalNew( maximumRowsExtra_ + 1 ); #ifdef ABC_USE_FUNCTION_POINTERS scatterUColumn_.conditionalNew(sizeof(scatterStruct), maximumRowsExtra_ + 1); elementRowU_.conditionalNew( lengthAreaUPlus_ ); elementRowUAddress_=elementRowU_.array(); firstZeroed_=0; #elif ABC_SMALL<2 elementRowU_.conditionalNew( lengthAreaU_ ); elementRowUAddress_=elementRowU_.array(); #endif #if COIN_BIG_DOUBLE==1 for (int i=0;i1 convertColumnToRowU_.conditionalNew( lengthAreaU_ ); convertColumnToRowUAddress_=convertColumnToRowU_.array(); #endif #endif #ifdef SMALL_PERMUTE assert (sizeof(CoinFactorizationDouble)>=2*sizeof(int)); denseArea_.conditionalNew(numberRows_+maximumRowsExtra_+2); fromSmallToBigRow_=reinterpret_cast(denseArea_.array()); fromSmallToBigColumn_=fromSmallToBigRow_+numberRows_; #endif doAddresses(); #if ABC_SMALL<2 // temp - use as marker for valid row/column lookup sparseThreshold_=0; #endif } #include "AbcSimplex.hpp" #include "ClpMessage.hpp" //Does most of factorization CoinSimplexInt CoinAbcTypeFactorization::factor (AbcSimplex * model) { #if ABC_DENSE_CODE int saveDense = denseThreshold_; if ((solveMode_&1)==0) denseThreshold_=0; #endif //sparse status_ = factorSparse ( ); switch ( status_ ) { case 0: //finished totalElements_ = 0; if ( numberGoodU_ < numberRows_ ) status_ = -1; break; #if ABC_DENSE_CODE #if ABC_SMALL<4 // dense case 2: status_=factorDense(); if(!status_) break; #endif #endif default: //singular ? or some error if ((messageLevel_&4)!=0) std::cout << "Error " << status_ << std::endl; if (status_==-99) { if (numberRows_-numberGoodU_<1000) { areaFactor_ *= 1.5; } else { double denseArea=(numberRows_-numberGoodU_)*(numberRows_-numberGoodU_); if (denseArea>1.5*lengthAreaU_) { areaFactor_ *= CoinMin(2.5,denseArea/1.5); } else { areaFactor_ *= 1.5; } } if (model->logLevel()>1) { char line[100]; sprintf(line,"need more memory lengthArea %d number %d done %d areaFactor %g", lengthAreaL_+lengthAreaU_,lengthU_+lengthL_,numberGoodU_,areaFactor_); model->messageHandler()->message(CLP_GENERAL2,*model->messagesPointer()) << line << CoinMessageEol; } } else if (status_==-97) { // just pivot tolerance issue status_=-99; char line[100]; sprintf(line,"Bad pivot values - increasing pivot tolerance to %g", pivotTolerance_); model->messageHandler()->message(CLP_GENERAL2,*model->messagesPointer()) << line << CoinMessageEol; } break; } /* endswitch */ //clean up if ( !status_ ) { if ( (messageLevel_ & 16)&&numberCompressions_) std::cout<<" Factorization did "< 10 ) { // but not more than 5 times final if (lengthAreaL_+lengthAreaU_<10*(lengthU_+lengthL_)) { areaFactor_ *= 1.1; if (model->logLevel()>1) { char line[100]; sprintf(line,"%d factorization compressions, lengthArea %d number %d new areaFactor %g", numberCompressions_,lengthAreaL_+lengthAreaU_,lengthU_+lengthL_,areaFactor_); model->messageHandler()->message(CLP_GENERAL2,*model->messagesPointer()) << line << CoinMessageEol; } } } numberCompressions_=0; cleanup ( ); } numberPivots_=0; #if ABC_DENSE_CODE denseThreshold_=saveDense; #endif return status_; } #ifdef ABC_USE_FUNCTION_POINTERS #define DENSE_TRY #ifdef DENSE_TRY static void pivotStartup(int first, int last, int numberInPivotColumn, int lengthArea,int giveUp, CoinFactorizationDouble * COIN_RESTRICT eArea,const int * COIN_RESTRICT saveColumn, const int * COIN_RESTRICT startColumnU,int * COIN_RESTRICT tempColumnCount, const CoinFactorizationDouble * COIN_RESTRICT elementU, const int * COIN_RESTRICT numberInColumn, const int * COIN_RESTRICT indexRowU) { if (last-first>giveUp) { int mid=(last+first)>>1; cilk_spawn pivotStartup(first,mid,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU); pivotStartup(mid,last,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU); cilk_sync; } else { CoinFactorizationDouble * COIN_RESTRICT area =eArea+first*lengthArea; for (int jColumn = first; jColumn < last; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; int numberNow=tempColumnCount[jColumn]; int start=startColumn+numberNow; int end=startColumn+numberInColumn[iColumn]; CoinFactorizationDouble thisPivotValue = elementU[startColumn-1]; for (CoinBigIndex j=start;jgiveUp) { int mid=(last+first)>>1; cilk_spawn pivotWhile(first,mid,numberInPivotColumn,lengthArea,giveUp, eArea,multipliersL); pivotWhile(mid,last,numberInPivotColumn,lengthArea,giveUp, eArea,multipliersL); cilk_sync; } else { CoinFactorizationDouble * COIN_RESTRICT area =eArea+first*lengthArea; int nDo=last-first; #if AVX2==0 for (int jColumn = 0; jColumn < nDo; jColumn++ ) { CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn]; area[numberInPivotColumn]=0.0; for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { area[j] -= thisPivotValue * multipliersL[j]; } area+=lengthArea; } #else int n=(numberInPivotColumn+3)&(~3); // for compiler error CoinFactorizationDouble * multipliers = const_cast(multipliersL); for (int jColumn = 0; jColumn < nDo; jColumn++ ) { //CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn]; __m256d pivot = _mm256_broadcast_sd(area+numberInPivotColumn); area[numberInPivotColumn]=0.0; for (CoinSimplexInt j = 0; j < n; j+=4 ) { __m256d a=_mm256_load_pd(area+j); __m256d m=_mm256_load_pd(multipliers+j); a -= pivot*m; *reinterpret_cast<__m256d *>(area+j)=a; //_mm256_store_pd ((area+j), a); //area[j] -= thisPivotValue * multipliersL[j]; //area[j+1] -= thisPivotValue * multipliersL[j+1]; //area[j+2] -= thisPivotValue * multipliersL[j+2]; //area[j+3] -= thisPivotValue * multipliersL[j+3]; } area+=lengthArea; } #endif } } static void pivotSomeAfter(int first, int last, int numberInPivotColumn,int lengthArea,int giveUp, CoinFactorizationDouble * COIN_RESTRICT eArea,const int * COIN_RESTRICT saveColumn, const int * COIN_RESTRICT startColumnU,int * COIN_RESTRICT tempColumnCount, CoinFactorizationDouble * COIN_RESTRICT elementU, int * COIN_RESTRICT numberInColumn, int * COIN_RESTRICT indexRowU, unsigned int * aBits, const int * COIN_RESTRICT indexL, const CoinFactorizationDouble * COIN_RESTRICT multipliersL, double tolerance) { if (last-first>giveUp) { int mid=(last+first)>>1; cilk_spawn pivotSomeAfter(first,mid,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); pivotSomeAfter(mid,last,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); cilk_sync; } else { int intsPerColumn = (lengthArea+31)>>5; CoinFactorizationDouble * COIN_RESTRICT area =eArea+first*lengthArea; for (int jColumn = first; jColumn < last; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; int numberNow=tempColumnCount[jColumn]; CoinFactorizationDouble thisPivotValue = area[numberInPivotColumn]; area[numberInPivotColumn]=0.0; int n=0; int positionLargest=-1; double largest=numberNow ? fabs(elementU[startColumn]) : 0.0; unsigned int * aBitsThis = aBits+jColumn*intsPerColumn; #if AVX2==0 for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { CoinFactorizationDouble value = area[j] - thisPivotValue * multipliersL[j]; CoinSimplexDouble absValue = fabs ( value ); area[j]=0.0; if ( absValue > tolerance ) { area[n] = value; if (absValue>largest) { largest=absValue; positionLargest=n; } n++; } else { // say zero int word = j>>5; int unsetBit=j-(word<<5); aBitsThis[word]&= ~(1<(multipliersL); int nDo=(numberInPivotColumn+3)&(~3); //double temp[4] __attribute__ ((aligned (32))); __m256d pivot = _mm256_broadcast_sd(&thisPivotValue); for (CoinSimplexInt j = 0; j < nDo; j+=4 ) { __m256d a=_mm256_load_pd(area+j); __m256d m=_mm256_load_pd(multipliers+j); a -= pivot*m; *reinterpret_cast<__m256d *>(area+j)=a; //_mm256_store_pd ((area+j), a); } for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { CoinFactorizationDouble value = area[j]; CoinSimplexDouble absValue = fabs ( value ); area[j]=0.0; if ( absValue > tolerance ) { area[n] = value; if (absValue>largest) { largest=absValue; positionLargest=n; } n++; } else { // say zero int word = j>>5; int unsetBit=j-(word<<5); aBitsThis[word]&= ~(1<=0) positionLargest+=put+numberNow; put+=numberNow; int iA=0; for (int jj=0;jj>1; } } int numberNeeded=put-startColumn; if (positionLargest>=0) { //swap first and largest CoinBigIndex start=startColumn; int firstIndex=indexRowU[start]; CoinFactorizationDouble firstValue=elementU[start]; indexRowU[start]=indexRowU[positionLargest]; elementU[start]=elementU[positionLargest]; indexRowU[positionLargest]=firstIndex; elementU[positionLargest]=firstValue; } tempColumnCount[jColumn]=numberNeeded-numberInColumn[iColumn]; assert (numberNeeded>=0); numberInColumn[iColumn]=numberNeeded; area += lengthArea; } } } #endif static void pivotSome(int first, int last, int numberInPivotColumn,int lengthArea,int giveUp, CoinFactorizationDouble * COIN_RESTRICT eArea,const int * COIN_RESTRICT saveColumn, const int * COIN_RESTRICT startColumnU,int * COIN_RESTRICT tempColumnCount, CoinFactorizationDouble * COIN_RESTRICT elementU, int * COIN_RESTRICT numberInColumn, int * COIN_RESTRICT indexRowU, unsigned int * aBits, const int * COIN_RESTRICT indexL, const CoinFactorizationDouble * COIN_RESTRICT multipliersL, double tolerance) { if (last-first>giveUp) { int mid=(last+first)>>1; cilk_spawn pivotSome(first,mid,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); pivotSome(mid,last,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); cilk_sync; } else { int intsPerColumn = (lengthArea+31)>>5; CoinFactorizationDouble * COIN_RESTRICT area =eArea+first*lengthArea; for (int jColumn = first; jColumn < last; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; int numberNow=tempColumnCount[jColumn]; CoinFactorizationDouble thisPivotValue = elementU[startColumn-1]; int start=startColumn+numberNow; int end=startColumn+numberInColumn[iColumn]; for (CoinBigIndex j=start;j tolerance ) { area[n] = value; if (absValue>largest) { largest=absValue; positionLargest=n; } n++; } else { // say zero int word = j>>5; int unsetBit=j-(word<<5); aBitsThis[word]&= ~(1<(multipliersL); //double temp[4] __attribute__ ((aligned (32))); __m256d pivot = _mm256_broadcast_sd(&thisPivotValue); for (CoinSimplexInt j = 0; j < nDo; j+=4 ) { __m256d a=_mm256_load_pd(area+j); __m256d m=_mm256_load_pd(multipliers+j); a -= pivot*m; *reinterpret_cast<__m256d *>(area+j)=a; //_mm256_store_pd ((area+j), a); } for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { CoinFactorizationDouble value = area[j]; CoinSimplexDouble absValue = fabs ( value ); area[j]=0.0; if ( absValue > tolerance ) { area[n] = value; if (absValue>largest) { largest=absValue; positionLargest=n; } n++; } else { // say zero int word = j>>5; int unsetBit=j-(word<<5); aBitsThis[word]&= ~(1<=0) positionLargest+=put+numberNow; put+=numberNow; int iA=0; for (int jj=0;jj>1; } } int numberNeeded=put-startColumn; if (positionLargest>=0) { //swap first and largest CoinBigIndex start=startColumn; int firstIndex=indexRowU[start]; CoinFactorizationDouble firstValue=elementU[start]; indexRowU[start]=indexRowU[positionLargest]; elementU[start]=elementU[positionLargest]; indexRowU[positionLargest]=firstIndex; elementU[positionLargest]=firstValue; } tempColumnCount[jColumn]=numberNeeded-numberInColumn[iColumn]; assert (numberNeeded>=0); numberInColumn[iColumn]=numberNeeded; } } } int CoinAbcTypeFactorization::pivot ( CoinSimplexInt & pivotRow, CoinSimplexInt & pivotColumn, CoinBigIndex pivotRowPosition, CoinBigIndex pivotColumnPosition, int * COIN_RESTRICT markRow) { CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnU_.array(); CoinBigIndex * COIN_RESTRICT startColumnU = startColumnU_.array(); CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumn_.array(); CoinFactorizationDouble * COIN_RESTRICT elementU = elementU_.array(); CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowU_.array(); CoinBigIndex * COIN_RESTRICT startRowU = startRowU_.array(); CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRow_.array(); CoinFactorizationDouble * COIN_RESTRICT elementL = elementL_.array(); CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowL_.array(); CoinSimplexInt * COIN_RESTRICT saveColumn = saveColumn_.array(); CoinSimplexInt * COIN_RESTRICT nextRow = nextRow_.array(); CoinSimplexInt * COIN_RESTRICT lastRow = lastRow_.array() ; int realPivotRow=fromSmallToBigRow_[pivotRow]; //int realPivotColumn=fromSmallToBigColumn[pivotColumn]; //store pivot columns (so can easily compress) CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1; CoinBigIndex startColumn = startColumnU[pivotColumn]; CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1; // temp CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1; CoinBigIndex put = 0; CoinBigIndex startRow = startRowU[pivotRow]; CoinBigIndex endRow = startRow + numberInPivotRow + 1; #if ABC_SMALL<2 // temp - switch off marker for valid row/column lookup sparseThreshold_=-1; #endif if ( pivotColumnPosition < 0 ) { for ( pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++ ) { CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition]; if ( iColumn != pivotColumn ) { saveColumn[put++] = iColumn; } else { break; } } } else { for (CoinBigIndex i = startRow ; i < pivotColumnPosition ; i++ ) { saveColumn[put++] = indexColumnU[i]; } } assert (pivotColumnPosition lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) printf("more memory needed in middle of invert\n"); return -99; } //l+=currentAreaL_->elementByColumn-elementL; CoinBigIndex lSave = l; CoinSimplexInt saveGoodL=numberGoodL_; CoinBigIndex * COIN_RESTRICT startColumnL = startColumnL_.array(); startColumnL[numberGoodL_] = l; //for luck and first time numberGoodL_++; if ( pivotRowPosition < 0 ) { for ( pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++ ) { CoinSimplexInt iRow = indexRowU[pivotRowPosition]; if ( iRow == pivotRow ) break; } } assert (pivotRowPosition>2); spaceZeroed=CoinMax(spaceZeroed,firstZeroed_); int maxBoth=CoinMax(numberInPivotRow,numberInPivotColumn); CoinBigIndex spaceOther=numberInPivotRow+maxBoth+numberInPivotRow*((numberInPivotColumn+31)>>5); // allow for new multipliersL spaceOther += 2*numberInPivotColumn+8; // 32 byte alignment wanted CoinBigIndex spaceNeeded=spaceZeroed+((spaceOther+1)>>1)+32; #ifdef INT_IS_8 abort(); #endif if (spaceNeeded>=lengthAreaUPlus_-lastEntryByColumnUPlus_) return -99; // see if need to zero out CoinFactorizationDouble * COIN_RESTRICT eArea = elementUColumnPlusAddress_+lengthAreaUPlus_-spaceZeroed; CoinInt64 xx = reinterpret_cast(eArea); int iBottom = static_cast(xx & 255); int offset = iBottom>>3; eArea -= offset; spaceZeroed=(elementUColumnPlusAddress_+lengthAreaUPlus_)-eArea; char * COIN_RESTRICT mark = reinterpret_cast(eArea+added); CoinFactorizationDouble * COIN_RESTRICT multipliersL = eArea-numberInPivotColumn; // adjust xx = reinterpret_cast(multipliersL); iBottom = static_cast(xx & 31); offset = iBottom>>3; multipliersL -= offset; int * COIN_RESTRICT tempColumnCount = reinterpret_cast(multipliersL)-numberInPivotRow; int * COIN_RESTRICT tempCount = tempColumnCount-maxBoth; int * COIN_RESTRICT others = tempCount-numberInPivotRow; for (CoinBigIndex i = startColumn; i < endColumn; i++ ) { CoinSimplexInt iRow = indexRowU[i]; //double value=elementU[i]*pivotMultiplier; markRow[iRow] = l - lSave; indexRowL[l] = iRow; multipliersL[l-lSave] = elementU[i]; l++; } startColumnL[numberGoodL_] = l; lengthL_ = l; //use end of L for temporary space BUT AVX CoinSimplexInt * COIN_RESTRICT indexL = &indexRowL[lSave]; //CoinFactorizationDouble * COIN_RESTRICT multipliersL = &elementL[lSave]; for (int i=0;i>2)<<2; // zero out rest memset(multipliersL+numberInPivotColumn,0,(lengthArea-numberInPivotColumn)*sizeof(CoinFactorizationDouble)); int intsPerColumn = (lengthArea+31)>>5; unsigned int * COIN_RESTRICT aBits = reinterpret_cast(others-intsPerColumn*numberInPivotRow); memset(aBits,0xff,intsPerColumn*4*numberInPivotRow); if (spaceZeroed>firstZeroed_) { CoinAbcMemset0(eArea,spaceZeroed-firstZeroed_); firstZeroed_=spaceZeroed; } #ifndef NDEBUG for (int i=0;i=0); #endif cilk_for_query (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; CoinBigIndex endColumn = startColumn + numberInColumn[iColumn]; CoinFactorizationDouble thisPivotValue = 0.0; CoinBigIndex put = startColumn; CoinBigIndex positionLargest = -1; double largest=0.0; CoinBigIndex position = startColumn; int iRow = indexRowU[position]; CoinFactorizationDouble value = elementU[position]; CoinSimplexInt mark = markRow[iRow]; CoinBigIndex end=endColumn-1; while ( position < end) { if ( mark == LARGE_UNSET ) { //keep if (fabs(value)>largest) { positionLargest=put; largest=fabs(value); } indexRowU[put] = iRow; elementU[put++] = value; } else if ( mark != LARGE_SET ) { //will be updated - move to end CoinFactorizationDouble value2=value; int mark2=mark; iRow = indexRowU[end]; value = elementU[end]; mark = markRow[iRow]; indexRowU[end]=mark2; elementU[end]=value2; end--; continue; } else { thisPivotValue = value; } position++; iRow = indexRowU[position]; value = elementU[position]; mark = markRow[iRow]; } // now last in column if ( mark == LARGE_UNSET ) { //keep if (fabs(value)>largest) { positionLargest=put; largest=fabs(value); } indexRowU[put] = iRow; elementU[put++] = value; } else if ( mark != LARGE_SET ) { //will be updated - move to end indexRowU[end]=mark; elementU[end]=value; } else { thisPivotValue = value; } //swap largest if (positionLargest>=0) { double largestValue=elementU[positionLargest]; int largestIndex=indexRowU[positionLargest]; if (positionLargest!=startColumn+1&&put>startColumn+1) { elementU[positionLargest]=elementU[startColumn+1]; indexRowU[positionLargest]=indexRowU[startColumn+1]; elementU[startColumn+1] = largestValue; indexRowU[startColumn+1] = largestIndex; } int firstIndex=indexRowU[startColumn]; CoinFactorizationDouble firstValue=elementU[startColumn]; // move first to end elementU[put] = firstValue; indexRowU[put++] = firstIndex; } else { put++; } elementU[startColumn] = thisPivotValue; indexRowU[startColumn] = realPivotRow; startColumn++; startColumnU[iColumn]=startColumn; numberInColumnPlus[iColumn]++; int numberNow=put-startColumn; tempColumnCount[jColumn]=numberNow; numberInColumn[iColumn]--; #ifndef NDEBUG for (int i=startColumn+numberNow;i=0); #endif //parallel mark[pivotColumn]=1; cilk_for_query (int jRow = 0; jRow < numberInPivotColumn; jRow++ ) { CoinSimplexInt iRow = indexL[jRow]; CoinBigIndex startRow = startRowU[iRow]; CoinBigIndex endRow = startRow + numberInRow[iRow]; CoinBigIndex put=startRow; // move earlier but set numberInRow to final for (CoinBigIndex i = startRow ; i < endRow; i++ ) { int iColumn = indexColumnU[i]; if (!mark[iColumn]) indexColumnU[put++]=iColumn; } numberInRow[iRow]=put-startRow; } mark[pivotColumn]=0; #ifdef DENSE_TRY int numberZeroOther=0; for (int jRow = 0; jRow < numberInPivotColumn; jRow++ ) { CoinSimplexInt iRow = indexL[jRow]; if (numberInRow[iRow]) { //printf("Cantdo INrow %d incolumn %d nother %d\n", // numberInPivotRow,numberInPivotColumn,numberZeroOther); numberZeroOther=-1; break; } } if (!numberZeroOther) { for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { if (!tempColumnCount[jColumn]) others[numberZeroOther++]=jColumn; } } #endif // serial for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; int numberNow=tempColumnCount[jColumn]; int numberNeeded=numberNow+numberInPivotColumn; tempCount[jColumn]=numberInColumn[iColumn]; //how much space have we got CoinSimplexInt next = nextColumn[iColumn]; CoinBigIndex space = startColumnU[next] - startColumn - numberInColumnPlus[next]; // do moves serially but fill in in parallel! if ( numberNeeded > space ) { //getColumnSpace also moves fixed part if ( !getColumnSpace ( iColumn, numberNeeded ) ) { return -99; } } numberInColumn[iColumn]=numberNeeded; } // move counts back for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; numberInColumn[iColumn]=tempCount[jColumn]; } // giveUp should be more sophisticated and also vary in next three #if ABC_PARALLEL==2 int giveUp=CoinMax(numberInPivotRow/(parallelMode_+1+(parallelMode_>>1)),16); #else int giveUp=numberInPivotRow; #endif #ifdef DENSE_TRY // If we keep full area - then can try doing many pivots in this function // Go round if there are any others just in this block bool inAreaAlready=false; if (numberZeroOther>4) { //printf("Cando INrow %d incolumn %d nother %d\n", // numberInPivotRow,numberInPivotColumn,numberZeroOther); int numberRowsTest=(numberRowsLeft_-numberZeroOther+0)&~7; if (numberRowsLeft_-numberZeroOther<=numberRowsTest) { //see if would go dense int numberSubtracted=0; // would have to be very big for parallel for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; numberSubtracted += numberInColumn[iColumn]-tempColumnCount[jColumn]; } // could do formula? - work backwards CoinBigIndex saveTotalElements=totalElements_; int saveNumberRowsLeft=numberRowsLeft_; int numberOut=numberRowsLeft_-numberRowsTest-1; numberRowsLeft_=numberRowsTest; CoinBigIndex total= totalElements_-numberSubtracted; int bestGoDense=-1; for (;numberRowsLeft_numberRowsLeft_-numberZeroOther) numberZeroOther=numberRowsLeft_-bestGoDense;; } } else { numberZeroOther=-1; } if (numberZeroOther>0) { // do all except last pivotStartup(0,numberInPivotRow,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU); assert (tempColumnCount[0]>=0); for (int iTry=numberZeroOther-1;iTry>=0;iTry--) { pivotWhile(0,numberInPivotRow,numberInPivotColumn,lengthArea,giveUp, eArea,multipliersL); assert (tempColumnCount[0]>=0); // find new pivot row int jPivotColumn=others[iTry]; CoinFactorizationDouble * COIN_RESTRICT area =eArea+jPivotColumn*lengthArea; double largest=tolerance; int jPivotRow=-1; for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { CoinFactorizationDouble value = area[j]; CoinSimplexDouble absValue = fabs ( value ); if (absValue>largest) { largest=absValue; jPivotRow=j; } } if (jPivotRow>=0) { markRow[pivotRow] = LARGE_UNSET; //modify linked list for pivots deleteLink ( pivotRow ); deleteLink ( pivotColumn + numberRows_ ); // put away last afterPivot(pivotRow,pivotColumn); if (reinterpret_cast(elementUColumnPlusAddress_+lastEntryByColumnUPlus_)>aBits) { #ifndef NDEBUG printf("? dense\n"); #endif return -99; } // new ones pivotRow=indexL[jPivotRow]; pivotColumn=saveColumn[jPivotColumn]; // now do stuff for pivot realPivotRow=fromSmallToBigRow_[pivotRow]; //int realPivotColumn=fromSmallToBigColumn[pivotColumn]; //store pivot columns (so can easily compress) CoinBigIndex startColumn = startColumnU[pivotColumn]; CoinBigIndex endColumn = startColumn + tempColumnCount[jPivotColumn]; CoinSimplexInt next = nextRow[pivotRow]; CoinSimplexInt last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; #ifdef SMALL_PERMUTE permuteAddress_[realPivotRow] = numberGoodU_; //use for permute #else permuteAddress_[pivotRow] = numberGoodU_; //use for permute #endif lastRow[pivotRow] = -2; numberInRow[pivotRow] = 0; assert (tempColumnCount[0]>=0); //store column in L, compress in U and take column out CoinBigIndex l = lengthL_; if ( l + numberInPivotColumn > lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) printf("more memory needed in middle of invert\n"); return -99; } //CoinBigIndex * COIN_RESTRICT startColumnL = startColumnL_.array(); numberGoodL_++; // move to L and move last numberInPivotColumn--; assert (tempColumnCount[0]>=0); if (jPivotRow!=numberInPivotColumn) { // swap for (int jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinFactorizationDouble * COIN_RESTRICT area =eArea+jColumn*lengthArea; CoinFactorizationDouble thisValue = area[jPivotRow]; area[jPivotRow]=area[numberInPivotColumn]; area[numberInPivotColumn]=thisValue; } // do indexL in last one int tempI=indexL[numberInPivotColumn]; CoinFactorizationDouble tempD=multipliersL[numberInPivotColumn]; indexL[numberInPivotColumn]=indexL[jPivotRow]; multipliersL[numberInPivotColumn]=multipliersL[jPivotRow]; indexL[jPivotRow]=tempI; multipliersL[jPivotRow]=tempD; jPivotRow=numberInPivotColumn; } assert (tempColumnCount[0]>=0); numberInPivotRow--; CoinFactorizationDouble pivotElement = area[numberInPivotColumn]; area[numberInPivotColumn]=0.0; // put last one in now CoinFactorizationDouble * COIN_RESTRICT areaLast =eArea+numberInPivotRow*lengthArea; // swap columns saveColumn[jPivotColumn]=saveColumn[numberInPivotRow]; saveColumn[numberInPivotRow]=pivotColumn; //int temp=tempColumnCount[jPivotColumn]; tempColumnCount[jPivotColumn]=tempColumnCount[numberInPivotRow]; totalElements_-=numberInColumn[pivotColumn]; mark[pivotColumn]=0; assert (tempColumnCount[0]>=0); for (int jRow=0;jRow=0); area[numberInPivotColumn]=thisPivotValue; if (fabs(thisPivotValue)>tolerance) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; int nKeep=tempColumnCount[jColumn]; if (nKeep) { if (nKeep>1) { // need to move one to end elementU[startColumn+nKeep]=elementU[startColumn+1]; indexRowU[startColumn+nKeep]=indexRowU[startColumn+1]; } // move largest elementU[startColumn+1]=elementU[startColumn]; indexRowU[startColumn+1]=indexRowU[startColumn]; } elementU[startColumn] = thisPivotValue; indexRowU[startColumn] = realPivotRow; startColumn++; startColumnU[iColumn]=startColumn; numberInColumnPlus[iColumn]++; //numberInColumn[iColumn]--; } } assert (tempColumnCount[0]>=0); // put away last (but remember count is one out) CoinAbcMemcpy(elementL+lSave,multipliersL,numberInPivotColumn+1); lSave=l; for (int i=0;i=0); multipliersL[l-lSave] = value; l++; } startColumnL[numberGoodL_] = l; lengthL_ = l; CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; pivotRegionAddress_[numberGoodU_] = pivotMultiplier; numberInColumn[pivotColumn] = 0; indexL = &indexRowL[lSave]; //adjust for (CoinSimplexInt j = 0; j < numberInPivotColumn; j++ ) { multipliersL[j] *= pivotMultiplier; } // zero out last multipliersL[numberInPivotColumn]=0.0; } else { // singular // give up break; } } assert (tempColumnCount[0]>=0); #if 0 // zero out extra bits int add1=numberInPivotColumn>>5; unsigned int * aBitsThis = aBits; int left=numberInPivotColumn-(add1<<5); unsigned int mark1 = (1<<(left-1)-1); int jColumn; for (jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { memset(aBitsThis+add1,0,(intsPerColumn-add1)*sizeof(int)); aBitsThis += intsPerColumn; } for (; jColumn < numberInPivotRow+numberZeroOther; jColumn++ ) { memset(aBitsThis,0,intsPerColumn*sizeof(int)); aBitsThis += intsPerColumn; } #endif // last bit inAreaAlready=true; } #endif #if 0 for (int i=0;i=0); #endif //if (added<1000) //giveUp=CoinMax(); //?? #ifdef DENSE_TRY if (!inAreaAlready) { #endif pivotSome(0,numberInPivotRow,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); #ifdef DENSE_TRY } else { pivotSomeAfter(0,numberInPivotRow,numberInPivotColumn,lengthArea,giveUp, eArea,saveColumn,startColumnU,tempColumnCount, elementU,numberInColumn,indexRowU,aBits,indexL, multipliersL,tolerance); } #endif #if 0 for (int i=0;i=0); #endif //serial for (int jRow = 0; jRow < numberInPivotColumn; jRow++ ) { CoinSimplexInt iRow = indexL[jRow]; CoinSimplexInt next = nextRow[iRow]; CoinBigIndex space = startRowU[next] - startRowU[iRow]; // assume full int numberNeeded = numberInPivotRow+numberInRow[iRow]; tempCount[jRow]=numberInRow[iRow]; numberInRow[iRow]=numberNeeded; if ( space < numberNeeded ) { if ( !getRowSpace ( iRow, numberNeeded ) ) { return -99; } } lastEntryByRowU_ = CoinMax(startRowU[iRow]+numberNeeded,lastEntryByRowU_); // in case I got it wrong! if (lastEntryByRowU_>lengthAreaU_) { return -99; } } // move counts back for (int jRow = 0; jRow < numberInPivotColumn; jRow++ ) { CoinSimplexInt iRow = indexL[jRow]; numberInRow[iRow]=tempCount[jRow]; } // parallel cilk_for_query (int jRow = 0; jRow < numberInPivotColumn; jRow++ ) { CoinSimplexInt iRow = indexL[jRow]; CoinBigIndex startRow = startRowU[iRow]; CoinBigIndex put = startRow + numberInRow[iRow]; int iWord = jRow>>5; unsigned int setBit=1<<(jRow&31); unsigned int * aBitsThis = aBits+iWord; for (int i=0;i=0&&indexRowU[i]10000) printf("INrow %d incolumn %d nzero %d\n", numberInPivotRow,numberInPivotColumn,numberZeroOther); #endif //printf("INrow %d incolumn %d nzero %d ratio %g\n", // numberInPivotRow,numberInPivotColumn,numberZeroOther,ratio); for (int i=0;i=tolerance) ; int iRow=indexRowL[j]; indexRowL[j] = fromSmallToBigRow_[iRow]; } #endif markRow[pivotRow] = LARGE_UNSET; //modify linked list for pivots deleteLink ( pivotRow ); deleteLink ( pivotColumn + numberRows_ ); totalElements_ += added; return status; } #endif // nonparallel pivot int CoinAbcTypeFactorization::pivot ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn, CoinBigIndex pivotRowPosition, CoinBigIndex pivotColumnPosition, CoinFactorizationDouble * COIN_RESTRICT work, CoinSimplexUnsignedInt * COIN_RESTRICT workArea2, CoinSimplexInt increment2, int * COIN_RESTRICT markRow) { CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnU_.array(); CoinBigIndex * COIN_RESTRICT startColumnU = startColumnU_.array(); CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumn_.array(); CoinFactorizationDouble * COIN_RESTRICT elementU = elementU_.array(); CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowU_.array(); CoinBigIndex * COIN_RESTRICT startRowU = startRowU_.array(); CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRow_.array(); CoinFactorizationDouble * COIN_RESTRICT elementL = elementL_.array(); CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowL_.array(); CoinSimplexInt * COIN_RESTRICT saveColumn = saveColumn_.array(); CoinSimplexInt * COIN_RESTRICT nextRow = nextRow_.array(); CoinSimplexInt * COIN_RESTRICT lastRow = lastRow_.array() ; #ifdef SMALL_PERMUTE int realPivotRow=fromSmallToBigRow_[pivotRow]; //int realPivotColumn=fromSmallToBigColumn[pivotColumn]; #endif //store pivot columns (so can easily compress) CoinSimplexInt numberInPivotRow = numberInRow[pivotRow] - 1; CoinBigIndex startColumn = startColumnU[pivotColumn]; CoinSimplexInt numberInPivotColumn = numberInColumn[pivotColumn] - 1; // temp CoinBigIndex endColumn = startColumn + numberInPivotColumn + 1; CoinBigIndex put = 0; CoinBigIndex startRow = startRowU[pivotRow]; CoinBigIndex endRow = startRow + numberInPivotRow + 1; #if ABC_SMALL<2 // temp - switch off marker for valid row/column lookup sparseThreshold_=-1; #endif if ( pivotColumnPosition < 0 ) { for ( pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++ ) { CoinSimplexInt iColumn = indexColumnU[pivotColumnPosition]; if ( iColumn != pivotColumn ) { saveColumn[put++] = iColumn; } else { #if BOTH_WAYS #endif break; } } } else { for (CoinBigIndex i = startRow ; i < pivotColumnPosition ; i++ ) { saveColumn[put++] = indexColumnU[i]; } } assert (pivotColumnPosition lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) printf("more memory needed in middle of invert\n"); return -99; } //l+=currentAreaL_->elementByColumn-elementL; CoinBigIndex lSave = l; CoinBigIndex * COIN_RESTRICT startColumnL = startColumnL_.array(); startColumnL[numberGoodL_] = l; //for luck and first time numberGoodL_++; startColumnL[numberGoodL_] = l + numberInPivotColumn; lengthL_ += numberInPivotColumn; if ( pivotRowPosition < 0 ) { for ( pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++ ) { CoinSimplexInt iRow = indexRowU[pivotRowPosition]; if ( iRow != pivotRow ) { indexRowL[l] = iRow; elementL[l] = elementU[pivotRowPosition]; markRow[iRow] = l - lSave; l++; //take out of row list CoinBigIndex start = startRowU[iRow]; CoinBigIndex end = start + numberInRow[iRow]; CoinBigIndex where = start; while ( indexColumnU[where] != pivotColumn ) { where++; } /* endwhile */ #if DEBUG_COIN if ( where >= end ) { abort ( ); } #endif #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; numberInRow[iRow]--; } else { break; } } } else { CoinBigIndex i; for ( i = startColumn; i < pivotRowPosition; i++ ) { CoinSimplexInt iRow = indexRowU[i]; markRow[iRow] = l - lSave; indexRowL[l] = iRow; elementL[l] = elementU[i]; l++; //take out of row list CoinBigIndex start = startRowU[iRow]; CoinBigIndex end = start + numberInRow[iRow]; CoinBigIndex where = start; while ( indexColumnU[where] != pivotColumn ) { where++; } /* endwhile */ #if DEBUG_COIN if ( where >= end ) { abort ( ); } #endif #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; numberInRow[iRow]--; assert (numberInRow[iRow]>=0); } } assert (pivotRowPosition= end ) { abort ( ); } #endif #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; numberInRow[iRow]--; assert (numberInRow[iRow]>=0); } markRow[pivotRow] = LARGE_SET; //compress pivot column (move pivot to front including saved) numberInColumn[pivotColumn] = 0; //use end of L for temporary space CoinSimplexInt * COIN_RESTRICT indexL = &indexRowL[lSave]; CoinFactorizationDouble * COIN_RESTRICT multipliersL = &elementL[lSave]; //adjust CoinSimplexInt j; for ( j = 0; j < numberInPivotColumn; j++ ) { multipliersL[j] *= pivotMultiplier; } CoinBigIndex added = numberInPivotRow * numberInPivotColumn; //zero out fill CoinBigIndex iErase; for ( iErase = 0; iErase < increment2 * numberInPivotRow; iErase++ ) { workArea2[iErase] = 0; } CoinSimplexUnsignedInt * COIN_RESTRICT temp2 = workArea2; CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumn_.array(); //pack down and move to work CoinSimplexInt jColumn; for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; CoinBigIndex startColumn = startColumnU[iColumn]; CoinBigIndex endColumn = startColumn + numberInColumn[iColumn]; CoinSimplexInt iRow = indexRowU[startColumn]; CoinFactorizationDouble value = elementU[startColumn]; CoinSimplexDouble largest; CoinBigIndex put = startColumn; CoinBigIndex positionLargest = -1; CoinFactorizationDouble thisPivotValue = 0.0; //compress column and find largest not updated bool checkLargest; CoinSimplexInt mark = markRow[iRow]; if ( mark == LARGE_UNSET ) { largest = fabs ( value ); positionLargest = put; put++; checkLargest = false; } else { //need to find largest largest = 0.0; checkLargest = true; if ( mark != LARGE_SET ) { //will be updated work[mark] = value; CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT; temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts added--; } else { thisPivotValue = value; } } CoinBigIndex i; for ( i = startColumn + 1; i < endColumn; i++ ) { iRow = indexRowU[i]; value = elementU[i]; CoinSimplexInt mark = markRow[iRow]; if ( mark == LARGE_UNSET ) { //keep indexRowU[put] = iRow; #if BOTH_WAYS #endif elementU[put] = value; if ( checkLargest ) { CoinSimplexDouble absValue = fabs ( value ); if ( absValue > largest ) { largest = absValue; positionLargest = put; } } put++; } else if ( mark != LARGE_SET ) { //will be updated work[mark] = value; CoinSimplexInt word = mark >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexInt bit = mark & COINFACTORIZATION_MASK_PER_INT; temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts added--; } else { thisPivotValue = value; } } //slot in pivot elementU[put] = elementU[startColumn]; indexRowU[put] = indexRowU[startColumn]; #if BOTH_WAYS #endif if ( positionLargest == startColumn ) { positionLargest = put; //follow if was largest } put++; elementU[startColumn] = thisPivotValue; #ifdef SMALL_PERMUTE indexRowU[startColumn] = realPivotRow; #else indexRowU[startColumn] = pivotRow; #endif #if BOTH_WAYS #endif //clean up counts startColumn++; numberInColumn[iColumn] = put - startColumn; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlus_.array(); numberInColumnPlus[iColumn]++; startColumnU[iColumn]++; //how much space have we got CoinSimplexInt next = nextColumn[iColumn]; CoinBigIndex space; space = startColumnU[next] - put - numberInColumnPlus[next]; //assume no zero elements if ( numberInPivotColumn > space ) { //getColumnSpace also moves fixed part if ( !getColumnSpace ( iColumn, numberInPivotColumn ) ) { return -99; } //redo starts positionLargest = positionLargest + startColumnU[iColumn] - startColumn; startColumn = startColumnU[iColumn]; put = startColumn + numberInColumn[iColumn]; } CoinSimplexDouble tolerance = zeroTolerance_; //CoinSimplexInt * COIN_RESTRICT nextCount = this->nextCount(); for ( j = 0; j < numberInPivotColumn; j++ ) { value = work[j] - thisPivotValue * multipliersL[j]; CoinSimplexDouble absValue = fabs ( value ); if ( absValue > tolerance ) { work[j] = 0.0; assert (put largest ) { largest = absValue; positionLargest = put; } put++; } else { work[j] = 0.0; added--; CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT; if ( temp2[word] & ( 1 << bit ) ) { //take out of row list iRow = indexL[j]; CoinBigIndex start = startRowU[iRow]; CoinBigIndex end = start + numberInRow[iRow]; CoinBigIndex where = start; while ( indexColumnU[where] != iColumn ) { where++; } /* endwhile */ #if DEBUG_COIN if ( where >= end ) { abort ( ); } #endif #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; numberInRow[iRow]--; } else { //make sure won't be added CoinSimplexInt word = j >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexInt bit = j & COINFACTORIZATION_MASK_PER_INT; temp2[word] = temp2[word] | ( 1 << bit ); //say already in counts } } } numberInColumn[iColumn] = put - startColumn; //move largest if ( positionLargest >= 0 ) { value = elementU[positionLargest]; iRow = indexRowU[positionLargest]; elementU[positionLargest] = elementU[startColumn]; indexRowU[positionLargest] = indexRowU[startColumn]; elementU[startColumn] = value; indexRowU[startColumn] = iRow; #if BOTH_WAYS #endif } //linked list for column //if ( nextCount[iColumn + numberRows_] != -2 ) { //modify linked list //deleteLink ( iColumn + numberRows_ ); //modifyLink ( iColumn + numberRows_, numberInColumn[iColumn] ); //} temp2 += increment2; } //get space for row list CoinSimplexUnsignedInt * COIN_RESTRICT putBase = workArea2; CoinSimplexInt bigLoops = numberInPivotColumn >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexInt i = 0; // do linked lists and update counts while ( bigLoops ) { bigLoops--; CoinSimplexInt bit; for ( bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++ ) { CoinSimplexUnsignedInt *putThis = putBase; CoinSimplexInt iRow = indexL[i]; //get space CoinSimplexInt number = 0; CoinSimplexInt jColumn; for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexUnsignedInt test = *putThis; putThis += increment2; test = 1 - ( ( test >> bit ) & 1 ); number += test; } CoinSimplexInt next = nextRow[iRow]; CoinBigIndex space; space = startRowU[next] - startRowU[iRow]; number += numberInRow[iRow]; if ( space < number ) { if ( !getRowSpace ( iRow, number ) ) { return -99; } } // now do putThis = putBase; next = nextRow[iRow]; number = numberInRow[iRow]; CoinBigIndex end = startRowU[iRow] + number; CoinSimplexInt saveIndex = indexColumnU[startRowU[next]]; //add in for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexUnsignedInt test = *putThis; putThis += increment2; test = 1 - ( ( test >> bit ) & 1 ); indexColumnU[end] = saveColumn[jColumn]; #if BOTH_WAYS #endif end += test; } lastEntryByRowU_ = CoinMax(end,lastEntryByRowU_); assert (lastEntryByRowU_<=lengthAreaU_); //put back next one in case zapped indexColumnU[startRowU[next]] = saveIndex; #if BOTH_WAYS #endif markRow[iRow] = LARGE_UNSET; number = end - startRowU[iRow]; numberInRow[iRow] = number; //deleteLink ( iRow ); //modifyLink ( iRow, number ); } putBase++; } /* endwhile */ CoinSimplexInt bit; for ( bit = 0; i < numberInPivotColumn; i++, bit++ ) { CoinSimplexUnsignedInt *putThis = putBase; CoinSimplexInt iRow = indexL[i]; //get space CoinSimplexInt number = 0; CoinSimplexInt jColumn; for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexUnsignedInt test = *putThis; putThis += increment2; test = 1 - ( ( test >> bit ) & 1 ); number += test; } CoinSimplexInt next = nextRow[iRow]; CoinBigIndex space; space = startRowU[next] - startRowU[iRow]; number += numberInRow[iRow]; if ( space < number ) { if ( !getRowSpace ( iRow, number ) ) { return -99; } } // now do putThis = putBase; next = nextRow[iRow]; number = numberInRow[iRow]; CoinBigIndex end = startRowU[iRow] + number; CoinSimplexInt saveIndex; saveIndex = indexColumnU[startRowU[next]]; //if (numberRowsSmall_==2791&&iRow==1160) //printf("start %d end %d\n",startRowU[iRow],end); //add in for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexUnsignedInt test = *putThis; putThis += increment2; test = 1 - ( ( test >> bit ) & 1 ); indexColumnU[end] = saveColumn[jColumn]; #if BOTH_WAYS #endif end += test; //if (numberRowsSmall_==2791&&iRow==1160) //printf("start %d end %d test %d col %d\n",startRowU[iRow],end,test,saveColumn[jColumn]); } indexColumnU[startRowU[next]] = saveIndex; lastEntryByRowU_ = CoinMax(end,lastEntryByRowU_); assert (lastEntryByRowU_<=lengthAreaU_); #if BOTH_WAYS #endif markRow[iRow] = LARGE_UNSET; number = end - startRowU[iRow]; numberInRow[iRow] = number; //deleteLink ( iRow ); //modifyLink ( iRow, number ); } for ( jColumn = 0; jColumn < numberInPivotRow; jColumn++ ) { CoinSimplexInt iColumn = saveColumn[jColumn]; modifyLink ( iColumn + numberRows_, numberInColumn[iColumn] ); } for (int i=0;i(elementUColumnPlusAddress_+lastEntryByColumnUPlus_),indexRow+startC,number); lastEntryByColumnUPlus_ += (number+1)>>1; #ifdef ABC_USE_FUNCTION_POINTERS if (!numberInColumnAddress_[pivotColumn]) { int iNext=nextColumnAddress_[pivotColumn]; int iLast=lastColumnAddress_[pivotColumn]; lastColumnAddress_[iNext]=iLast; assert (iLast>=0); nextColumnAddress_[iLast]=iNext; } #endif #endif numberGoodU_++; numberRowsLeft_--; #if COIN_DEBUG==2 checkConsistency ( ); #endif } #if ABC_DENSE_CODE // After pivoting - returns true if need to go dense int CoinAbcTypeFactorization::wantToGoDense() { int status=0; if (denseThreshold_) { // see whether to go dense // only if exact multiple if ((numberRowsLeft_&7)==0) { CoinSimplexDouble full = numberRowsLeft_; full *= full; assert (full>=0.0); CoinSimplexDouble leftElements = totalElements_; //if (numberRowsLeft_==100) //printf("at 100 %d elements\n",totalElements_); CoinSimplexDouble ratio; if (numberRowsLeft_>2000) ratio=4.5; else if (numberRowsLeft_>800) ratio=3.0;//3.5; else if (numberRowsLeft_>256) ratio=2.0;//2.5; //else if (numberRowsLeft_==8) //ratio=200.0; else ratio=1.5; //ratio *=0.75; if ((ratio*leftElements>full&&numberRowsLeft_>abs(denseThreshold_))) { #if 0 //ndef NDEBUG //return to do dense CoinSimplexInt check=0; for (CoinSimplexInt iColumn=0;iColumn1 std::cout<<" Went dense at "< lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) std::cout << "more memory needed in middle of invert" << std::endl; return false; } CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; startColumnL[numberGoodL_] = l; //for luck and first time numberGoodL_++; startColumnL[numberGoodL_] = l + numberDoColumn; lengthL_ += numberDoColumn; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinFactorizationDouble pivotElement = elementU[pivotRowPosition]; CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; pivotRegionAddress_[numberGoodU_] = pivotMultiplier; CoinBigIndex i; CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #ifdef SMALL_PERMUTE int realPivotRow=fromSmallToBigRow_[pivotRow]; #endif for ( i = startColumn; i < pivotRowPosition; i++ ) { CoinSimplexInt iRow = indexRowU[i]; #ifdef SMALL_PERMUTE indexRowL[l] = fromSmallToBigRow_[iRow]; #else indexRowL[l] = iRow; #endif elementL[l] = elementU[i] * pivotMultiplier; l++; //take out of row list CoinBigIndex start = startRowU[iRow]; CoinSimplexInt iNumberInRow = numberInRow[iRow]; CoinBigIndex end = start + iNumberInRow; CoinBigIndex where = start; while ( indexColumnU[where] != pivotColumn ) { where++; } /* endwhile */ assert ( where < end ); #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; iNumberInRow--; numberInRow[iRow] = iNumberInRow; modifyLink ( iRow, iNumberInRow ); } for ( i = pivotRowPosition + 1; i < endColumn; i++ ) { CoinSimplexInt iRow = indexRowU[i]; #ifdef SMALL_PERMUTE indexRowL[l] = fromSmallToBigRow_[iRow]; #else indexRowL[l] = iRow; #endif elementL[l] = elementU[i] * pivotMultiplier; l++; //take out of row list CoinBigIndex start = startRowU[iRow]; CoinSimplexInt iNumberInRow = numberInRow[iRow]; CoinBigIndex end = start + iNumberInRow; CoinBigIndex where = start; while ( indexColumnU[where] != pivotColumn ) { where++; } /* endwhile */ assert ( where < end ); #if BOTH_WAYS #endif indexColumnU[where] = indexColumnU[end - 1]; iNumberInRow--; numberInRow[iRow] = iNumberInRow; modifyLink ( iRow, iNumberInRow ); } numberInColumn[pivotColumn] = 0; //modify linked list for pivots numberInRow[pivotRow] = 0; deleteLink ( pivotRow ); deleteLink ( pivotColumn + numberRows_ ); //take out this bit of indexColumnU CoinSimplexInt next = nextRow[pivotRow]; CoinSimplexInt last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; lastRow[pivotRow] =-2; #ifdef SMALL_PERMUTE permuteAddress_[realPivotRow]=numberGoodU_; #else permuteAddress_[pivotRow]=numberGoodU_; #endif return true; } // pivotColumnSingleton. Does one pivot on Column Singleton in factorization void CoinAbcTypeFactorization::pivotColumnSingleton ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ) { CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; //store pivot columns (so can easily compress) CoinSimplexInt numberDoRow = numberInRow[pivotRow] - 1; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinBigIndex startColumn = startColumnU[pivotColumn]; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; CoinBigIndex startRow = startRowU[pivotRow]; CoinBigIndex endRow = startRow + numberDoRow + 1; CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; //take out this bit of indexColumnU CoinSimplexInt next = nextRow[pivotRow]; CoinSimplexInt last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; lastRow[pivotRow] =-2; //mark #ifdef SMALL_PERMUTE int realPivotRow=fromSmallToBigRow_[pivotRow]; permuteAddress_[realPivotRow]=numberGoodU_; #else permuteAddress_[pivotRow]=numberGoodU_; #endif //clean up counts CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinFactorizationDouble pivotElement = elementU[startColumn]; pivotRegionAddress_[numberGoodU_] = 1.0 / pivotElement; numberInColumn[pivotColumn] = 0; CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; //CoinSimplexInt * COIN_RESTRICT saveColumn = saveColumnAddress_; CoinBigIndex i; // would I be better off doing other way first?? for ( i = startRow; i < endRow; i++ ) { CoinSimplexInt iColumn = indexColumnU[i]; if ( numberInColumn[iColumn] ) { CoinSimplexInt number = numberInColumn[iColumn] - 1; //modify linked list modifyLink ( iColumn + numberRows_, number ); //move pivot row element #ifdef SMALL_PERMUTE CoinBigIndex start = startColumnU[iColumn]; #endif if ( number ) { #ifndef SMALL_PERMUTE CoinBigIndex start = startColumnU[iColumn]; #endif CoinBigIndex pivot = start; CoinSimplexInt iRow = indexRowU[pivot]; while ( iRow != pivotRow ) { pivot++; iRow = indexRowU[pivot]; } assert (pivot < startColumnU[iColumn] + numberInColumn[iColumn]); #if BOTH_WAYS #endif if ( pivot != start ) { //move largest one up CoinFactorizationDouble value = elementU[start]; iRow = indexRowU[start]; elementU[start] = elementU[pivot]; assert (indexRowU[pivot]==pivotRow); indexRowU[start] = indexRowU[pivot]; elementU[pivot] = elementU[start + 1]; indexRowU[pivot] = indexRowU[start + 1]; elementU[start + 1] = value; indexRowU[start + 1] = iRow; #if BOTH_WAYS #endif } else { //find new largest element CoinSimplexInt iRowSave = indexRowU[start + 1]; CoinFactorizationDouble valueSave = elementU[start + 1]; CoinFactorizationDouble valueLargest = fabs ( valueSave ); CoinBigIndex end = start + numberInColumn[iColumn]; CoinBigIndex largest = start + 1; CoinBigIndex k; for ( k = start + 2; k < end; k++ ) { CoinFactorizationDouble value = elementU[k]; CoinFactorizationDouble valueAbs = fabs ( value ); if ( valueAbs > valueLargest ) { valueLargest = valueAbs; largest = k; } } indexRowU[start + 1] = indexRowU[largest]; elementU[start + 1] = elementU[largest]; indexRowU[largest] = iRowSave; elementU[largest] = valueSave; #if BOTH_WAYS #endif } } #ifdef SMALL_PERMUTE indexRowU[start]=realPivotRow; #endif //clean up counts numberInColumn[iColumn]--; numberInColumnPlus[iColumn]++; startColumnU[iColumn]++; //totalElements_--; } } //modify linked list for pivots deleteLink ( pivotRow ); deleteLink ( pivotColumn + numberRows_ ); numberInRow[pivotRow] = 0; //put in dummy pivot in L CoinBigIndex l = lengthL_; CoinBigIndex * startColumnL = startColumnLAddress_; startColumnL[numberGoodL_] = l; //for luck and first time numberGoodL_++; startColumnL[numberGoodL_] = l; } // getColumnSpace. Gets space for one Column with given length //may have to do compression (returns true) //also moves existing vector bool CoinAbcTypeFactorization::getColumnSpace ( CoinSimplexInt iColumn, CoinSimplexInt extraNeeded ) { CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; CoinSimplexInt number = numberInColumnPlus[iColumn] + numberInColumn[iColumn]; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinBigIndex space = lengthAreaU_ - lastEntryByColumnU_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; if ( space < extraNeeded + number + 4 ) { //compression CoinSimplexInt iColumn = nextColumn[maximumRowsExtra_]; CoinBigIndex put = 0; while ( iColumn != maximumRowsExtra_ ) { //move CoinBigIndex get; CoinBigIndex getEnd; if ( startColumnU[iColumn] >= 0 ) { get = startColumnU[iColumn] - numberInColumnPlus[iColumn]; getEnd = startColumnU[iColumn] + numberInColumn[iColumn]; startColumnU[iColumn] = put + numberInColumnPlus[iColumn]; } else { get = -startColumnU[iColumn]; getEnd = get + numberInColumn[iColumn]; startColumnU[iColumn] = -put; } assert (put<=get); for (CoinBigIndex i = get; i < getEnd; i++ ) { indexRowU[put] = indexRowU[i]; elementU[put] = elementU[i]; #if BOTH_WAYS #endif put++; } iColumn = nextColumn[iColumn]; } /* endwhile */ numberCompressions_++; lastEntryByColumnU_ = put; space = lengthAreaU_ - put; if ( extraNeeded == COIN_INT_MAX >> 1 ) { return true; } if ( space < extraNeeded + number + 2 ) { //need more space //if we can allocate bigger then do so and copy //if not then return so code can start again status_ = -99; return false; } } CoinBigIndex put = lastEntryByColumnU_; CoinSimplexInt next = nextColumn[iColumn]; CoinSimplexInt last = lastColumn[iColumn]; if ( extraNeeded || next != maximumRowsExtra_ ) { //out nextColumn[last] = next; lastColumn[next] = last; //in at end last = lastColumn[maximumRowsExtra_]; nextColumn[last] = iColumn; lastColumn[maximumRowsExtra_] = iColumn; lastColumn[iColumn] = last; nextColumn[iColumn] = maximumRowsExtra_; //move CoinBigIndex get = startColumnU[iColumn] - numberInColumnPlus[iColumn]; startColumnU[iColumn] = put + numberInColumnPlus[iColumn]; CoinSimplexInt *indexRow = indexRowU; CoinFactorizationDouble *element = elementU; CoinSimplexInt i = 0; if ( ( number & 1 ) != 0 ) { element[put] = element[get]; indexRow[put] = indexRow[get]; #if BOTH_WAYS #endif i = 1; } for ( ; i < number; i += 2 ) { CoinFactorizationDouble value0 = element[get + i]; CoinFactorizationDouble value1 = element[get + i + 1]; CoinSimplexInt index0 = indexRow[get + i]; CoinSimplexInt index1 = indexRow[get + i + 1]; element[put + i] = value0; element[put + i + 1] = value1; indexRow[put + i] = index0; indexRow[put + i + 1] = index1; #if BOTH_WAYS #endif } put += number; get += number; //add 2 for luck lastEntryByColumnU_ = put + extraNeeded + 2; if (lastEntryByColumnU_>lengthAreaU_) { // get more memory #ifdef CLP_DEVELOP printf("put %d, needed %d, start %d, length %d\n", put,extraNeeded,lastEntryByColumnU_, lengthAreaU_); #endif return false; } } else { //take off space lastEntryByColumnU_ = startColumnU[last] + numberInColumn[last]; } startColumnU[maximumRowsExtra_]=lastEntryByColumnU_; return true; } // getRowSpace. Gets space for one Row with given length //may have to do compression (returns true) //also moves existing vector bool CoinAbcTypeFactorization::getRowSpace ( CoinSimplexInt iRow, CoinSimplexInt extraNeeded ) { CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt number = numberInRow[iRow]; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; CoinBigIndex space = lengthAreaU_ - lastEntryByRowU_; CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; if ( space < extraNeeded + number + 2 ) { //compression CoinSimplexInt iRow = nextRow[numberRows_]; CoinBigIndex put = 0; while ( iRow != numberRows_ ) { //move CoinBigIndex get = startRowU[iRow]; CoinBigIndex getEnd = startRowU[iRow] + numberInRow[iRow]; startRowU[iRow] = put; if (put>get) { //need more space //if we can allocate bigger then do so and copy //if not then return so code can start again status_ = -99; return false;; } CoinBigIndex i; for ( i = get; i < getEnd; i++ ) { indexColumnU[put] = indexColumnU[i]; #if BOTH_WAYS #endif put++; } iRow = nextRow[iRow]; } /* endwhile */ numberCompressions_++; lastEntryByRowU_ = put; space = lengthAreaU_ - put; if ( space < extraNeeded + number + 2 ) { //need more space //if we can allocate bigger then do so and copy //if not then return so code can start again status_ = -99; return false;; } } CoinBigIndex put = lastEntryByRowU_; CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt last = lastRow[iRow]; //out nextRow[last] = next; lastRow[next] = last; //in at end last = lastRow[numberRows_]; nextRow[last] = iRow; lastRow[numberRows_] = iRow; lastRow[iRow] = last; nextRow[iRow] = numberRows_; //move CoinBigIndex get = startRowU[iRow]; startRowU[iRow] = put; while ( number ) { number--; indexColumnU[put] = indexColumnU[get]; #if BOTH_WAYS #endif put++; get++; } /* endwhile */ //add 4 for luck lastEntryByRowU_ = put + extraNeeded + 4; return true; } // cleanup. End of factorization void CoinAbcTypeFactorization::cleanup ( ) { #ifdef ABC_USE_FUNCTION_POINTERS #define PRINT_LEVEL 0 if (PRINT_LEVEL){ printf("----------Start---------\n"); #if PRINT_LEVEL<2 double smallestP=COIN_DBL_MAX; int iPs=-1; double largestP=0.0; int iP=-1; double largestL=0.0; int iL=-1; double largestU=0.0; int iU=-1; #endif for (int i=0;i1 printf("%d permute %d pivotColumn %d pivotRegion %g\n",i,permuteAddress_[i], pivotColumnAddress_[i],pivotRegionAddress_[i]); #else if (fabs(pivotRegionAddress_[i])>largestP) { iP=i; largestP=fabs(pivotRegionAddress_[i]); } if (fabs(pivotRegionAddress_[i])1 printf("pivot %d offset %d number %d\n",i,scatter.offset,number); #endif const CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter.offset; const CoinBigIndex * COIN_RESTRICT indices = reinterpret_cast(area+number); #if PRINT_LEVEL>1 for (int j1 = 0; j1 < number; j1+=5 ) { for (int j = j1; j < CoinMin(number,j1+5); j++ ) printf("(%d,%g) ",indices[j],area[j]); printf("\n"); } #else for (int j = 0; j < number; j++ ) if (fabs(area[j])>largestU) { iU=i; largestU=fabs(area[j]); } #endif } printf("----------LLL---------\n"); CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; for (int i=0;i1 int * indices = indexRowL+startColumnL[i]; printf("%d has %d elements\n",i,number); for (int j1 = 0; j1 < number; j1+=5 ) { for (int j = j1; j < CoinMin(number,j1+5); j++ ) printf("(%d,%g) ",indices[j],elementL[j+startColumnL[i]]); printf("\n"); } #else for (int j = 0; j < number; j++ ) { if (fabs(elementL[j+startColumnL[i]])>largestL) { iL=i; largestL=fabs(elementL[j+startColumnL[i]]); } } #endif } } #if PRINT_LEVEL<2 printf("smallest pivot %g at %d, largest %g at %d - largestL %g at %d largestU %g at %d\n",smallestP,iPs,largestP,iP,largestL,iL,largestU,iU); #endif printf("----------End---------\n"); } #endif #ifdef ABC_ORDERED_FACTORIZATION { //int sizeL=0; //int sizeU=0; CoinSimplexInt * COIN_RESTRICT permuteA = permuteAddress_+maximumRowsExtra_+1; CoinSimplexInt * COIN_RESTRICT permuteB = permuteA + numberRows_; // one may be correct for (int i=0;i(area+number); for (int j = 0; j < number; j++ ) { int iRow=indices[j]; indices[j]=permuteA[iRow]; } } CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; for (int i=0;i=0&&permute[i]=numberRows_) printf("Bad a %d %d\n",i,k); assert(k>=0&&kpivotLOrder(); CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; bool cleanCopy=false; #if ABC_SMALL<2 assert (numberGoodU_==numberRows_); if (numberGoodU_==numberRows_) { #ifndef ABC_USE_FUNCTION_POINTERS const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnPlusAddress_; CoinFactorizationDouble * elementU = elementUAddress_; CoinFactorizationDouble * elementU2 = elementRowUAddress_; CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; CoinSimplexInt * COIN_RESTRICT indexRowU2 = indexColumnUAddress_; // so that just slacks will have start of 0 CoinBigIndex size=1; for (int i=0;i> 1 ); //compress // Redo total elements totalElements_=0; for (int i = 0; i < numberRows_; i++ ) { CoinSimplexInt number = numberInColumnPlus[i]; totalElements_ += number; startColumnU[i] -= number; } } #endif // swap arrays numberInColumn_.swap(numberInColumnPlus_); numberInColumnAddress_ = numberInColumn_.array(); numberInColumnPlusAddress_ = numberInColumnPlus_.array(); CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; #if ABC_SMALL<2 numberInColumnPlus = numberInColumnPlusAddress_; #endif //make column starts OK //for best cache behavior get in order (last pivot at bottom of space) //that will need thinking about lastEntryByRowU_ = totalElements_; CoinSimplexInt * COIN_RESTRICT back = firstCountAddress_+numberRows_; CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; #ifndef ABC_USE_FUNCTION_POINTERS maximumU_=startColumnU[numberRows_-1]+numberInColumn[numberRows_-1]; #else maximumU_=lastEntryByColumnUPlus_; #endif #ifndef ABC_ORDERED_FACTORIZATION CoinFactorizationDouble * COIN_RESTRICT workArea = workAreaAddress_; CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #else CoinSimplexInt * COIN_RESTRICT permuteA = permuteAddress_+maximumRowsExtra_+1; // use work area for scatter scatterStruct * COIN_RESTRICT scatterPointer = scatterUColumn(); scatterStruct * COIN_RESTRICT scatterPointerTemp = reinterpret_cast(workAreaAddress_); #endif for (CoinSimplexInt i=0;ipivotLOrder(),pivotLOrder,numberRows_*sizeof(int)); // swap later CoinAbcMemcpy(startColumnU,startRow,numberRows_); CoinAbcMemcpy(numberInColumn,numberInRow,numberRows_); #endif #if ABC_DENSE_CODE==2 if (numberDense_) { assert (numberDense_<30000); CoinFactorizationDouble * COIN_RESTRICT denseArea = denseAreaAddress_; CoinFactorizationDouble * COIN_RESTRICT denseRegion = denseArea+leadingDimension_*numberDense_; CoinSimplexInt * COIN_RESTRICT densePermute= reinterpret_cast(denseRegion+FACTOR_CPU*numberDense_); short * COIN_RESTRICT forFtran = reinterpret_cast(densePermute+numberDense_); short * COIN_RESTRICT forBtran = forFtran+numberDense_; short * COIN_RESTRICT forFtran2 = forBtran+numberDense_; // maybe could do inside dgetrf //CoinAbcMemcpy(forBtran,pivotLOrder+numberRows_-numberDense_,numberDense_); //CoinAbcMemcpy(forFtran,pivotLOrder+numberRows_-numberDense_,numberDense_); for (int i=0;i(i); forFtran[i]=static_cast(i); } for (int i=0;i=0;i--) { int ip=densePermute[i]; short temp=forFtran[i]; forFtran[i]=forFtran[ip]; forFtran[ip]=temp; } #if ABC_SMALL<3 const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; int lastSparse=numberRows_-numberDense_; forFtran -= lastSparse; // adjust CoinFillN(forFtran2,numberRows_,static_cast(-1)); for (int i=0;i=lastSparse) { short kRow = static_cast(forFtran[jRow]); forFtran2[i]=kRow; } } #endif } #endif CoinAbcMemset0(numberInRow,numberRows_+1); if ( (messageLevel_ & 8)) { std::cout<<" length of U "<=0 if (maximumU_>10*numberRows_||numberRows_<200) { // NO numberInColumnPlus_.conditionalDelete() ; numberInColumnPlusAddress_=NULL; setNoGotRCopy(); } else { #endif setYesGotRCopy(); for (int i = 0; i < numberRows_; i++ ) { lastColumn[i] = i - 1; nextColumn[i] = i + 1; numberInColumnPlus[i]=0; #if ABC_SMALL>=0 } #endif nextColumn[numberRows_ - 1] = maximumRowsExtra_; lastColumn[maximumRowsExtra_] = numberRows_ - 1; nextColumn[maximumRowsExtra_] = 0; lastColumn[0] = maximumRowsExtra_; } #endif numberU_ = numberGoodU_; numberL_ = numberGoodL_; CoinSimplexInt firstReal = numberSlacks_; CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; // We should know how many in L //CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; for (firstReal = numberSlacks_; firstReal= needed ) { lengthR_ = 0; lengthAreaR_ = space; } else { lengthR_ = 0; lengthAreaR_ = space; if ((messageLevel_&4)) std::cout<<"Factorization may need some increasing area space" <1.0) { double dense = numberDense_; dense *= dense; double withoutDense = totalElements_ - dense +1.0; factor *= 1.0 +dense/withoutDense; } #endif return factor; } // checkConsistency. Checks that row and column copies look OK void CoinAbcTypeFactorization::checkConsistency ( ) { bool bad = false; CoinSimplexInt iRow; CoinBigIndex * startRowU = startRowUAddress_; CoinSimplexInt * numberInRow = numberInRowAddress_; CoinSimplexInt * numberInColumn = numberInColumnAddress_; CoinSimplexInt * indexColumnU = indexColumnUAddress_; CoinSimplexInt * indexRowU = indexRowUAddress_; CoinBigIndex * startColumnU = startColumnUAddress_; for ( iRow = 0; iRow < numberRows_; iRow++ ) { if ( numberInRow[iRow] ) { CoinBigIndex startRow = startRowU[iRow]; CoinBigIndex endRow = startRow + numberInRow[iRow]; CoinBigIndex j; for ( j = startRow; j < endRow; j++ ) { CoinSimplexInt iColumn = indexColumnU[j]; CoinBigIndex startColumn = startColumnU[iColumn]; CoinBigIndex endColumn = startColumn + numberInColumn[iColumn]; bool found = false; CoinBigIndex k; for ( k = startColumn; k < endColumn; k++ ) { if ( indexRowU[k] == iRow ) { found = true; break; } } if ( !found ) { bad = true; std::cout << "row " << iRow << " column " << iColumn << " Rows" << std::endl; } } } } CoinSimplexInt iColumn; for ( iColumn = 0; iColumn < numberRows_; iColumn++ ) { if ( numberInColumn[iColumn] ) { CoinBigIndex startColumn = startColumnU[iColumn]; CoinBigIndex endColumn = startColumn + numberInColumn[iColumn]; CoinBigIndex j; for ( j = startColumn; j < endColumn; j++ ) { CoinSimplexInt iRow = indexRowU[j]; CoinBigIndex startRow = startRowU[iRow]; CoinBigIndex endRow = startRow + numberInRow[iRow]; bool found = false; CoinBigIndex k; for ( k = startRow; k < endRow; k++ ) { if ( indexColumnU[k] == iColumn ) { found = true; break; } } if ( !found ) { bad = true; std::cout << "row " << iRow << " column " << iColumn << " Columns" << std::endl; } } } } if ( bad ) { abort ( ); } } // pivotOneOtherRow. When just one other row so faster bool CoinAbcTypeFactorization::pivotOneOtherRow ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ) { CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; CoinSimplexInt COIN_RESTRICT numberInPivotRow = numberInRow[pivotRow] - 1; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinBigIndex startColumn = startColumnU[pivotColumn]; CoinBigIndex startRow = startRowU[pivotRow]; CoinBigIndex endRow = startRow + numberInPivotRow + 1; //take out this bit of indexColumnU CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; CoinSimplexInt next = nextRow[pivotRow]; CoinSimplexInt last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; lastRow[pivotRow] = -2; #ifdef SMALL_PERMUTE int realPivotRow=fromSmallToBigRow_[pivotRow]; //int realPivotColumn=fromSmallToBigColumn[pivotColumn]; #endif #ifdef SMALL_PERMUTE permuteAddress_[realPivotRow]=numberGoodU_; #else permuteAddress_[pivotRow]=numberGoodU_; #endif numberInRow[pivotRow] = 0; #if ABC_SMALL<2 // temp - switch off marker for valid row/column lookup sparseThreshold_=-2; #endif //store column in L, compress in U and take column out CoinBigIndex l = lengthL_; if ( l + 1 > lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) std::cout << "more memory needed in middle of invert" << std::endl; return false; } //l+=currentAreaL_->elementByColumn-elementL_; //CoinBigIndex lSave=l; CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; startColumnL[numberGoodL_] = l; //for luck and first time numberGoodL_++; startColumnL[numberGoodL_] = l + 1; lengthL_++; CoinFactorizationDouble pivotElement; CoinFactorizationDouble otherMultiplier; CoinSimplexInt otherRow; CoinSimplexInt * COIN_RESTRICT saveColumn = saveColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; if ( indexRowU[startColumn] == pivotRow ) { pivotElement = elementU[startColumn]; otherMultiplier = elementU[startColumn + 1]; otherRow = indexRowU[startColumn + 1]; } else { pivotElement = elementU[startColumn + 1]; otherMultiplier = elementU[startColumn]; otherRow = indexRowU[startColumn]; } CoinSimplexInt numberSave = numberInRow[otherRow]; CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; pivotRegion[numberGoodU_] = pivotMultiplier; numberInColumn[pivotColumn] = 0; otherMultiplier = otherMultiplier * pivotMultiplier; #ifdef SMALL_PERMUTE indexRowL[l] = fromSmallToBigRow_[otherRow]; #else indexRowL[l] = otherRow; #endif elementL[l] = otherMultiplier; //take out of row list CoinBigIndex start = startRowU[otherRow]; CoinBigIndex end = start + numberSave; CoinBigIndex where = start; CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; while ( indexColumnU[where] != pivotColumn ) { where++; } /* endwhile */ assert ( where < end ); #if BOTH_WAYS #endif end--; indexColumnU[where] = indexColumnU[end]; CoinSimplexInt numberAdded = 0; CoinSimplexInt numberDeleted = 0; //pack down and move to work CoinSimplexInt j; const CoinSimplexInt * COIN_RESTRICT nextCount = this->nextCountAddress_; CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; for ( j = startRow; j < endRow; j++ ) { CoinSimplexInt iColumn = indexColumnU[j]; if ( iColumn != pivotColumn ) { CoinBigIndex startColumn = startColumnU[iColumn]; CoinSimplexInt numberInColumnIn=numberInColumn[iColumn]; CoinBigIndex endColumn = startColumn + numberInColumnIn; CoinSimplexInt iRow = indexRowU[startColumn]; CoinFactorizationDouble value = elementU[startColumn]; CoinFactorizationDouble largest; bool foundOther = false; //leave room for pivot CoinBigIndex put = startColumn + 1; CoinBigIndex positionLargest = -1; CoinFactorizationDouble thisPivotValue = 0.0; CoinFactorizationDouble otherElement = 0.0; CoinFactorizationDouble nextValue = elementU[put];; CoinSimplexInt nextIRow = indexRowU[put]; //compress column and find largest not updated if ( iRow != pivotRow ) { if ( iRow != otherRow ) { largest = fabs ( value ); elementU[put] = value; indexRowU[put] = iRow; positionLargest = put; #if BOTH_WAYS #endif put++; CoinBigIndex i; for ( i = startColumn + 1; i < endColumn; i++ ) { iRow = nextIRow; value = nextValue; nextIRow = indexRowU[i + 1]; nextValue = elementU[i + 1]; if ( iRow != pivotRow ) { if ( iRow != otherRow ) { //keep indexRowU[put] = iRow; elementU[put] = value;; #if BOTH_WAYS #endif put++; } else { otherElement = value; foundOther = true; } } else { thisPivotValue = value; } } } else { otherElement = value; foundOther = true; //need to find largest largest = 0.0; CoinBigIndex i; for ( i = startColumn + 1; i < endColumn; i++ ) { iRow = nextIRow; value = nextValue; nextIRow = indexRowU[i + 1]; nextValue = elementU[i + 1]; if ( iRow != pivotRow ) { //keep indexRowU[put] = iRow; elementU[put] = value;; #if BOTH_WAYS #endif CoinFactorizationDouble absValue = fabs ( value ); if ( absValue > largest ) { largest = absValue; positionLargest = put; } put++; } else { thisPivotValue = value; } } } } else { //need to find largest largest = 0.0; thisPivotValue = value; CoinBigIndex i; for ( i = startColumn + 1; i < endColumn; i++ ) { iRow = nextIRow; value = nextValue; nextIRow = indexRowU[i + 1]; nextValue = elementU[i + 1]; if ( iRow != otherRow ) { //keep indexRowU[put] = iRow; elementU[put] = value;; #if BOTH_WAYS #endif CoinFactorizationDouble absValue = fabs ( value ); if ( absValue > largest ) { largest = absValue; positionLargest = put; } put++; } else { otherElement = value; foundOther = true; } } } //slot in pivot elementU[startColumn] = thisPivotValue; #ifdef SMALL_PERMUTE indexRowU[startColumn] = realPivotRow; #else indexRowU[startColumn] = pivotRow; #endif //clean up counts startColumn++; numberInColumn[iColumn] = put - startColumn; numberInColumnPlus[iColumn]++; startColumnU[iColumn]++; otherElement = otherElement - thisPivotValue * otherMultiplier; CoinFactorizationDouble absValue = fabs ( otherElement ); if ( !TEST_LESS_THAN_TOLERANCE_REGISTER(absValue) ) { if ( !foundOther ) { //have we space saveColumn[numberAdded++] = iColumn; CoinSimplexInt next = nextColumn[iColumn]; CoinBigIndex space; space = startColumnU[next] - put - numberInColumnPlus[next]; if ( space <= 0 ) { //getColumnSpace also moves fixed part CoinSimplexInt number = numberInColumn[iColumn]; if ( !getColumnSpace ( iColumn, number + 1 ) ) { return false; } //redo starts positionLargest = positionLargest + startColumnU[iColumn] - startColumn; startColumn = startColumnU[iColumn]; put = startColumn + number; } } elementU[put] = otherElement; indexRowU[put] = otherRow; #if BOTH_WAYS #endif if ( absValue > largest ) { largest = absValue; positionLargest = put; } put++; } else { if ( foundOther ) { numberDeleted++; //take out of row list CoinBigIndex where = start; while ( indexColumnU[where] != iColumn ) { where++; } /* endwhile */ assert ( where < end ); #if BOTH_WAYS #endif end--; indexColumnU[where] = indexColumnU[end]; } } CoinSimplexInt numberInColumnOut = put - startColumn; numberInColumn[iColumn] = numberInColumnOut; //move largest if ( positionLargest >= 0 ) { value = elementU[positionLargest]; iRow = indexRowU[positionLargest]; elementU[positionLargest] = elementU[startColumn]; indexRowU[positionLargest] = indexRowU[startColumn]; elementU[startColumn] = value; indexRowU[startColumn] = iRow; #if BOTH_WAYS #endif } //linked list for column if ( numberInColumnIn!=numberInColumnOut&&nextCount[iColumn + numberRows_] != -2 ) { //modify linked list modifyLink ( iColumn + numberRows_, numberInColumnOut ); } } } //get space for row list next = nextRow[otherRow]; CoinBigIndex space; space = startRowU[next] - end; totalElements_ += numberAdded - numberDeleted; CoinSimplexInt number = numberAdded + ( end - start ); if ( space < numberAdded ) { numberInRow[otherRow] = end - start; if ( !getRowSpace ( otherRow, number ) ) { return false; } end = startRowU[otherRow] + end - start; } // do linked lists and update counts numberInRow[otherRow] = number; if ( number != numberSave ) { modifyLink ( otherRow, number ); } for ( j = 0; j < numberAdded; j++ ) { #if BOTH_WAYS #endif indexColumnU[end++] = saveColumn[j]; } lastEntryByRowU_ = CoinMax(end,lastEntryByRowU_); assert (lastEntryByRowU_<=lengthAreaU_); //modify linked list for pivots deleteLink ( pivotRow ); deleteLink ( pivotColumn + numberRows_ ); return true; } // Delete all stuff void CoinAbcTypeFactorization::almostDestructor() { gutsOfDestructor(1); } // PreProcesses column ordered copy of basis void CoinAbcTypeFactorization::preProcess ( ) { CoinBigIndex numberElements = startColumnUAddress_[numberRows_-1] + numberInColumnAddress_[numberRows_-1]; setNumberElementsU(numberElements); } // Return largest double CoinAbcTypeFactorization::preProcess3 ( ) { CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; totalElements_ = lengthU_; //links and initialize pivots CoinZeroN ( numberInColumn+numberRows_, maximumRowsExtra_ + 1 - numberRows_); CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; CoinFillN ( pivotColumnAddress_, numberRows_, -1 ); CoinZeroN ( numberInColumnPlus, maximumRowsExtra_ + 1 ); CoinZeroN ( lastRow, numberRows_ ); startColumn[maximumRowsExtra_] = lengthU_; lastEntryByColumnU_=lengthU_; lastEntryByRowU_=lengthU_; //do slacks first //CoinBigIndex * startColumnU = startColumnUAddress_; CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; //CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinSimplexInt * COIN_RESTRICT pivotColumn = pivotColumnAddress_; //CoinFillN(pivotRegion,numberSlacks_,static_cast(SLACK_VALUE)); // **************** TEMP ********************* CoinFillN(pivotRegion,numberSlacks_,static_cast(1.0)); CoinZeroN(startColumnL,numberSlacks_+1); CoinZeroN(numberInColumn,numberSlacks_); CoinZeroN(numberInColumnPlus,numberSlacks_); #ifdef ABC_USE_FUNCTION_POINTERS // Use row copy elementUColumnPlusAddress_ = elementRowU_.array(); scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; #endif lastEntryByColumnUPlus_=1; //for (int i=0;i1 CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #ifdef SMALL_PERMUTE CoinSimplexInt * COIN_RESTRICT fromBigToSmallRow=reinterpret_cast(saveColumn_.array()); CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; //move largest in column to beginning // If we always compress then can combine CoinSimplexInt * COIN_RESTRICT tempIndex = firstCountAddress_; //saveColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT workArea = workAreaAddress_; // Compress int nSmall=0; // fromBig is only used at setup time for (int i=0;i=0) { // out fromBigToSmallRow[i]=-1; } else { // in fromBigToSmallRow[i]=nSmall; numberInRow[nSmall]=numberInRow[i]; lastRow[nSmall]=lastRow[i]; fromSmallToBigRow_[nSmall++]=i; } } nSmall=0; for (CoinSimplexInt iColumn = numberSlacks_; iColumn < numberRows_; iColumn++ ) { CoinSimplexInt number = numberInColumn[iColumn]; // use workArea and tempIndex for remaining elements CoinBigIndex first = startColumn[iColumn]; int saveFirst=first; fromSmallToBigColumn_[nSmall]=iColumn; CoinBigIndex largest = -1; CoinFactorizationDouble valueLargest = -1.0; CoinSimplexInt nOther=0; CoinBigIndex end = first+number; for (CoinBigIndex k = first ; k < end; k++ ) { CoinSimplexInt iRow = indexRow[k]; assert (iRow valueLargest ) { valueLargest = valueAbs; largest = nOther; } iRow=fromBigToSmallRow[iRow]; assert (iRow>=0); tempIndex[nOther]=iRow; workArea[nOther++]=value; } else { indexRow[first] = iRow; element[first++] = value; } } CoinSimplexInt nMoved = first-saveFirst; numberInColumnPlus[nSmall]=nMoved; totalElements_ -= nMoved; startColumn[nSmall]=first; //largest if (largest>=0) { indexRow[first] = tempIndex[largest]; element[first++] = workArea[largest]; } for (CoinBigIndex k=0;k valueLargest ) { valueLargest = valueAbs; largest = nOther; } tempIndex[nOther]=iRow; workArea[nOther++]=value; #if CONVERTROW<2 CoinSimplexInt iLook = startRow[iRow]; startRow[iRow] = iLook + 1; indexColumn[iLook] = iColumn; #endif #if BOTH_WAYS #endif } else { indexRow[first] = iRow; #if BOTH_WAYS #endif element[first++] = value; } } overallLargest=CoinMax(overallLargest,valueLargest); CoinSimplexInt nMoved = first-startColumn[iColumn]; numberInColumnPlus[iColumn]=nMoved; totalElements_ -= nMoved; startColumn[iColumn]=first; //largest if (largest>=0) { #if CONVERTROW>1 int iRow=tempIndex[largest]; indexRow[first] = iRow; CoinSimplexInt iLook = startRow[iRow]; startRow[iRow] = iLook + 1; indexColumn[iLook] = iColumn; convertRowToColumn[iLook]=first; convertColumnToRow[first]=iLook; #else indexRow[first] = tempIndex[largest]; #endif #if BOTH_WAYS #endif element[first++] = workArea[largest]; } for (CoinBigIndex k=0;k1 int iRow=tempIndex[k]; indexRow[first] = iRow; CoinSimplexInt iLook = startRow[iRow]; startRow[iRow] = iLook + 1; indexColumn[iLook] = iColumn; convertRowToColumn[iLook]=first; convertColumnToRow[first]=iLook; #else indexRow[first] = tempIndex[k]; #endif #if BOTH_WAYS #endif element[first++] = workArea[k]; } } numberInColumn[iColumn]=first-startColumn[iColumn]; } #else #if CONVERTROW>1 for (CoinSimplexInt iColumn = 0; iColumn < numberRowsSmall_; iColumn++ ) { CoinSimplexInt number = numberInColumn[iColumn]; CoinBigIndex first = startColumn[iColumn]; CoinBigIndex end = first+number; for (CoinBigIndex k = first ; k < end; k++ ) { CoinSimplexInt iRow = indexRow[k]; CoinSimplexInt iLook = startRow[iRow]; startRow[iRow] = iLook + 1; indexColumn[iLook] = iColumn; convertRowToColumn[iLook]=k; convertColumnToRow[k]=iLook; } } #endif #endif for (CoinSimplexInt iRow=numberRowsSmall_-1;iRow>0;iRow--) startRow[iRow]=startRow[iRow-1]; startRow[0]=0; // Do links (do backwards to get rows first?) CoinSimplexInt * firstCount=tempIndex; for (int i=0;ipivotLOrderAddress_; CoinSimplexInt * COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_; CoinSimplexInt * COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_; CoinSimplexInt iThis=-1; for (int i=0;i=0;i--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt iNext=pivotLOrder[i]; #else CoinSimplexInt iNext=i; #endif pivotLinkedBackwards[iThis]=iNext; iThis=iNext; } pivotLinkedBackwards[iThis]=-1; pivotLinkedBackwards[-1]=-2; #if 0 //ndef NDEBUG { char * test = new char[numberRows_]; memset(test,0,numberRows_); CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; //CoinSimplexInt * COIN_RESTRICT pivotLOrder = firstCountAddress_; //const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; for (int i=0;i=0&&iRow(area+number); for (int j = 0; j < number; j++ ) { CoinSimplexInt iRow = indices[j]; assert (iRow>=0&&iRow2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinZeroN ( numberInRow, numberRows_+1 ); for (CoinSimplexInt i = 0; i < numberRows_; i++ ) { CoinBigIndex start = startColumnU[i]; CoinBigIndex end = start + numberInColumn[i]; CoinFactorizationDouble pivotValue = pivotRegion[i]; CoinBigIndex j; for ( j = start; j < end; j++ ) { CoinSimplexInt iRow = indexRowU[j]; CoinSimplexInt iLook = numberInRow[iRow]; numberInRow[iRow] = iLook + 1; CoinBigIndex k = startRow[iRow] + iLook; indexColumnU[k] = i; #if CONVERTROW convertRowToColumn[k] = j-start; #if CONVERTROW>2 convertColumnToRow[j] = k; #endif #endif //multiply by pivot elementU[j] *= pivotValue; elementRow[k] = elementU[j]; } } #else for (CoinSimplexInt i = 0; i < numberRows_; i++ ) { scatterStruct & COIN_RESTRICT scatter = scatterPointer[i]; CoinSimplexInt number = scatter.number; const CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter.offset; const CoinBigIndex * COIN_RESTRICT indices = reinterpret_cast(area+number); for (int j = 0; j < number; j++ ) { CoinSimplexInt iRow = indices[j]; CoinBigIndex k = startRow[iRow]; startRow[iRow]=k+1; indexColumnU[k] = i; #if CONVERTROW convertRowToColumn[k] = j; #if CONVERTROW>2 convertColumnToRow[j+startColumnU[i]] = k; abort(); // fix #endif #endif //CoinFactorizationDouble pivotValue = pivotRegion[i]; //multiply by pivot //elementU[j+startColumnU[i]] *= pivotValue; elementRow[k] = area[j]; } } #endif //CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; //CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; for (int j = numberRows_-1; j >=0; j-- ) { lastRow[j] = j - 1; nextRow[j] = j + 1; #ifdef ABC_USE_FUNCTION_POINTERS startRow[j+1]=startRow[j]; #endif } startRow[0]=0; nextRow[numberRows_ - 1] = numberRows_; lastRow[numberRows_] = numberRows_ - 1; nextRow[numberRows_] = 0; lastRow[0] = numberRows_; //memcpy(firstCountAddress_+numberRows_+1,pivotLinkedBackwards-1,(numberRows_+2)*sizeof(int)); } else { #endif #ifndef ABC_USE_FUNCTION_POINTERS for (CoinSimplexInt i = 0; i < numberRows_; i++ ) { CoinBigIndex start = startColumnU[i]; CoinBigIndex end = start + numberInColumn[i]; CoinFactorizationDouble pivotValue = pivotRegion[i]; CoinBigIndex j; for ( j = start; j < end; j++ ) { //multiply by pivot elementU[j] *= pivotValue; } } #endif #if ABC_SMALL<2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; assert (number==numberInColumn[iRow]); if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); for (int i=0;i=0); workArea[iOriginal]=i; } CoinSimplexInt iRow=0; for (CoinSimplexInt i=0;i=0) iRow++; assert (iRow=0&&indexRowUAddress_[j]-1.0e50&&elementUAddress_[j]<1.0e50); std::cout << indexRowUAddress_[j] << " " << elementUAddress_[j] << std::endl; } } for ( i = 0; i < numberRows_; i++ ) { std::cout << "l " << i << " " << startColumnLAddress_[i + 1] - startColumnLAddress_[i] << std::endl; CoinSort_2(indexRowLAddress_+startColumnLAddress_[i], indexRowLAddress_+startColumnLAddress_[i+1], elementLAddress_+startColumnLAddress_[i]); CoinSimplexInt j; for ( j = startColumnLAddress_[i]; j < startColumnLAddress_[i + 1]; j++ ) { std::cout << indexRowLAddress_[j] << " " << elementLAddress_[j] << std::endl; } } } // sort so can compare void CoinAbcTypeFactorization::sort ( ) const { CoinSimplexInt i; for ( i = 0; i < numberRows_; i++ ) { CoinSort_2(indexRowUAddress_+startColumnUAddress_[i], indexRowUAddress_+startColumnUAddress_[i]+numberInColumnAddress_[i], elementUAddress_+startColumnUAddress_[i]); } for ( i = 0; i < numberRows_; i++ ) { CoinSort_2(indexRowLAddress_+startColumnLAddress_[i], indexRowLAddress_+startColumnLAddress_[i+1], elementLAddress_+startColumnLAddress_[i]); } } #ifdef CHECK_LINKS //static int ixxxxxx=0; void CoinAbcTypeFactorization::checkLinks(int type) { //if (type<1) return; #if 0 //ABC_SMALL<2 if (numberRowsSmall_!=5698) return; ixxxxxx++; if (fromSmallToBigRow_[3195]==3581) { if (permuteAddress_[3581]>=0) { assert (numberInRowAddress_[3195]==0); CoinSimplexInt * numberInColumn = numberInColumnAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; for (int i=startColumn[1523];i=7615900) { printf("trouble ahead\n"); } return; if (ixxxxxx<406245) return; #endif CoinSimplexInt * COIN_RESTRICT nextCount = this->nextCount(); CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCount(); CoinSimplexInt * COIN_RESTRICT lastCount = this->lastCount(); CoinSimplexInt * numberInColumn = numberInColumnAddress_; CoinSimplexInt * numberInRow = numberInRowAddress_; if (type) { int nBad=0; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; for (int i=0;i=0&&iRow=lastStart); lastStart=iStart; list1[iRow]=1; iRow=nextRow[iRow]; } for (int i=0;i=0&&iColumn=lastStart); lastStart=iStart; list1[iColumn]=1; iColumn=nextColumn[iColumn]; } int nEnd=0; for (int i=0;i1) { for (int i=0;i=0) { #if VERBOSE count++; if (iCount<=VERBOSE) { if (next=0) assert (next2==lastCount[next]); } #if VERBOSE if (count) printf("%d items have count %d\n",count,iCount); #endif } delete [] mark; } #endif #endif Clp-1.15.10/src/AbcNonLinearCost.cpp0000644000076600007660000007754012101105055015475 0ustar coincoin/* $Id: AbcNonLinearCost.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include #include #include "CoinIndexedVector.hpp" #include "AbcSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "AbcNonLinearCost.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcNonLinearCost::AbcNonLinearCost () : changeCost_(0.0), feasibleCost_(0.0), infeasibilityWeight_(-1.0), largestInfeasibility_(0.0), sumInfeasibilities_(0.0), averageTheta_(0.0), numberRows_(0), numberColumns_(0), model_(NULL), numberInfeasibilities_(-1), status_(NULL), bound_(NULL), cost_(NULL) { } //#define VALIDATE #ifdef VALIDATE static double * saveLowerV = NULL; static double * saveUpperV = NULL; #ifdef NDEBUG Validate should not be set if no debug #endif #endif /* Constructor from simplex. This will just set up wasteful arrays for linear, but later may do dual analysis and even finding duplicate columns */ AbcNonLinearCost::AbcNonLinearCost ( AbcSimplex * model) { model_ = model; numberRows_ = model_->numberRows(); numberColumns_ = model_->numberColumns(); // If gub then we need this extra int numberTotal = numberRows_ + numberColumns_; numberInfeasibilities_ = 0; changeCost_ = 0.0; feasibleCost_ = 0.0; infeasibilityWeight_ = -1.0; double * cost = model_->costRegion(); // check if all 0 int iSequence; bool allZero = true; for (iSequence = 0; iSequence < numberTotal; iSequence++) { if (cost[iSequence]) { allZero = false; break; } } if (allZero) model_->setInfeasibilityCost(1.0); sumInfeasibilities_ = 0.0; averageTheta_ = 0.0; largestInfeasibility_ = 0.0; bound_ = new double[numberTotal]; cost_ = new double[numberTotal]; status_ = new unsigned char[numberTotal]; for (iSequence = 0; iSequence < numberTotal; iSequence++) { bound_[iSequence] = 0.0; cost_[iSequence] = cost[iSequence]; setInitialStatus(status_[iSequence]); } } // Refresh - assuming regions OK void AbcNonLinearCost::refresh() { int numberTotal = numberRows_ + numberColumns_; numberInfeasibilities_ = 0; sumInfeasibilities_ = 0.0; largestInfeasibility_ = 0.0; double infeasibilityCost = model_->infeasibilityCost(); double primalTolerance = model_->currentPrimalTolerance(); double * cost = model_->costRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * solution = model_->solutionRegion(); for (int iSequence = 0; iSequence < numberTotal; iSequence++) { cost_[iSequence] = cost[iSequence]; double value = solution[iSequence]; double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible status_[iSequence] = static_cast(CLP_FEASIBLE | (CLP_SAME << 4)); bound_[iSequence] = 0.0; } else { // below double infeasibility = lowerValue - value - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); cost[iSequence] -= infeasibilityCost; numberInfeasibilities_++; status_[iSequence] = static_cast(CLP_BELOW_LOWER | (CLP_SAME << 4)); bound_[iSequence] = upperValue; upper[iSequence] = lowerValue; lower[iSequence] = -COIN_DBL_MAX; } } else { // above double infeasibility = value - upperValue - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); cost[iSequence] += infeasibilityCost; numberInfeasibilities_++; status_[iSequence] = static_cast(CLP_ABOVE_UPPER | (CLP_SAME << 4)); bound_[iSequence] = lowerValue; lower[iSequence] = upperValue; upper[iSequence] = COIN_DBL_MAX; } } // checkInfeasibilities(model_->primalTolerance()); } // Refresh - from original void AbcNonLinearCost::refreshFromPerturbed(double tolerance) { // original costs and perturbed bounds model_->copyFromSaved(32+2); refresh(); //checkInfeasibilities(tolerance); } // Refreshes costs always makes row costs zero void AbcNonLinearCost::refreshCosts(const double * columnCosts) { double * cost = model_->costRegion(); // zero row costs memset(cost + numberColumns_, 0, numberRows_ * sizeof(double)); // copy column costs CoinMemcpyN(columnCosts, numberColumns_, cost); for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { cost_[iSequence] = cost[iSequence]; } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcNonLinearCost::AbcNonLinearCost (const AbcNonLinearCost & rhs) : changeCost_(0.0), feasibleCost_(0.0), infeasibilityWeight_(-1.0), largestInfeasibility_(0.0), sumInfeasibilities_(0.0), averageTheta_(0.0), numberRows_(rhs.numberRows_), numberColumns_(rhs.numberColumns_), model_(NULL), numberInfeasibilities_(-1), status_(NULL), bound_(NULL), cost_(NULL) { if (numberRows_) { int numberTotal = numberRows_ + numberColumns_; model_ = rhs.model_; numberInfeasibilities_ = rhs.numberInfeasibilities_; changeCost_ = rhs.changeCost_; feasibleCost_ = rhs.feasibleCost_; infeasibilityWeight_ = rhs.infeasibilityWeight_; largestInfeasibility_ = rhs.largestInfeasibility_; sumInfeasibilities_ = rhs.sumInfeasibilities_; averageTheta_ = rhs.averageTheta_; bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); cost_ = CoinCopyOfArray(rhs.cost_, numberTotal); status_ = CoinCopyOfArray(rhs.status_, numberTotal); } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcNonLinearCost::~AbcNonLinearCost () { delete [] status_; delete [] bound_; delete [] cost_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcNonLinearCost & AbcNonLinearCost::operator=(const AbcNonLinearCost& rhs) { if (this != &rhs) { numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; delete [] status_; delete [] bound_; delete [] cost_; status_ = NULL; bound_ = NULL; cost_ = NULL; if (numberRows_) { int numberTotal = numberRows_ + numberColumns_; bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); cost_ = CoinCopyOfArray(rhs.cost_, numberTotal); status_ = CoinCopyOfArray(rhs.status_, numberTotal); } model_ = rhs.model_; numberInfeasibilities_ = rhs.numberInfeasibilities_; changeCost_ = rhs.changeCost_; feasibleCost_ = rhs.feasibleCost_; infeasibilityWeight_ = rhs.infeasibilityWeight_; largestInfeasibility_ = rhs.largestInfeasibility_; sumInfeasibilities_ = rhs.sumInfeasibilities_; averageTheta_ = rhs.averageTheta_; } return *this; } // Changes infeasible costs and computes number and cost of infeas // We will need to re-think objective offsets later // We will also need a 2 bit per variable array for some // purpose which will come to me later void AbcNonLinearCost::checkInfeasibilities(double oldTolerance) { numberInfeasibilities_ = 0; double infeasibilityCost = model_->infeasibilityCost(); changeCost_ = 0.0; largestInfeasibility_ = 0.0; sumInfeasibilities_ = 0.0; double primalTolerance = model_->currentPrimalTolerance(); int iSequence; double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); bool toNearest = oldTolerance <= 0.0; feasibleCost_ = 0.0; //bool checkCosts = (infeasibilityWeight_ != infeasibilityCost); infeasibilityWeight_ = infeasibilityCost; int numberTotal = numberColumns_ + numberRows_; // nonbasic should be at a valid bound for (iSequence = 0; iSequence < numberTotal; iSequence++) { double value = solution[iSequence]; unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost_[iSequence]; double trueCost = costValue; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; costValue -= infeasibilityCost; } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; costValue += infeasibilityCost; } // get correct place int newWhere = CLP_FEASIBLE; AbcSimplex::Status status = model_->getInternalStatus(iSequence); if (upperValue == lowerValue && status != AbcSimplex::isFixed) { if (status != AbcSimplex::basic) { model_->setInternalStatus(iSequence, AbcSimplex::isFixed); status = AbcSimplex::isFixed; } } switch(status) { case AbcSimplex::basic: case AbcSimplex::superBasic: if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; assert (fabs(lowerValue) < 1.0e100); double infeasibility = lowerValue - value - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); costValue = trueCost - infeasibilityCost; changeCost_ -= lowerValue * (costValue - cost[iSequence]); numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; double infeasibility = value - upperValue - primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); costValue = trueCost + infeasibilityCost; changeCost_ -= upperValue * (costValue - cost[iSequence]); numberInfeasibilities_++; } break; case AbcSimplex::isFree: break; case AbcSimplex::atUpperBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value - upperValue) > oldTolerance * 1.0001) { if (fabs(value - lowerValue) <= oldTolerance * 1.0001) { if (fabs(value - lowerValue) > primalTolerance) { solution[iSequence] = lowerValue; value = lowerValue; } model_->setInternalStatus(iSequence, AbcSimplex::atLowerBound); } else { if (value < upperValue) { if (value > lowerValue) { model_->setInternalStatus(iSequence, AbcSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence] = lowerValue; value = lowerValue; model_->setInternalStatus(iSequence, AbcSimplex::atLowerBound); } } else { // set to upper bound as infeasible solution[iSequence] = upperValue; value = upperValue; } } } else if (fabs(value - upperValue) > primalTolerance) { solution[iSequence] = upperValue; value = upperValue; } } else { // Set to nearest and make at bound if (fabs(value - lowerValue) < fabs(value - upperValue)) { solution[iSequence] = lowerValue; value = lowerValue; model_->setInternalStatus(iSequence, AbcSimplex::atLowerBound); } else { solution[iSequence] = upperValue; value = upperValue; } } break; case AbcSimplex::atLowerBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value - lowerValue) > oldTolerance * 1.0001) { if (fabs(value - upperValue) <= oldTolerance * 1.0001) { if (fabs(value - upperValue) > primalTolerance) { solution[iSequence] = upperValue; value = upperValue; } model_->setInternalStatus(iSequence, AbcSimplex::atUpperBound); } else { if (value < upperValue) { if (value > lowerValue) { model_->setInternalStatus(iSequence, AbcSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence] = lowerValue; value = lowerValue; } } else { // set to upper bound as infeasible solution[iSequence] = upperValue; value = upperValue; model_->setInternalStatus(iSequence, AbcSimplex::atUpperBound); } } } else if (fabs(value - lowerValue) > primalTolerance) { solution[iSequence] = lowerValue; value = lowerValue; } } else { // Set to nearest and make at bound if (fabs(value - lowerValue) < fabs(value - upperValue)) { solution[iSequence] = lowerValue; value = lowerValue; } else { solution[iSequence] = upperValue; value = upperValue; model_->setInternalStatus(iSequence, AbcSimplex::atUpperBound); } } break; case AbcSimplex::isFixed: solution[iSequence] = lowerValue; value = lowerValue; break; } if (iWhere != newWhere) { setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; costValue = trueCost - infeasibilityCost; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; costValue = trueCost + infeasibilityCost; } else { costValue = trueCost; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } // always do as other things may change cost[iSequence] = costValue; feasibleCost_ += trueCost * value; } model_->moveToBasic(14); // all except solution } // Puts feasible bounds into lower and upper void AbcNonLinearCost::feasibleBounds() { int iSequence; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); int numberTotal = numberColumns_ + numberRows_; for (iSequence = 0; iSequence < numberTotal; iSequence++) { unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; } setOriginalStatus(status_[iSequence], CLP_FEASIBLE); lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } void AbcNonLinearCost::goBackAll(const CoinIndexedVector * update) { assert (model_ != NULL); const int * pivotVariable = model_->pivotVariable(); int number = update->getNumElements(); const int * index = update->getIndices(); for (int i = 0; i < number; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; setSameStatus(status_[iSequence]); } } void AbcNonLinearCost::checkInfeasibilities(int numberInArray, const int * index) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); double * solutionBasic = model_->solutionBasic(); double * upperBasic = model_->upperBasic(); double * lowerBasic = model_->lowerBasic(); double * costBasic = model_->costBasic(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double value = solutionBasic[iRow]; unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lowerBasic[iRow]; double upperValue = upperBasic[iRow]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; assert (fabs(lowerValue) < 1.0e100); costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; lowerBasic[iRow] = lowerValue; upperBasic[iRow] = upperValue; costBasic[iRow] = costValue; } } } /* Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. On input array is empty (but indices exist). On exit just changed costs will be stored as normal CoinIndexedVector */ void AbcNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); int number = 0; int * index = update->getIndices(); double * work = update->denseVector(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); double * solutionBasic = model_->solutionBasic(); double * upperBasic = model_->upperBasic(); double * lowerBasic = model_->lowerBasic(); double * costBasic = model_->costBasic(); for (int i = 0; i < numberInArray; i++) { int iRow = index[i]; int iSequence = pivotVariable[iRow]; double value = solutionBasic[iRow]; unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lowerBasic[iRow]; double upperValue = upperBasic[iRow]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { work[iRow] = cost[iSequence] - costValue; index[number++] = iRow; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; lowerBasic[iRow] = lowerValue; upperBasic[iRow] = upperValue; costBasic[iRow] = costValue; } } update->setNumElements(number); } /* Sets bounds and cost for one variable - returns change in cost*/ double AbcNonLinearCost::setOne(int iSequence, double value) { assert (model_ != NULL); double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference = 0.0; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { difference = cost[iSequence] - costValue; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } AbcSimplex::Status status = model_->getInternalStatus(iSequence); if (upperValue == lowerValue) { model_->setInternalStatus(iSequence, AbcSimplex::isFixed); } switch(status) { case AbcSimplex::basic: case AbcSimplex::superBasic: case AbcSimplex::isFree: break; case AbcSimplex::atUpperBound: case AbcSimplex::atLowerBound: case AbcSimplex::isFixed: // set correctly if (fabs(value - lowerValue) <= primalTolerance * 1.001) { model_->setInternalStatus(iSequence, AbcSimplex::atLowerBound); } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { model_->setInternalStatus(iSequence, AbcSimplex::atUpperBound); } else { // set superBasic model_->setInternalStatus(iSequence, AbcSimplex::superBasic); } break; } changeCost_ += value * difference; return difference; } /* Sets bounds and cost for one variable - returns change in cost*/ double AbcNonLinearCost::setOneBasic(int iRow, double value) { assert (model_ != NULL); int iSequence=model_->pivotVariable()[iRow]; double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference = 0.0; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); double * upperBasic = model_->upperBasic(); double * lowerBasic = model_->lowerBasic(); double * costBasic = model_->costBasic(); unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lowerBasic[iRow]; double upperValue = upperBasic[iRow]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { difference = cost[iSequence] - costValue; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upperValue = lowerValue; lowerValue = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lowerValue = upperValue; upperValue = COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; lowerBasic[iRow] = lowerValue; upperBasic[iRow] = upperValue; costBasic[iRow] = costValue; } changeCost_ += value * difference; return difference; } /* Sets bounds and cost for outgoing variable may change value Returns direction */ int AbcNonLinearCost::setOneOutgoing(int iRow, double & value) { assert (model_ != NULL); int iSequence=model_->pivotVariable()[iRow]; double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference = 0.0; int direction = 0; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); double * upperBasic = model_->upperBasic(); double * lowerBasic = model_->lowerBasic(); unsigned char iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lowerBasic[iRow]; double upperValue = upperBasic[iRow]; double costValue = cost_[iSequence]; // Set perceived direction out if (value <= lowerValue + 1.001 * primalTolerance) { direction = 1; } else if (value >= upperValue - 1.001 * primalTolerance) { direction = -1; } else { // odd direction = 0; } int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; numberInfeasibilities_--; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; numberInfeasibilities_--; } // get correct place // If fixed give benefit of doubt if (lowerValue == upperValue) value = lowerValue; int newWhere = CLP_FEASIBLE; if (value - upperValue <= primalTolerance) { if (value - lowerValue >= -primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere = CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; assert (fabs(lowerValue) < 1.0e100); } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere != newWhere) { difference = cost[iSequence] - costValue; setOriginalStatus(status_[iSequence], newWhere); if (newWhere == CLP_BELOW_LOWER) { bound_[iSequence] = upperValue; upper[iSequence] = lowerValue; lower[iSequence] = -COIN_DBL_MAX; } else if (newWhere == CLP_ABOVE_UPPER) { bound_[iSequence] = lowerValue; lower[iSequence] = upperValue; upper[iSequence] = COIN_DBL_MAX; } else { lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } cost[iSequence] = costValue; } // set correctly if (fabs(value - lowerValue) <= primalTolerance * 1.001) { value = CoinMin(value, lowerValue + primalTolerance); } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { value = CoinMax(value, upperValue - primalTolerance); } else { //printf("*** variable wandered off bound %g %g %g!\n", // lowerValue,value,upperValue); if (value - lowerValue <= upperValue - value) value = lowerValue + primalTolerance; else value = upperValue - primalTolerance; } changeCost_ += value * difference; return direction; } // Returns nearest bound double AbcNonLinearCost::nearest(int iRow, double solutionValue) { assert (model_ != NULL); int iSequence=model_->pivotVariable()[iRow]; double nearest = 0.0; const double * upperBasic = model_->upperBasic(); const double * lowerBasic = model_->lowerBasic(); double lowerValue = lowerBasic[iRow]; double upperValue = upperBasic[iRow]; int iWhere = originalStatus(status_[iSequence]); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; } if (fabs(solutionValue - lowerValue) < fabs(solutionValue - upperValue)) nearest = lowerValue; else nearest = upperValue; return nearest; } /// Feasible cost with offset and direction (i.e. for reporting) double AbcNonLinearCost::feasibleReportCost() const { double value; model_->getDblParam(ClpObjOffset, value); return (feasibleCost_ + model_->objectiveAsObject()->nonlinearOffset()) * model_->optimizationDirection() / (model_->objectiveScale() * model_->rhsScale()) - value; } // Get rid of real costs (just for moment) void AbcNonLinearCost::zapCosts() { } #ifdef VALIDATE // For debug void AbcNonLinearCost::validate() { double primalTolerance = model_->currentPrimalTolerance(); int iSequence; const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); const double * cost = model_->costRegion(); double infeasibilityCost = model_->infeasibilityCost(); int numberTotal = numberRows_ + numberColumns_; int numberInfeasibilities = 0; double sumInfeasibilities = 0.0; for (iSequence = 0; iSequence < numberTotal; iSequence++) { double value = solution[iSequence]; int iStatus = status_[iSequence]; assert (currentStatus(iStatus) == CLP_SAME); double lowerValue = lower[iSequence]; double upperValue = upper[iSequence]; double costValue = cost_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere == CLP_BELOW_LOWER) { lowerValue = upperValue; upperValue = bound_[iSequence]; assert (fabs(lowerValue) < 1.0e100); costValue -= infeasibilityCost; assert (value <= lowerValue - primalTolerance); numberInfeasibilities++; sumInfeasibilities += lowerValue - value - primalTolerance; assert (model_->getInternalStatus(iSequence) == AbcSimplex::basic); } else if (iWhere == CLP_ABOVE_UPPER) { upperValue = lowerValue; lowerValue = bound_[iSequence]; costValue += infeasibilityCost; assert (value >= upperValue + primalTolerance); numberInfeasibilities++; sumInfeasibilities += value - upperValue - primalTolerance; assert (model_->getInternalStatus(iSequence) == AbcSimplex::basic); } else { assert (value >= lowerValue - primalTolerance && value <= upperValue + primalTolerance); } assert (lowerValue == saveLowerV[iSequence]); assert (upperValue == saveUpperV[iSequence]); assert (costValue == cost[iSequence]); } if (numberInfeasibilities) printf("JJ %d infeasibilities summing to %g\n", numberInfeasibilities, sumInfeasibilities); } #endif Clp-1.15.10/src/ClpSimplex.cpp0000644000076600007660000176631412240211604014440 0ustar coincoin/* $Id: ClpSimplex.cpp 1989 2013-11-11 17:27:32Z 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). //#undef NDEBUG #include "ClpConfig.h" #include "CoinPragma.hpp" #include #if SLIM_CLP==2 #define SLIM_NOIO #endif #include "CoinHelperFunctions.hpp" #include "CoinFloatEqual.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpDualRowSteepest.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpNonLinearCost.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include "ClpLinearObjective.hpp" #include "ClpHelperFunctions.hpp" #include "CoinModel.hpp" #include "CoinLpIO.hpp" #include #if CLP_HAS_ABC #include "CoinAbcCommon.hpp" #endif #include #include #include //############################################################################# ClpSimplex::ClpSimplex (bool emptyMessages) : ClpModel(emptyMessages), bestPossibleImprovement_(0.0), zeroTolerance_(1.0e-13), columnPrimalSequence_(-2), rowPrimalSequence_(-2), bestObjectiveValue_(-COIN_DBL_MAX), moreSpecialOptions_(2), baseIteration_(0), primalToleranceToGetOptimal_(-1.0), largeValue_(1.0e15), largestPrimalError_(0.0), largestDualError_(0.0), alphaAccuracy_(-1.0), dualBound_(1.0e10), alpha_(0.0), theta_(0.0), lowerIn_(0.0), valueIn_(0.0), upperIn_(-COIN_DBL_MAX), dualIn_(0.0), lowerOut_(-1), valueOut_(-1), upperOut_(-1), dualOut_(-1), dualTolerance_(1.0e-7), primalTolerance_(1.0e-7), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), infeasibilityCost_(1.0e10), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), acceptablePivot_(1.0e-8), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rowObjectiveWork_(NULL), objectiveWork_(NULL), sequenceIn_(-1), directionIn_(-1), sequenceOut_(-1), directionOut_(-1), pivotRow_(-1), lastGoodIteration_(-100), dj_(NULL), rowReducedCost_(NULL), reducedCostWork_(NULL), solution_(NULL), rowActivityWork_(NULL), columnActivityWork_(NULL), numberDualInfeasibilities_(0), numberDualInfeasibilitiesWithoutFree_(0), numberPrimalInfeasibilities_(100), numberRefinements_(0), pivotVariable_(NULL), factorization_(NULL), savedSolution_(NULL), numberTimesOptimal_(0), disasterArea_(NULL), changeMade_(1), algorithm_(0), forceFactorization_(-1), perturbation_(100), nonLinearCost_(NULL), lastBadIteration_(-999999), lastFlaggedIteration_(-999999), numberFake_(0), numberChanged_(0), progressFlag_(0), firstFree_(-1), numberExtraRows_(0), maximumBasic_(0), dontFactorizePivots_(0), incomingInfeasibility_(1.0), allowedInfeasibility_(10.0), automaticScale_(0), maximumPerturbationSize_(0), perturbationArray_(NULL), baseModel_(NULL) #ifdef ABC_INHERIT ,abcSimplex_(NULL), abcState_(0) #endif { int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } for (i = 0; i < 4; i++) { spareIntArray_[i] = 0; spareDoubleArray_[i] = 0.0; } saveStatus_ = NULL; // get an empty factorization so we can set tolerances etc getEmptyFactorization(); // Say sparse factorization_->sparseThreshold(1); // say Steepest pricing dualRowPivot_ = new ClpDualRowSteepest(); // say Steepest pricing primalColumnPivot_ = new ClpPrimalColumnSteepest(); solveType_ = 1; // say simplex based life form } // Subproblem constructor ClpSimplex::ClpSimplex ( const ClpModel * rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn, bool dropNames, bool dropIntegers, bool fixOthers) : ClpModel(rhs, numberRows, whichRow, numberColumns, whichColumn, dropNames, dropIntegers), bestPossibleImprovement_(0.0), zeroTolerance_(1.0e-13), columnPrimalSequence_(-2), rowPrimalSequence_(-2), bestObjectiveValue_(-COIN_DBL_MAX), moreSpecialOptions_(2), baseIteration_(0), primalToleranceToGetOptimal_(-1.0), largeValue_(1.0e15), largestPrimalError_(0.0), largestDualError_(0.0), alphaAccuracy_(-1.0), dualBound_(1.0e10), alpha_(0.0), theta_(0.0), lowerIn_(0.0), valueIn_(0.0), upperIn_(-COIN_DBL_MAX), dualIn_(0.0), lowerOut_(-1), valueOut_(-1), upperOut_(-1), dualOut_(-1), dualTolerance_(1.0e-7), primalTolerance_(1.0e-7), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), infeasibilityCost_(1.0e10), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), acceptablePivot_(1.0e-8), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rowObjectiveWork_(NULL), objectiveWork_(NULL), sequenceIn_(-1), directionIn_(-1), sequenceOut_(-1), directionOut_(-1), pivotRow_(-1), lastGoodIteration_(-100), dj_(NULL), rowReducedCost_(NULL), reducedCostWork_(NULL), solution_(NULL), rowActivityWork_(NULL), columnActivityWork_(NULL), numberDualInfeasibilities_(0), numberDualInfeasibilitiesWithoutFree_(0), numberPrimalInfeasibilities_(100), numberRefinements_(0), pivotVariable_(NULL), factorization_(NULL), savedSolution_(NULL), numberTimesOptimal_(0), disasterArea_(NULL), changeMade_(1), algorithm_(0), forceFactorization_(-1), perturbation_(100), nonLinearCost_(NULL), lastBadIteration_(-999999), lastFlaggedIteration_(-999999), numberFake_(0), numberChanged_(0), progressFlag_(0), firstFree_(-1), numberExtraRows_(0), maximumBasic_(0), dontFactorizePivots_(0), incomingInfeasibility_(1.0), allowedInfeasibility_(10.0), automaticScale_(0), maximumPerturbationSize_(0), perturbationArray_(NULL), baseModel_(NULL) #ifdef ABC_INHERIT ,abcSimplex_(NULL), abcState_(0) #endif { int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } for (i = 0; i < 4; i++) { spareIntArray_[i] = 0; spareDoubleArray_[i] = 0.0; } saveStatus_ = NULL; // get an empty factorization so we can set tolerances etc getEmptyFactorization(); // say Steepest pricing dualRowPivot_ = new ClpDualRowSteepest(); // say Steepest pricing primalColumnPivot_ = new ClpPrimalColumnSteepest(); solveType_ = 1; // say simplex based life form if (fixOthers) { int numberOtherColumns = rhs->numberColumns(); int numberOtherRows = rhs->numberRows(); double * solution = new double [numberOtherColumns]; CoinZeroN(solution, numberOtherColumns); int i; for (i = 0; i < numberColumns; i++) { int iColumn = whichColumn[i]; if (solution[iColumn]) fixOthers = false; // duplicates solution[iColumn] = 1.0; } if (fixOthers) { const double * otherSolution = rhs->primalColumnSolution(); const double * objective = rhs->objective(); double offset = 0.0; for (i = 0; i < numberOtherColumns; i++) { if (solution[i]) { solution[i] = 0.0; // in } else { solution[i] = otherSolution[i]; offset += objective[i] * otherSolution[i]; } } double * rhsModification = new double [numberOtherRows]; CoinZeroN(rhsModification, numberOtherRows); rhs->matrix()->times(solution, rhsModification) ; for ( i = 0; i < numberRows; i++) { int iRow = whichRow[i]; if (rowLower_[i] > -1.0e20) rowLower_[i] -= rhsModification[iRow]; if (rowUpper_[i] < 1.0e20) rowUpper_[i] -= rhsModification[iRow]; } delete [] rhsModification; setObjectiveOffset(rhs->objectiveOffset() - offset); // And set objective value to match setObjectiveValue(rhs->objectiveValue()); } delete [] solution; } } // Subproblem constructor ClpSimplex::ClpSimplex ( const ClpSimplex * rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn, bool dropNames, bool dropIntegers, bool fixOthers) : ClpModel(rhs, numberRows, whichRow, numberColumns, whichColumn, dropNames, dropIntegers), bestPossibleImprovement_(0.0), zeroTolerance_(1.0e-13), columnPrimalSequence_(-2), rowPrimalSequence_(-2), bestObjectiveValue_(-COIN_DBL_MAX), moreSpecialOptions_(2), baseIteration_(0), primalToleranceToGetOptimal_(-1.0), largeValue_(1.0e15), largestPrimalError_(0.0), largestDualError_(0.0), alphaAccuracy_(-1.0), dualBound_(1.0e10), alpha_(0.0), theta_(0.0), lowerIn_(0.0), valueIn_(0.0), upperIn_(-COIN_DBL_MAX), dualIn_(0.0), lowerOut_(-1), valueOut_(-1), upperOut_(-1), dualOut_(-1), dualTolerance_(rhs->dualTolerance_), primalTolerance_(rhs->primalTolerance_), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), infeasibilityCost_(1.0e10), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), acceptablePivot_(1.0e-8), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rowObjectiveWork_(NULL), objectiveWork_(NULL), sequenceIn_(-1), directionIn_(-1), sequenceOut_(-1), directionOut_(-1), pivotRow_(-1), lastGoodIteration_(-100), dj_(NULL), rowReducedCost_(NULL), reducedCostWork_(NULL), solution_(NULL), rowActivityWork_(NULL), columnActivityWork_(NULL), numberDualInfeasibilities_(0), numberDualInfeasibilitiesWithoutFree_(0), numberPrimalInfeasibilities_(100), numberRefinements_(0), pivotVariable_(NULL), factorization_(NULL), savedSolution_(NULL), numberTimesOptimal_(0), disasterArea_(NULL), changeMade_(1), algorithm_(0), forceFactorization_(-1), perturbation_(100), nonLinearCost_(NULL), lastBadIteration_(-999999), lastFlaggedIteration_(-999999), numberFake_(0), numberChanged_(0), progressFlag_(0), firstFree_(-1), numberExtraRows_(0), maximumBasic_(0), dontFactorizePivots_(0), incomingInfeasibility_(1.0), allowedInfeasibility_(10.0), automaticScale_(0), maximumPerturbationSize_(0), perturbationArray_(NULL), baseModel_(NULL) #ifdef ABC_INHERIT ,abcSimplex_(NULL), abcState_(rhs->abcState_) #endif { int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } for (i = 0; i < 4; i++) { spareIntArray_[i] = 0; spareDoubleArray_[i] = 0.0; } saveStatus_ = NULL; factorization_ = new ClpFactorization(*rhs->factorization_, -numberRows_); //factorization_ = new ClpFactorization(*rhs->factorization_, // rhs->factorization_->goDenseThreshold()); ClpDualRowDantzig * pivot = dynamic_cast< ClpDualRowDantzig*>(rhs->dualRowPivot_); // say Steepest pricing if (!pivot) dualRowPivot_ = new ClpDualRowSteepest(); else dualRowPivot_ = new ClpDualRowDantzig(); // say Steepest pricing primalColumnPivot_ = new ClpPrimalColumnSteepest(); solveType_ = 1; // say simplex based life form if (fixOthers) { int numberOtherColumns = rhs->numberColumns(); int numberOtherRows = rhs->numberRows(); double * solution = new double [numberOtherColumns]; CoinZeroN(solution, numberOtherColumns); int i; for (i = 0; i < numberColumns; i++) { int iColumn = whichColumn[i]; if (solution[iColumn]) fixOthers = false; // duplicates solution[iColumn] = 1.0; } if (fixOthers) { const double * otherSolution = rhs->primalColumnSolution(); const double * objective = rhs->objective(); double offset = 0.0; for (i = 0; i < numberOtherColumns; i++) { if (solution[i]) { solution[i] = 0.0; // in } else { solution[i] = otherSolution[i]; offset += objective[i] * otherSolution[i]; } } double * rhsModification = new double [numberOtherRows]; CoinZeroN(rhsModification, numberOtherRows); rhs->matrix()->times(solution, rhsModification) ; for ( i = 0; i < numberRows; i++) { int iRow = whichRow[i]; if (rowLower_[i] > -1.0e20) rowLower_[i] -= rhsModification[iRow]; if (rowUpper_[i] < 1.0e20) rowUpper_[i] -= rhsModification[iRow]; } delete [] rhsModification; setObjectiveOffset(rhs->objectiveOffset() - offset); // And set objective value to match setObjectiveValue(rhs->objectiveValue()); } delete [] solution; } if (rhs->maximumPerturbationSize_) { maximumPerturbationSize_ = 2 * numberColumns; perturbationArray_ = new double [maximumPerturbationSize_]; for (i = 0; i < numberColumns; i++) { int iColumn = whichColumn[i]; perturbationArray_[2*i] = rhs->perturbationArray_[2*iColumn]; perturbationArray_[2*i+1] = rhs->perturbationArray_[2*iColumn+1]; } } } // Puts solution back small model void ClpSimplex::getbackSolution(const ClpSimplex & smallModel, const int * whichRow, const int * whichColumn) { setSumDualInfeasibilities(smallModel.sumDualInfeasibilities()); setNumberDualInfeasibilities(smallModel.numberDualInfeasibilities()); setSumPrimalInfeasibilities(smallModel.sumPrimalInfeasibilities()); setNumberPrimalInfeasibilities(smallModel.numberPrimalInfeasibilities()); setNumberIterations(smallModel.numberIterations()); setProblemStatus(smallModel.status()); setObjectiveValue(smallModel.objectiveValue()); const double * solution2 = smallModel.primalColumnSolution(); int i; int numberRows2 = smallModel.numberRows(); int numberColumns2 = smallModel.numberColumns(); const double * dj2 = smallModel.dualColumnSolution(); for ( i = 0; i < numberColumns2; i++) { int iColumn = whichColumn[i]; columnActivity_[iColumn] = solution2[i]; reducedCost_[iColumn] = dj2[i]; setStatus(iColumn, smallModel.getStatus(i)); } const double * dual2 = smallModel.dualRowSolution(); memset(dual_, 0, numberRows_ * sizeof(double)); for (i = 0; i < numberRows2; i++) { int iRow = whichRow[i]; setRowStatus(iRow, smallModel.getRowStatus(i)); dual_[iRow] = dual2[i]; } CoinZeroN(rowActivity_, numberRows_); #if 0 if (!problemStatus_) { ClpDisjointCopyN(smallModel.objective(), smallModel.numberColumns_, smallModel.reducedCost_); smallModel.matrix_->transposeTimes(-1.0, smallModel.dual_, smallModel.reducedCost_); for (int i = 0; i < smallModel.numberColumns_; i++) { if (smallModel.getColumnStatus(i) == basic) assert (fabs(smallModel.reducedCost_[i]) < 1.0e-5); } ClpDisjointCopyN(objective(), numberColumns_, reducedCost_); matrix_->transposeTimes(-1.0, dual_, reducedCost_); for (int i = 0; i < numberColumns_; i++) { if (getColumnStatus(i) == basic) assert (fabs(reducedCost_[i]) < 1.0e-5); } } #endif matrix()->times(columnActivity_, rowActivity_) ; } //----------------------------------------------------------------------------- ClpSimplex::~ClpSimplex () { setPersistenceFlag(0); gutsOfDelete(0); delete nonLinearCost_; } //############################################################################# void ClpSimplex::setLargeValue( double value) { if (value > 0.0 && value < COIN_DBL_MAX) largeValue_ = value; } int ClpSimplex::gutsOfSolution ( double * givenDuals, const double * givenPrimals, bool valuesPass) { // if values pass, save values of basic variables double * save = NULL; double oldValue = 0.0; if (valuesPass) { assert(algorithm_ > 0); // only primal at present assert(nonLinearCost_); int iRow; checkPrimalSolution( rowActivityWork_, columnActivityWork_); // get correct bounds on all variables nonLinearCost_->checkInfeasibilities(primalTolerance_); oldValue = nonLinearCost_->largestInfeasibility(); save = new double[numberRows_]; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; save[iRow] = solution_[iPivot]; } } // do work computePrimals(rowActivityWork_, columnActivityWork_); // If necessary - override results if (givenPrimals) { CoinMemcpyN(givenPrimals, numberColumns_, columnActivityWork_); memset(rowActivityWork_, 0, numberRows_ * sizeof(double)); times(-1.0, columnActivityWork_, rowActivityWork_); } double objectiveModification = 0.0; if (algorithm_ > 0 && nonLinearCost_ != NULL) { // primal algorithm // get correct bounds on all variables // If 4 bit set - Force outgoing variables to exact bound (primal) if ((specialOptions_ & 4) == 0) nonLinearCost_->checkInfeasibilities(primalTolerance_); else nonLinearCost_->checkInfeasibilities(0.0); objectiveModification += nonLinearCost_->changeInCost(); if (nonLinearCost_->numberInfeasibilities()) if (handler_->detail(CLP_SIMPLEX_NONLINEAR, messages_) < 100) { handler_->message(CLP_SIMPLEX_NONLINEAR, messages_) << nonLinearCost_->changeInCost() << nonLinearCost_->numberInfeasibilities() << CoinMessageEol; } } if (valuesPass) { double badInfeasibility = nonLinearCost_->largestInfeasibility(); #ifdef CLP_DEBUG std::cout << "Largest given infeasibility " << oldValue << " now " << nonLinearCost_->largestInfeasibility() << std::endl; #endif int numberOut = 0; // But may be very large rhs etc double useError = CoinMin(largestPrimalError_, 1.0e5 / maximumAbsElement(solution_, numberRows_ + numberColumns_)); if ((oldValue < incomingInfeasibility_ || badInfeasibility > (CoinMax(10.0 * allowedInfeasibility_, 100.0 * oldValue))) && (badInfeasibility > CoinMax(incomingInfeasibility_, allowedInfeasibility_) || useError > 1.0e-3)) { if (algorithm_>1) { // nonlinear //printf("Original largest infeas %g, now %g, primalError %g\n", // oldValue,nonLinearCost_->largestInfeasibility(), // largestPrimalError_); //printf("going to all slack\n"); allSlackBasis(true); CoinIotaN(pivotVariable_, numberRows_, numberColumns_); return 1; } //printf("Original largest infeas %g, now %g, primalError %g\n", // oldValue,nonLinearCost_->largestInfeasibility(), // largestPrimalError_); // throw out up to 1000 structurals int maxOut = (allowedInfeasibility_==10.0) ? 1000 : 100; int iRow; int * sort = new int[numberRows_]; // first put back solution and store difference for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double difference = fabs(solution_[iPivot] - save[iRow]); solution_[iPivot] = save[iRow]; save[iRow] = difference; } int numberBasic = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_) { // column double difference = save[iRow]; if (difference > 1.0e-4) { sort[numberOut] = iRow; save[numberOut++] = -difference; if (getStatus(iPivot) == basic) numberBasic++; } } } if (!numberBasic) { //printf("no errors on basic - going to all slack - numberOut %d\n",numberOut); #if 0 allSlackBasis(true); CoinIotaN(pivotVariable_, numberRows_, numberColumns_); #else // allow numberOut = 0; #endif } CoinSort_2(save, save + numberOut, sort); numberOut = CoinMin(maxOut, numberOut); for (iRow = 0; iRow < numberOut; iRow++) { int jRow = sort[iRow]; int iColumn = pivotVariable_[jRow]; setColumnStatus(iColumn, superBasic); setRowStatus(jRow, basic); pivotVariable_[jRow] = jRow + numberColumns_; if (fabs(solution_[iColumn]) > 1.0e10) { if (upper_[iColumn] < 0.0) { solution_[iColumn] = upper_[iColumn]; } else if (lower_[iColumn] > 0.0) { solution_[iColumn] = lower_[iColumn]; } else { solution_[iColumn] = 0.0; } } } delete [] sort; } delete [] save; if (numberOut) return numberOut; } if ((moreSpecialOptions_ & 128) != 0 && !numberIterations_) { //printf("trying feas pump\n"); const char * integerType = integerInformation(); assert (integerType); assert (perturbationArray_); CoinZeroN(cost_, numberRows_ + numberColumns_); for (int i = 0; i < numberRows_ - numberRows_; i++) { int iSequence = pivotVariable_[i]; if (iSequence < numberColumns_ && integerType[iSequence]) { double lower = lower_[iSequence]; double upper = upper_[iSequence]; double value = solution_[iSequence]; if (value >= lower - primalTolerance_ && value <= upper + primalTolerance_) { double sign; if (value - lower < upper - value) sign = 1.0; else sign = -1.0; cost_[iSequence] = sign * perturbationArray_[iSequence]; } } } } #if CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)==0) { #endif computeDuals(givenDuals); if ((moreSpecialOptions_ & 128) != 0 && !numberIterations_) { const char * integerType = integerInformation(); // Need to do columns and rows to stay dual feasible for (int iSequence = 0; iSequence < numberColumns_; iSequence++) { if (integerType[iSequence] && getStatus(iSequence) != basic) { double djValue = dj_[iSequence]; double change = 0.0; if (getStatus(iSequence) == atLowerBound) change = CoinMax(-djValue, 10.0 * perturbationArray_[iSequence]); else if (getStatus(iSequence) == atUpperBound) change = CoinMin(-djValue, -10.0 * perturbationArray_[iSequence]); cost_[iSequence] = change; dj_[iSequence] += change; } } } // now check solutions //checkPrimalSolution( rowActivityWork_, columnActivityWork_); //checkDualSolution(); checkBothSolutions(); objectiveValue_ += objectiveModification / (objectiveScale_ * rhsScale_); #if CAN_HAVE_ZERO_OBJ>1 } else { checkPrimalSolution( rowActivityWork_, columnActivityWork_); #ifndef COIN_REUSE_RANDOM memset(dj_,0,(numberRows_+numberColumns_)*sizeof(double)); #else for (int iSequence=0;iSequencelogLevel() > 3 || (largestPrimalError_ > 1.0e-2 || largestDualError_ > 1.0e-2)) handler_->message(CLP_SIMPLEX_ACCURACY, messages_) << largestPrimalError_ << largestDualError_ << CoinMessageEol; if (largestPrimalError_ > 1.0e-1 && numberRows_ > 100 && numberIterations_) { // Change factorization tolerance if (factorization_->zeroTolerance() > 1.0e-18) factorization_->zeroTolerance(1.0e-18); } // Switch off false values pass indicator if (!valuesPass && algorithm_ > 0) firstFree_ = -1; return 0; } void ClpSimplex::computePrimals ( const double * rowActivities, const double * columnActivities) { //work space CoinIndexedVector * workSpace = rowArray_[0]; CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); CoinIndexedVector * previousVector = rowArray_[2]; previousVector->clear(); // accumulate non basic stuff int iRow; // order is this way for scaling if (columnActivities != columnActivityWork_) ClpDisjointCopyN(columnActivities, numberColumns_, columnActivityWork_); if (rowActivities != rowActivityWork_) ClpDisjointCopyN(rowActivities, numberRows_, rowActivityWork_); double * array = arrayVector->denseVector(); int * index = arrayVector->getIndices(); int number = 0; const double * rhsOffset = matrix_->rhsOffset(this, false, true); if (!rhsOffset) { // Use whole matrix every time to make it easier for ClpMatrixBase // So zero out basic for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; assert (iPivot >= 0); solution_[iPivot] = 0.0; #ifdef CLP_INVESTIGATE assert (getStatus(iPivot) == basic); #endif } // Extended solution before "update" matrix_->primalExpanded(this, 0); times(-1.0, columnActivityWork_, array); for (iRow = 0; iRow < numberRows_; iRow++) { double value = array[iRow] + rowActivityWork_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } else { array[iRow] = 0.0; } } } else { // we have an effective rhs lying around // zero out basic (really just for slacks) for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; solution_[iPivot] = 0.0; } for (iRow = 0; iRow < numberRows_; iRow++) { double value = rhsOffset[iRow] + rowActivityWork_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } else { array[iRow] = 0.0; } } } arrayVector->setNumElements(number); #ifdef CLP_DEBUG if (numberIterations_ == -3840) { int i; for (i = 0; i < numberRows_ + numberColumns_; i++) printf("%d status %d\n", i, status_[i]); printf("xxxxx1\n"); for (i = 0; i < numberRows_; i++) if (array[i]) printf("%d rhs %g\n", i, array[i]); printf("xxxxx2\n"); for (i = 0; i < numberRows_ + numberColumns_; i++) if (getStatus(i) != basic) printf("%d non basic %g %g %g\n", i, lower_[i], solution_[i], upper_[i]); printf("xxxxx3\n"); } #endif // Ftran adjusted RHS and iterate to improve accuracy double lastError = COIN_DBL_MAX; int iRefine; CoinIndexedVector * thisVector = arrayVector; CoinIndexedVector * lastVector = previousVector; if (number) factorization_->updateColumn(workSpace, thisVector); double * work = workSpace->denseVector(); #ifdef CLP_DEBUG if (numberIterations_ == -3840) { int i; for (i = 0; i < numberRows_; i++) if (array[i]) printf("%d after rhs %g\n", i, array[i]); printf("xxxxx4\n"); } #endif bool goodSolution = true; for (iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) { int numberIn = thisVector->getNumElements(); int * indexIn = thisVector->getIndices(); double * arrayIn = thisVector->denseVector(); // put solution in correct place if (!rhsOffset) { int j; for (j = 0; j < numberIn; j++) { iRow = indexIn[j]; int iPivot = pivotVariable_[iRow]; solution_[iPivot] = arrayIn[iRow]; //assert (fabs(solution_[iPivot])<1.0e100); } } else { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; solution_[iPivot] = arrayIn[iRow]; //assert (fabs(solution_[iPivot])<1.0e100); } } // Extended solution after "update" matrix_->primalExpanded(this, 1); // check Ax == b (for all) // signal column generated matrix to just do basic (and gub) unsigned int saveOptions = specialOptions(); setSpecialOptions(16); times(-1.0, columnActivityWork_, work); setSpecialOptions(saveOptions); largestPrimalError_ = 0.0; double multiplier = 131072.0; for (iRow = 0; iRow < numberRows_; iRow++) { double value = work[iRow] + rowActivityWork_[iRow]; work[iRow] = value * multiplier; if (fabs(value) > largestPrimalError_) { largestPrimalError_ = fabs(value); } } if (largestPrimalError_ >= lastError) { // restore CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; goodSolution = false; break; } if (iRefine < numberRefinements_ && largestPrimalError_ > 1.0e-10) { // try and make better // save this CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; int * indexOut = thisVector->getIndices(); int number = 0; array = thisVector->denseVector(); thisVector->clear(); for (iRow = 0; iRow < numberRows_; iRow++) { double value = work[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; work[iRow] = 0.0; } } thisVector->setNumElements(number); lastError = largestPrimalError_; factorization_->updateColumn(workSpace, thisVector); multiplier = 1.0 / multiplier; double * previous = lastVector->denseVector(); number = 0; for (iRow = 0; iRow < numberRows_; iRow++) { double value = previous[iRow] + multiplier * array[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; } else { array[iRow] = 0.0; } } thisVector->setNumElements(number); } else { break; } } // solution as accurate as we are going to get ClpFillN(work, numberRows_, 0.0); if (!goodSolution) { array = thisVector->denseVector(); // put solution in correct place for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; solution_[iPivot] = array[iRow]; //assert (fabs(solution_[iPivot])<1.0e100); } } arrayVector->clear(); previousVector->clear(); #ifdef CLP_DEBUG if (numberIterations_ == -3840) { exit(77); } #endif } // now dual side void ClpSimplex::computeDuals(double * givenDjs) { #ifndef SLIM_CLP if (objective_->type() == 1 || !objective_->activated()) { #endif // Linear //work space CoinIndexedVector * workSpace = rowArray_[0]; CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); CoinIndexedVector * previousVector = rowArray_[2]; previousVector->clear(); int iRow; #ifdef CLP_DEBUG workSpace->checkClear(); #endif double * array = arrayVector->denseVector(); int * index = arrayVector->getIndices(); int number = 0; if (!givenDjs) { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value = cost_[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } } else { // dual values pass - djs may not be zero for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; // make sure zero if done if (!pivoted(iPivot)) givenDjs[iPivot] = 0.0; double value = cost_[iPivot] - givenDjs[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } } arrayVector->setNumElements(number); // Extended duals before "updateTranspose" matrix_->dualExpanded(this, arrayVector, givenDjs, 0); // Btran basic costs and get as accurate as possible double lastError = COIN_DBL_MAX; int iRefine; double * work = workSpace->denseVector(); CoinIndexedVector * thisVector = arrayVector; CoinIndexedVector * lastVector = previousVector; factorization_->updateColumnTranspose(workSpace, thisVector); for (iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) { // check basic reduced costs zero largestDualError_ = 0.0; if (!numberExtraRows_) { // Just basic int * index2 = workSpace->getIndices(); // use reduced costs for slacks as work array double * work2 = reducedCostWork_ + numberColumns_; int numberStructurals = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_) index2[numberStructurals++] = iPivot; } matrix_->listTransposeTimes(this, array, index2, numberStructurals, work2); numberStructurals = 0; if (!givenDjs) { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value; if (iPivot >= numberColumns_) { // slack value = rowObjectiveWork_[iPivot-numberColumns_] + array[iPivot-numberColumns_]; } else { // column value = objectiveWork_[iPivot] - work2[numberStructurals++]; } work[iRow] = value; if (fabs(value) > largestDualError_) { largestDualError_ = fabs(value); } } } else { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot >= numberColumns_) { // slack work[iRow] = rowObjectiveWork_[iPivot-numberColumns_] + array[iPivot-numberColumns_] - givenDjs[iPivot]; } else { // column work[iRow] = objectiveWork_[iPivot] - work2[numberStructurals++] - givenDjs[iPivot]; } if (fabs(work[iRow]) > largestDualError_) { largestDualError_ = fabs(work[iRow]); //assert (largestDualError_<1.0e-7); //if (largestDualError_>1.0e-7) //printf("large dual error %g\n",largestDualError_); } } } } else { // extra rows - be more careful #if 1 // would be faster to do just for basic but this reduces code ClpDisjointCopyN(objectiveWork_, numberColumns_, reducedCostWork_); transposeTimes(-1.0, array, reducedCostWork_); #else // Just basic int * index2 = workSpace->getIndices(); int numberStructurals = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_) index2[numberStructurals++] = iPivot; } matrix_->listTransposeTimes(this, array, index2, numberStructurals, work); for (iRow = 0; iRow < numberStructurals; iRow++) { int iPivot = index2[iRow]; reducedCostWork_[iPivot] = objectiveWork_[iPivot] - work[iRow]; } #endif // update by duals on sets matrix_->dualExpanded(this, NULL, NULL, 1); if (!givenDjs) { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value; if (iPivot >= numberColumns_) { // slack value = rowObjectiveWork_[iPivot-numberColumns_] + array[iPivot-numberColumns_]; } else { // column value = reducedCostWork_[iPivot]; } work[iRow] = value; if (fabs(value) > largestDualError_) { largestDualError_ = fabs(value); } } } else { for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot >= numberColumns_) { // slack work[iRow] = rowObjectiveWork_[iPivot-numberColumns_] + array[iPivot-numberColumns_] - givenDjs[iPivot]; } else { // column work[iRow] = reducedCostWork_[iPivot] - givenDjs[iPivot]; } if (fabs(work[iRow]) > largestDualError_) { largestDualError_ = fabs(work[iRow]); //assert (largestDualError_<1.0e-7); //if (largestDualError_>1.0e-7) //printf("large dual error %g\n",largestDualError_); } } } } if (largestDualError_ >= lastError) { // restore CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; break; } if (iRefine < numberRefinements_ && largestDualError_ > 1.0e-10 && !givenDjs) { // try and make better // save this CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; int * indexOut = thisVector->getIndices(); int number = 0; array = thisVector->denseVector(); thisVector->clear(); double multiplier = 131072.0; for (iRow = 0; iRow < numberRows_; iRow++) { double value = multiplier * work[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; work[iRow] = 0.0; } work[iRow] = 0.0; } thisVector->setNumElements(number); lastError = largestDualError_; factorization_->updateColumnTranspose(workSpace, thisVector); multiplier = 1.0 / multiplier; double * previous = lastVector->denseVector(); number = 0; for (iRow = 0; iRow < numberRows_; iRow++) { double value = previous[iRow] + multiplier * array[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; } else { array[iRow] = 0.0; } } thisVector->setNumElements(number); } else { break; } } // now look at dual solution array = thisVector->denseVector(); for (iRow = 0; iRow < numberRows_; iRow++) { // slack double value = array[iRow]; dual_[iRow] = value; value += rowObjectiveWork_[iRow]; rowReducedCost_[iRow] = value; } // can use work if problem scaled (for better cache) ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); double * saveRowScale = rowScale_; //double * saveColumnScale = columnScale_; if (scaledMatrix_) { rowScale_ = NULL; clpMatrix = scaledMatrix_; } if (clpMatrix && (clpMatrix->flags() & 2) == 0) { CoinIndexedVector * cVector = columnArray_[0]; int * whichColumn = cVector->getIndices(); assert (!cVector->getNumElements()); int n = 0; for (int i = 0; i < numberColumns_; i++) { if (getColumnStatus(i) != basic) { whichColumn[n++] = i; reducedCostWork_[i] = objectiveWork_[i]; } else { reducedCostWork_[i] = 0.0; } } if (numberRows_ > 4000) clpMatrix->transposeTimesSubset(n, whichColumn, dual_, reducedCostWork_, rowScale_, columnScale_, work); else clpMatrix->transposeTimesSubset(n, whichColumn, dual_, reducedCostWork_, rowScale_, columnScale_, NULL); } else { ClpDisjointCopyN(objectiveWork_, numberColumns_, reducedCostWork_); if (numberRows_ > 4000) matrix_->transposeTimes(-1.0, dual_, reducedCostWork_, rowScale_, columnScale_, work); else matrix_->transposeTimes(-1.0, dual_, reducedCostWork_, rowScale_, columnScale_, NULL); } rowScale_ = saveRowScale; //columnScale_ = saveColumnScale; ClpFillN(work, numberRows_, 0.0); // Extended duals and check dual infeasibility if (!matrix_->skipDualCheck() || algorithm_ < 0 || problemStatus_ != -2) matrix_->dualExpanded(this, NULL, NULL, 2); // If necessary - override results if (givenDjs) { // restore accurate duals CoinMemcpyN(dj_, (numberRows_ + numberColumns_), givenDjs); } arrayVector->clear(); previousVector->clear(); #ifndef SLIM_CLP } else { // Nonlinear objective_->reducedGradient(this, dj_, false); // get dual_ by moving from reduced costs for slacks CoinMemcpyN(dj_ + numberColumns_, numberRows_, dual_); } #endif } /* Given an existing factorization computes and checks primal and dual solutions. Uses input arrays for variables at bounds. Returns feasibility states */ int ClpSimplex::getSolution ( const double * /*rowActivities*/, const double * /*columnActivities*/) { if (!factorization_->status()) { // put in standard form createRim(7 + 8 + 16 + 32, false, -1); if (pivotVariable_[0] < 0) internalFactorize(0); // do work gutsOfSolution ( NULL, NULL); // release extra memory deleteRim(0); } return factorization_->status(); } /* Given an existing factorization computes and checks primal and dual solutions. Uses current problem arrays for bounds. Returns feasibility states */ int ClpSimplex::getSolution ( ) { double * rowActivities = new double[numberRows_]; double * columnActivities = new double[numberColumns_]; ClpDisjointCopyN ( rowActivityWork_, numberRows_ , rowActivities); ClpDisjointCopyN ( columnActivityWork_, numberColumns_ , columnActivities); int status = getSolution( rowActivities, columnActivities); delete [] rowActivities; delete [] columnActivities; return status; } // Factorizes using current basis. This is for external use // Return codes are as from ClpFactorization int ClpSimplex::factorize () { // put in standard form createRim(7 + 8 + 16 + 32, false); // do work int status = internalFactorize(-1); // release extra memory deleteRim(0); return status; } // Clean up status void ClpSimplex::cleanStatus() { int iRow, iColumn; int numberBasic = 0; // make row activities correct memset(rowActivityWork_, 0, numberRows_ * sizeof(double)); times(1.0, columnActivityWork_, rowActivityWork_); if (!status_) createStatus(); for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) == basic) numberBasic++; else { setRowStatus(iRow, superBasic); // but put to bound if close if (fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow]) <= primalTolerance_) { rowActivityWork_[iRow] = rowLowerWork_[iRow]; setRowStatus(iRow, atLowerBound); } else if (fabs(rowActivityWork_[iRow] - rowUpperWork_[iRow]) <= primalTolerance_) { rowActivityWork_[iRow] = rowUpperWork_[iRow]; setRowStatus(iRow, atUpperBound); } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) == basic) { if (numberBasic == numberRows_) { // take out of basis setColumnStatus(iColumn, superBasic); // but put to bound if close if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else if (fabs(columnActivityWork_[iColumn] - columnUpperWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } else numberBasic++; } else { setColumnStatus(iColumn, superBasic); // but put to bound if close if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else if (fabs(columnActivityWork_[iColumn] - columnUpperWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } } } /* Factorizes using current basis. solveType - 1 iterating, 0 initial, -1 external - 2 then iterating but can throw out of basis If 10 added then in primal values pass Return codes are as from ClpFactorization unless initial factorization when total number of singularities is returned. Special case is numberRows_+1 -> all slack basis. */ int ClpSimplex::internalFactorize ( int solveType) { int iRow, iColumn; int totalSlacks = numberRows_; if (!status_) createStatus(); bool valuesPass = false; if (solveType >= 10) { valuesPass = true; solveType -= 10; } #ifdef CLP_DEBUG if (solveType > 0) { int numberFreeIn = 0, numberFreeOut = 0; double biggestDj = 0.0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { switch(getColumnStatus(iColumn)) { case basic: if (columnLower_[iColumn] < -largeValue_ && columnUpper_[iColumn] > largeValue_) numberFreeIn++; break; default: if (columnLower_[iColumn] < -largeValue_ && columnUpper_[iColumn] > largeValue_) { numberFreeOut++; biggestDj = CoinMax(fabs(dj_[iColumn]), biggestDj); } break; } } if (numberFreeIn + numberFreeOut) printf("%d in basis, %d out - largest dj %g\n", numberFreeIn, numberFreeOut, biggestDj); } #endif if (solveType <= 0) { // Make sure everything is clean for (iRow = 0; iRow < numberRows_; iRow++) { if(getRowStatus(iRow) == isFixed) { // double check fixed if (rowUpperWork_[iRow] > rowLowerWork_[iRow]) setRowStatus(iRow, atLowerBound); } else if (getRowStatus(iRow) == isFree) { // may not be free after all if (rowLowerWork_[iRow] > -largeValue_ || rowUpperWork_[iRow] < largeValue_) setRowStatus(iRow, superBasic); } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if(getColumnStatus(iColumn) == isFixed) { // double check fixed if (columnUpperWork_[iColumn] > columnLowerWork_[iColumn]) setColumnStatus(iColumn, atLowerBound); } else if (getColumnStatus(iColumn) == isFree) { // may not be free after all if (columnLowerWork_[iColumn] > -largeValue_ || columnUpperWork_[iColumn] < largeValue_) setColumnStatus(iColumn, superBasic); } } if (!valuesPass) { // not values pass so set to bounds bool allSlack = true; if (status_) { for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) != basic) { allSlack = false; break; } } } if (!allSlack) { //#define CLP_INVESTIGATE2 #ifdef CLP_INVESTIGATE3 int numberTotal = numberRows_ + numberColumns_; double * saveSol = valuesPass ? CoinCopyOfArray(solution_, numberTotal) : NULL; #endif // set values from warm start (if sensible) int numberBasic = 0; for (iRow = 0; iRow < numberRows_; iRow++) { switch(getRowStatus(iRow)) { case basic: numberBasic++; break; case atUpperBound: rowActivityWork_[iRow] = rowUpperWork_[iRow]; if (rowActivityWork_[iRow] > largeValue_) { if (rowLowerWork_[iRow] > -largeValue_) { rowActivityWork_[iRow] = rowLowerWork_[iRow]; setRowStatus(iRow, atLowerBound); } else { // say free setRowStatus(iRow, isFree); rowActivityWork_[iRow] = 0.0; } } break; case ClpSimplex::isFixed: case atLowerBound: rowActivityWork_[iRow] = rowLowerWork_[iRow]; if (rowActivityWork_[iRow] < -largeValue_) { if (rowUpperWork_[iRow] < largeValue_) { rowActivityWork_[iRow] = rowUpperWork_[iRow]; setRowStatus(iRow, atUpperBound); } else { // say free setRowStatus(iRow, isFree); rowActivityWork_[iRow] = 0.0; } } break; case isFree: break; // not really free - fall through to superbasic case superBasic: if (rowUpperWork_[iRow] > largeValue_) { if (rowLowerWork_[iRow] > -largeValue_) { rowActivityWork_[iRow] = rowLowerWork_[iRow]; setRowStatus(iRow, atLowerBound); } else { // say free setRowStatus(iRow, isFree); rowActivityWork_[iRow] = 0.0; } } else { if (rowLowerWork_[iRow] > -largeValue_) { // set to nearest if (fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow]) < fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow])) { rowActivityWork_[iRow] = rowLowerWork_[iRow]; setRowStatus(iRow, atLowerBound); } else { rowActivityWork_[iRow] = rowUpperWork_[iRow]; setRowStatus(iRow, atUpperBound); } } else { rowActivityWork_[iRow] = rowUpperWork_[iRow]; setRowStatus(iRow, atUpperBound); } } break; } } totalSlacks = numberBasic; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { switch(getColumnStatus(iColumn)) { case basic: if (numberBasic == maximumBasic_) { // take out of basis if (columnLowerWork_[iColumn] > -largeValue_) { if (columnActivityWork_[iColumn] - columnLowerWork_[iColumn] < columnUpperWork_[iColumn] - columnActivityWork_[iColumn]) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } else if (columnUpperWork_[iColumn] < largeValue_) { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } else { columnActivityWork_[iColumn] = 0.0; setColumnStatus(iColumn, isFree); } } else { numberBasic++; } break; case atUpperBound: columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; if (columnActivityWork_[iColumn] > largeValue_) { if (columnLowerWork_[iColumn] < -largeValue_) { columnActivityWork_[iColumn] = 0.0; setColumnStatus(iColumn, isFree); } else { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } } break; case isFixed: case atLowerBound: columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; if (columnActivityWork_[iColumn] < -largeValue_) { if (columnUpperWork_[iColumn] > largeValue_) { columnActivityWork_[iColumn] = 0.0; setColumnStatus(iColumn, isFree); } else { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } break; case isFree: break; // not really free - fall through to superbasic case superBasic: if (columnUpperWork_[iColumn] > largeValue_) { if (columnLowerWork_[iColumn] > -largeValue_) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else { // say free setColumnStatus(iColumn, isFree); columnActivityWork_[iColumn] = 0.0; } } else { if (columnLowerWork_[iColumn] > -largeValue_) { // set to nearest if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn]) < fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } else { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } break; } } #ifdef CLP_INVESTIGATE3 if (saveSol) { int numberChanged = 0; double largestChanged = 0.0; for (int i = 0; i < numberTotal; i++) { double difference = fabs(solution_[i] - saveSol[i]); if (difference > 1.0e-7) { numberChanged++; if (difference > largestChanged) largestChanged = difference; } } if (numberChanged) printf("%d changed, largest %g\n", numberChanged, largestChanged); delete [] saveSol; } #endif #if 0 if (numberBasic < numberRows_) { // add some slacks in case odd warmstart #ifdef CLP_INVESTIGATE printf("BAD %d basic, %d rows %d slacks\n", numberBasic, numberRows_, totalSlacks); #endif int iRow = numberRows_ - 1; while (numberBasic < numberRows_) { if (getRowStatus(iRow) != basic) { setRowStatus(iRow, basic); numberBasic++; totalSlacks++; iRow--; } else { break; } } } #endif } else { // all slack basis int numberBasic = 0; if (!status_) { createStatus(); } for (iRow = 0; iRow < numberRows_; iRow++) { double lower = rowLowerWork_[iRow]; double upper = rowUpperWork_[iRow]; if (lower > -largeValue_ || upper < largeValue_) { if (fabs(lower) <= fabs(upper)) { rowActivityWork_[iRow] = lower; } else { rowActivityWork_[iRow] = upper; } } else { rowActivityWork_[iRow] = 0.0; } setRowStatus(iRow, basic); numberBasic++; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double lower = columnLowerWork_[iColumn]; double upper = columnUpperWork_[iColumn]; double big_bound = largeValue_; if (lower > -big_bound || upper < big_bound) { if ((getColumnStatus(iColumn) == atLowerBound && columnActivityWork_[iColumn] == lower) || (getColumnStatus(iColumn) == atUpperBound && columnActivityWork_[iColumn] == upper)) { // status looks plausible } else { // set to sensible if (fabs(lower) <= fabs(upper)) { setColumnStatus(iColumn, atLowerBound); columnActivityWork_[iColumn] = lower; } else { setColumnStatus(iColumn, atUpperBound); columnActivityWork_[iColumn] = upper; } } } else { setColumnStatus(iColumn, isFree); columnActivityWork_[iColumn] = 0.0; } } } } else { // values pass has less coding // make row activities correct and clean basis a bit cleanStatus(); if (status_) { int numberBasic = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) == basic) numberBasic++; } totalSlacks = numberBasic; #if 0 for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) == basic) numberBasic++; } #endif } else { // all slack basis int numberBasic = 0; if (!status_) { createStatus(); } for (iRow = 0; iRow < numberRows_; iRow++) { setRowStatus(iRow, basic); numberBasic++; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { setColumnStatus(iColumn, superBasic); // but put to bound if close if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else if (fabs(columnActivityWork_[iColumn] - columnUpperWork_[iColumn]) <= primalTolerance_) { columnActivityWork_[iColumn] = columnUpperWork_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } } } numberRefinements_ = 1; // set fixed if they are for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) != basic ) { if (rowLowerWork_[iRow] == rowUpperWork_[iRow]) { rowActivityWork_[iRow] = rowLowerWork_[iRow]; setRowStatus(iRow, isFixed); } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) != basic ) { if (columnLowerWork_[iColumn] == columnUpperWork_[iColumn]) { columnActivityWork_[iColumn] = columnLowerWork_[iColumn]; setColumnStatus(iColumn, isFixed); } } } } //for (iRow=0;iRow1.0e10) { // printf("large %g at %d - status %d\n", // solution_[iRow],iRow,status_[iRow]); //} //} # if 0 //ndef _MSC_VER // The local static var k is a problem when trying to build a DLL. Since this is // just for debugging (likely done on *nix), just hide it from Windows // -- lh, 101016 -- if (0) { static int k = 0; printf("start basis\n"); int i; for (i = 0; i < numberRows_; i++) printf ("xx %d %d\n", i, pivotVariable_[i]); for (i = 0; i < numberRows_ + numberColumns_; i++) if (getColumnStatus(i) == basic) printf ("yy %d basic\n", i); if (k > 20) exit(0); k++; } # endif #if 0 //ndef NDEBUG // Make sure everything is clean double sumOutside=0.0; int numberOutside=0; //double sumOutsideLarge=0.0; int numberOutsideLarge=0; double sumInside=0.0; int numberInside=0; //double sumInsideLarge=0.0; int numberInsideLarge=0; int numberTotal=numberRows_+numberColumns_; for (int iSequence = 0; iSequence < numberTotal; iSequence++) { if(getStatus(iSequence) == isFixed) { // double check fixed assert (upper_[iSequence] == lower_[iSequence]); assert (fabs(solution_[iSequence]-lower_[iSequence])lower_[iSequence]) { numberInside++; sumInside+=solution_[iSequence]-lower_[iSequence]; if (solution_[iSequence]>lower_[iSequence]+primalTolerance_) numberInsideLarge++; } } else if (getStatus(iSequence) == atUpperBound) { assert (fabs(solution_[iSequence]-upper_[iSequence])<1000.0*primalTolerance_); if (solution_[iSequence]>upper_[iSequence]) { numberOutside++; sumOutside+=solution_[iSequence]-upper_[iSequence]; if (solution_[iSequence]>upper_[iSequence]+primalTolerance_) numberOutsideLarge++; } else if (solution_[iSequence]factorize(this, solveType, valuesPass); if (status) { handler_->message(CLP_SIMPLEX_BADFACTOR, messages_) << status << CoinMessageEol; return -1; } else if (!solveType) { // Initial basis - return number of singularities int numberSlacks = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) == basic) numberSlacks++; } status = CoinMax(numberSlacks - totalSlacks, 0); // special case if all slack if (numberSlacks == numberRows_) { status = numberRows_ + 1; } } // sparse methods //if (factorization_->sparseThreshold()) { // get default value factorization_->sparseThreshold(0); if (!(moreSpecialOptions_&1024)) factorization_->goSparse(); //} return status; } /* This does basis housekeeping and does values for in/out variables. Can also decide to re-factorize */ int ClpSimplex::housekeeping(double objectiveChange) { // save value of incoming and outgoing double oldIn = solution_[sequenceIn_]; double oldOut = solution_[sequenceOut_]; numberIterations_++; changeMade_++; // something has happened // incoming variable if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE1,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE1, messages_) << directionOut_ << directionIn_ << theta_ << dualOut_ << dualIn_ << alpha_ << CoinMessageEol; if (getStatus(sequenceIn_) == isFree) { handler_->message(CLP_SIMPLEX_FREEIN, messages_) << sequenceIn_ << CoinMessageEol; } } #if 0 printf("h1 %d %d %g %g %g %g", directionOut_ , directionIn_, theta_ , dualOut_, dualIn_, alpha_); #endif // change of incoming char rowcol[] = {'R', 'C'}; if (pivotRow_ >= 0) pivotVariable_[pivotRow_] = sequenceIn(); if (upper_[sequenceIn_] > 1.0e20 && lower_[sequenceIn_] < -1.0e20) progressFlag_ |= 2; // making real progress solution_[sequenceIn_] = valueIn_; if (upper_[sequenceOut_] - lower_[sequenceOut_] < 1.0e-12) progressFlag_ |= 1; // making real progress if (sequenceIn_ != sequenceOut_) { if (alphaAccuracy_ > 0.0) { double value = fabs(alpha_); if (value > 1.0) alphaAccuracy_ *= value; else alphaAccuracy_ /= value; } //assert( getStatus(sequenceOut_)== basic); setStatus(sequenceIn_, basic); if (upper_[sequenceOut_] - lower_[sequenceOut_] > 0) { // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueOut_ - lower_[sequenceOut_]) < fabs(valueOut_ - upper_[sequenceOut_])) { // going to lower setStatus(sequenceOut_, atLowerBound); oldOut = lower_[sequenceOut_]; } else { // going to upper setStatus(sequenceOut_, atUpperBound); oldOut = upper_[sequenceOut_]; } } else { // fixed setStatus(sequenceOut_, isFixed); } solution_[sequenceOut_] = valueOut_; } else { //if (objective_->type()<2) //assert (fabs(theta_)>1.0e-13); // flip from bound to bound // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueIn_ - lower_[sequenceIn_]) < fabs(valueIn_ - upper_[sequenceIn_])) { // as if from upper bound setStatus(sequenceIn_, atLowerBound); } else { // as if from lower bound setStatus(sequenceIn_, atUpperBound); } } // Update hidden stuff e.g. effective RHS and gub int invertNow=matrix_->updatePivot(this, oldIn, oldOut); objectiveValue_ += objectiveChange / (objectiveScale_ * rhsScale_); if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE2,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE2, messages_) << numberIterations_ << objectiveValue() << rowcol[isColumn(sequenceIn_)] << sequenceWithin(sequenceIn_) << rowcol[isColumn(sequenceOut_)] << sequenceWithin(sequenceOut_); handler_->printing(algorithm_ < 0) << dualOut_ << theta_; handler_->printing(algorithm_ > 0) << dualIn_ << theta_; handler_->message() << CoinMessageEol; } #if 0 if (numberIterations_ > 10000) printf(" it %d %g %c%d %c%d\n" , numberIterations_, objectiveValue() , rowcol[isColumn(sequenceIn_)], sequenceWithin(sequenceIn_) , rowcol[isColumn(sequenceOut_)], sequenceWithin(sequenceOut_)); #endif if (trustedUserPointer_ && trustedUserPointer_->typeStruct == 1) { if (algorithm_ > 0 && integerType_ && !nonLinearCost_->numberInfeasibilities()) { if (fabs(theta_) > 1.0e-6 || !numberIterations_) { // For saving solutions typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; clpSolution * solution = reinterpret_cast (trustedUserPointer_->data); if (solution->numberSolutions == solution->maximumSolutions) { int n = solution->maximumSolutions; int n2 = (n * 3) / 2 + 10; solution->maximumSolutions = n2; double ** temp = new double * [n2]; for (int i = 0; i < n; i++) temp[i] = solution->solution[i]; delete [] solution->solution; solution->solution = temp; int * tempN = new int [n2]; for (int i = 0; i < n; i++) tempN[i] = solution->numberUnsatisfied[i]; delete [] solution->numberUnsatisfied; solution->numberUnsatisfied = tempN; } assert (numberColumns_ == solution->numberColumns); double * sol = new double [numberColumns_]; solution->solution[solution->numberSolutions] = sol; int numberFixed = 0; int numberUnsat = 0; int numberSat = 0; double sumUnsat = 0.0; double tolerance = 10.0 * primalTolerance_; double mostAway = 0.0; for (int i = 0; i < numberColumns_; i++) { // Save anyway sol[i] = columnScale_ ? solution_[i] * columnScale_[i] : solution_[i]; // rest is optional if (upper_[i] > lower_[i]) { double value = solution_[i]; if (value > lower_[i] + tolerance && value < upper_[i] - tolerance && integerType_[i]) { // may have to modify value if scaled if (columnScale_) value *= columnScale_[i]; double closest = floor(value + 0.5); // problem may be perturbed so relax test if (fabs(value - closest) > 1.0e-4) { numberUnsat++; sumUnsat += fabs(value - closest); if (mostAway < fabs(value - closest)) { mostAway = fabs(value - closest); } } else { numberSat++; } } else { numberSat++; } } else { numberFixed++; } } solution->numberUnsatisfied[solution->numberSolutions++] = numberUnsat; COIN_DETAIL_PRINT(printf("iteration %d, %d unsatisfied (%g,%g), %d fixed, %d satisfied\n", numberIterations_, numberUnsat, sumUnsat, mostAway, numberFixed, numberSat)); } } } if (hitMaximumIterations()) return 2; #if 1 //if (numberIterations_>14000) //handler_->setLogLevel(63); //if (numberIterations_>24000) //exit(77); // check for small cycles int in = sequenceIn_; int out = sequenceOut_; matrix_->correctSequence(this, in, out); int cycle = progress_.cycle(in, out, directionIn_, directionOut_); if (cycle > 0 && objective_->type() < 2 && matrix_->type() < 15) { //if (cycle>0) { if (handler_->logLevel() >= 63) printf("Cycle of %d\n", cycle); // reset progress_.startCheck(); double random = randomNumberGenerator_.randomDouble(); int extra = static_cast (9.999 * random); int off[] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 4}; if (factorization_->pivots() > cycle) { forceFactorization_ = CoinMax(1, cycle - off[extra]); } else { /* need to reject something should be better if don't reject incoming as it is in basis */ int iSequence; //if (algorithm_ > 0) // iSequence = sequenceIn_; //else iSequence = sequenceOut_; char x = isColumn(iSequence) ? 'C' : 'R'; if (handler_->logLevel() >= 63) handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(iSequence) << CoinMessageEol; setFlagged(iSequence); //printf("flagging %d\n",iSequence); } return 1; } #endif // only time to re-factorize if one before real time // this is so user won't be surprised that maximumPivots has exact meaning int numberPivots = factorization_->pivots(); int maximumPivots = factorization_->maximumPivots(); int numberDense = factorization_->numberDense(); bool dontInvert = ((specialOptions_ & 16384) != 0 && numberIterations_ * 3 > 2 * maximumIterations()); if (numberPivots == maximumPivots || maximumPivots < 2) { // If dense then increase if (maximumPivots > 100 && numberDense > 1.5 * maximumPivots) { factorization_->maximumPivots(numberDense); dualRowPivot_->maximumPivotsChanged(); primalColumnPivot_->maximumPivotsChanged(); // and redo arrays for (int iRow = 0; iRow < 4; iRow++) { int length = rowArray_[iRow]->capacity() + numberDense - maximumPivots; rowArray_[iRow]->reserve(length); } } return 1; } else if ((factorization_->timeToRefactorize() && !dontInvert) ||invertNow) { //printf("ret after %d pivots\n",factorization_->pivots()); return 1; } else if (forceFactorization_ > 0 && factorization_->pivots() == forceFactorization_) { // relax forceFactorization_ = (3 + 5 * forceFactorization_) / 4; if (forceFactorization_ > factorization_->maximumPivots()) forceFactorization_ = -1; //off return 1; } else if (numberIterations_ > 1000 + 10 * (numberRows_ + (numberColumns_ >> 2)) && matrix_->type()<15) { double random = randomNumberGenerator_.randomDouble(); int maxNumber = (forceFactorization_ < 0) ? maximumPivots : CoinMin(forceFactorization_, maximumPivots); if (factorization_->pivots() >= random * maxNumber) { return 1; } else if (numberIterations_ > 1000000 + 10 * (numberRows_ + (numberColumns_ >> 2)) && numberIterations_ < 1001000 + 10 * (numberRows_ + (numberColumns_ >> 2))) { return 1; } else { // carry on iterating return 0; } } else { // carry on iterating return 0; } } // Copy constructor. ClpSimplex::ClpSimplex(const ClpSimplex &rhs, int scalingMode) : ClpModel(rhs, scalingMode), bestPossibleImprovement_(0.0), zeroTolerance_(1.0e-13), columnPrimalSequence_(-2), rowPrimalSequence_(-2), bestObjectiveValue_(rhs.bestObjectiveValue_), moreSpecialOptions_(2), baseIteration_(0), primalToleranceToGetOptimal_(-1.0), largeValue_(1.0e15), largestPrimalError_(0.0), largestDualError_(0.0), alphaAccuracy_(-1.0), dualBound_(1.0e10), alpha_(0.0), theta_(0.0), lowerIn_(0.0), valueIn_(0.0), upperIn_(-COIN_DBL_MAX), dualIn_(0.0), lowerOut_(-1), valueOut_(-1), upperOut_(-1), dualOut_(-1), dualTolerance_(1.0e-7), primalTolerance_(1.0e-7), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), infeasibilityCost_(1.0e10), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), acceptablePivot_(1.0e-8), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rowObjectiveWork_(NULL), objectiveWork_(NULL), sequenceIn_(-1), directionIn_(-1), sequenceOut_(-1), directionOut_(-1), pivotRow_(-1), lastGoodIteration_(-100), dj_(NULL), rowReducedCost_(NULL), reducedCostWork_(NULL), solution_(NULL), rowActivityWork_(NULL), columnActivityWork_(NULL), numberDualInfeasibilities_(0), numberDualInfeasibilitiesWithoutFree_(0), numberPrimalInfeasibilities_(100), numberRefinements_(0), pivotVariable_(NULL), factorization_(NULL), savedSolution_(NULL), numberTimesOptimal_(0), disasterArea_(NULL), changeMade_(1), algorithm_(0), forceFactorization_(-1), perturbation_(100), nonLinearCost_(NULL), lastBadIteration_(-999999), lastFlaggedIteration_(-999999), numberFake_(0), numberChanged_(0), progressFlag_(0), firstFree_(-1), numberExtraRows_(0), maximumBasic_(0), dontFactorizePivots_(0), incomingInfeasibility_(1.0), allowedInfeasibility_(10.0), automaticScale_(0), maximumPerturbationSize_(0), perturbationArray_(NULL), baseModel_(NULL) #ifdef ABC_INHERIT ,abcSimplex_(NULL), abcState_(0) #endif { int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } for (i = 0; i < 4; i++) { spareIntArray_[i] = 0; spareDoubleArray_[i] = 0.0; } saveStatus_ = NULL; factorization_ = NULL; dualRowPivot_ = NULL; primalColumnPivot_ = NULL; gutsOfDelete(0); delete nonLinearCost_; nonLinearCost_ = NULL; gutsOfCopy(rhs); solveType_ = 1; // say simplex based life form } // Copy constructor from model ClpSimplex::ClpSimplex(const ClpModel &rhs, int scalingMode) : ClpModel(rhs, scalingMode), bestPossibleImprovement_(0.0), zeroTolerance_(1.0e-13), columnPrimalSequence_(-2), rowPrimalSequence_(-2), bestObjectiveValue_(-COIN_DBL_MAX), moreSpecialOptions_(2), baseIteration_(0), primalToleranceToGetOptimal_(-1.0), largeValue_(1.0e15), largestPrimalError_(0.0), largestDualError_(0.0), alphaAccuracy_(-1.0), dualBound_(1.0e10), alpha_(0.0), theta_(0.0), lowerIn_(0.0), valueIn_(0.0), upperIn_(-COIN_DBL_MAX), dualIn_(0.0), lowerOut_(-1), valueOut_(-1), upperOut_(-1), dualOut_(-1), dualTolerance_(1.0e-7), primalTolerance_(1.0e-7), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), infeasibilityCost_(1.0e10), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), acceptablePivot_(1.0e-8), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rowObjectiveWork_(NULL), objectiveWork_(NULL), sequenceIn_(-1), directionIn_(-1), sequenceOut_(-1), directionOut_(-1), pivotRow_(-1), lastGoodIteration_(-100), dj_(NULL), rowReducedCost_(NULL), reducedCostWork_(NULL), solution_(NULL), rowActivityWork_(NULL), columnActivityWork_(NULL), numberDualInfeasibilities_(0), numberDualInfeasibilitiesWithoutFree_(0), numberPrimalInfeasibilities_(100), numberRefinements_(0), pivotVariable_(NULL), factorization_(NULL), savedSolution_(NULL), numberTimesOptimal_(0), disasterArea_(NULL), changeMade_(1), algorithm_(0), forceFactorization_(-1), perturbation_(100), nonLinearCost_(NULL), lastBadIteration_(-999999), lastFlaggedIteration_(-999999), numberFake_(0), numberChanged_(0), progressFlag_(0), firstFree_(-1), numberExtraRows_(0), maximumBasic_(0), dontFactorizePivots_(0), incomingInfeasibility_(1.0), allowedInfeasibility_(10.0), automaticScale_(0), maximumPerturbationSize_(0), perturbationArray_(NULL), baseModel_(NULL) #ifdef ABC_INHERIT ,abcSimplex_(NULL), abcState_(0) #endif { int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } for (i = 0; i < 4; i++) { spareIntArray_[i] = 0; spareDoubleArray_[i] = 0.0; } saveStatus_ = NULL; // get an empty factorization so we can set tolerances etc getEmptyFactorization(); // say Steepest pricing dualRowPivot_ = new ClpDualRowSteepest(); // say Steepest pricing primalColumnPivot_ = new ClpPrimalColumnSteepest(); solveType_ = 1; // say simplex based life form } // Assignment operator. This copies the data ClpSimplex & ClpSimplex::operator=(const ClpSimplex & rhs) { if (this != &rhs) { gutsOfDelete(0); delete nonLinearCost_; nonLinearCost_ = NULL; ClpModel::operator=(rhs); gutsOfCopy(rhs); } return *this; } void ClpSimplex::gutsOfCopy(const ClpSimplex & rhs) { assert (numberRows_ == rhs.numberRows_); assert (numberColumns_ == rhs.numberColumns_); numberExtraRows_ = rhs.numberExtraRows_; maximumBasic_ = rhs.maximumBasic_; dontFactorizePivots_ = rhs.dontFactorizePivots_; int numberRows2 = numberRows_ + numberExtraRows_; moreSpecialOptions_ = rhs.moreSpecialOptions_; if ((whatsChanged_ & 1) != 0) { int numberTotal = numberColumns_ + numberRows2; if ((specialOptions_ & 65536) != 0 && maximumRows_ >= 0) { assert (maximumInternalRows_ >= numberRows2); assert (maximumInternalColumns_ >= numberColumns_); numberTotal = 2 * (maximumInternalColumns_ + maximumInternalRows_); } lower_ = ClpCopyOfArray(rhs.lower_, numberTotal); rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; upper_ = ClpCopyOfArray(rhs.upper_, numberTotal); rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; cost_ = ClpCopyOfArray(rhs.cost_, numberTotal); objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; dj_ = ClpCopyOfArray(rhs.dj_, numberTotal); if (dj_) { reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; } solution_ = ClpCopyOfArray(rhs.solution_, numberTotal); if (solution_) { columnActivityWork_ = solution_; rowActivityWork_ = solution_ + numberColumns_; } if (rhs.pivotVariable_) { pivotVariable_ = new int[numberRows2]; CoinMemcpyN ( rhs.pivotVariable_, numberRows2 , pivotVariable_); } else { pivotVariable_ = NULL; } savedSolution_ = ClpCopyOfArray(rhs.savedSolution_, numberTotal); int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; if (rhs.rowArray_[i]) rowArray_[i] = new CoinIndexedVector(*rhs.rowArray_[i]); columnArray_[i] = NULL; if (rhs.columnArray_[i]) columnArray_[i] = new CoinIndexedVector(*rhs.columnArray_[i]); } if (rhs.saveStatus_) { saveStatus_ = ClpCopyOfArray( rhs.saveStatus_, numberTotal); } } else { lower_ = NULL; rowLowerWork_ = NULL; columnLowerWork_ = NULL; upper_ = NULL; rowUpperWork_ = NULL; columnUpperWork_ = NULL; cost_ = NULL; objectiveWork_ = NULL; rowObjectiveWork_ = NULL; dj_ = NULL; reducedCostWork_ = NULL; rowReducedCost_ = NULL; solution_ = NULL; columnActivityWork_ = NULL; rowActivityWork_ = NULL; pivotVariable_ = NULL; savedSolution_ = NULL; int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } saveStatus_ = NULL; } if (rhs.factorization_) { setFactorization(*rhs.factorization_); } else { delete factorization_; factorization_ = NULL; } bestPossibleImprovement_ = rhs.bestPossibleImprovement_; columnPrimalSequence_ = rhs.columnPrimalSequence_; zeroTolerance_ = rhs.zeroTolerance_; rowPrimalSequence_ = rhs.rowPrimalSequence_; bestObjectiveValue_ = rhs.bestObjectiveValue_; baseIteration_ = rhs.baseIteration_; primalToleranceToGetOptimal_ = rhs.primalToleranceToGetOptimal_; largeValue_ = rhs.largeValue_; largestPrimalError_ = rhs.largestPrimalError_; largestDualError_ = rhs.largestDualError_; alphaAccuracy_ = rhs.alphaAccuracy_; dualBound_ = rhs.dualBound_; alpha_ = rhs.alpha_; theta_ = rhs.theta_; lowerIn_ = rhs.lowerIn_; valueIn_ = rhs.valueIn_; upperIn_ = rhs.upperIn_; dualIn_ = rhs.dualIn_; sequenceIn_ = rhs.sequenceIn_; directionIn_ = rhs.directionIn_; lowerOut_ = rhs.lowerOut_; valueOut_ = rhs.valueOut_; upperOut_ = rhs.upperOut_; dualOut_ = rhs.dualOut_; sequenceOut_ = rhs.sequenceOut_; directionOut_ = rhs.directionOut_; pivotRow_ = rhs.pivotRow_; lastGoodIteration_ = rhs.lastGoodIteration_; numberRefinements_ = rhs.numberRefinements_; dualTolerance_ = rhs.dualTolerance_; primalTolerance_ = rhs.primalTolerance_; sumDualInfeasibilities_ = rhs.sumDualInfeasibilities_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberDualInfeasibilitiesWithoutFree_ = rhs.numberDualInfeasibilitiesWithoutFree_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; dualRowPivot_ = rhs.dualRowPivot_->clone(true); dualRowPivot_->setModel(this); primalColumnPivot_ = rhs.primalColumnPivot_->clone(true); primalColumnPivot_->setModel(this); numberTimesOptimal_ = rhs.numberTimesOptimal_; disasterArea_ = NULL; changeMade_ = rhs.changeMade_; algorithm_ = rhs.algorithm_; forceFactorization_ = rhs.forceFactorization_; perturbation_ = rhs.perturbation_; infeasibilityCost_ = rhs.infeasibilityCost_; lastBadIteration_ = rhs.lastBadIteration_; lastFlaggedIteration_ = rhs.lastFlaggedIteration_; numberFake_ = rhs.numberFake_; numberChanged_ = rhs.numberChanged_; progressFlag_ = rhs.progressFlag_; firstFree_ = rhs.firstFree_; incomingInfeasibility_ = rhs.incomingInfeasibility_; allowedInfeasibility_ = rhs.allowedInfeasibility_; automaticScale_ = rhs.automaticScale_; #ifdef ABC_INHERIT abcSimplex_ = NULL; abcState_ = rhs.abcState_; #endif maximumPerturbationSize_ = rhs.maximumPerturbationSize_; if (maximumPerturbationSize_ && maximumPerturbationSize_ >= 2 * numberColumns_) { perturbationArray_ = CoinCopyOfArray(rhs.perturbationArray_, maximumPerturbationSize_); } else { maximumPerturbationSize_ = 0; perturbationArray_ = NULL; } if (rhs.baseModel_) { baseModel_ = new ClpSimplex(*rhs.baseModel_); } else { baseModel_ = NULL; } progress_ = rhs.progress_; for (int i = 0; i < 4; i++) { spareIntArray_[i] = rhs.spareIntArray_[i]; spareDoubleArray_[i] = rhs.spareDoubleArray_[i]; } sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; acceptablePivot_ = rhs.acceptablePivot_; if (rhs.nonLinearCost_ != NULL) nonLinearCost_ = new ClpNonLinearCost(*rhs.nonLinearCost_); else nonLinearCost_ = NULL; solveType_ = rhs.solveType_; } // type == 0 do everything, most + pivot data, 2 factorization data as well void ClpSimplex::gutsOfDelete(int type) { if (!type || (specialOptions_ & 65536) == 0) { maximumInternalColumns_ = -1; maximumInternalRows_ = -1; delete [] lower_; lower_ = NULL; rowLowerWork_ = NULL; columnLowerWork_ = NULL; delete [] upper_; upper_ = NULL; rowUpperWork_ = NULL; columnUpperWork_ = NULL; delete [] cost_; cost_ = NULL; objectiveWork_ = NULL; rowObjectiveWork_ = NULL; delete [] dj_; dj_ = NULL; reducedCostWork_ = NULL; rowReducedCost_ = NULL; delete [] solution_; solution_ = NULL; rowActivityWork_ = NULL; columnActivityWork_ = NULL; delete [] savedSolution_; savedSolution_ = NULL; } if ((specialOptions_ & 2) == 0) { delete nonLinearCost_; nonLinearCost_ = NULL; } int i; if ((specialOptions_ & 65536) == 0) { for (i = 0; i < 6; i++) { delete rowArray_[i]; rowArray_[i] = NULL; delete columnArray_[i]; columnArray_[i] = NULL; } } delete [] saveStatus_; saveStatus_ = NULL; if (type != 1) { delete rowCopy_; rowCopy_ = NULL; } if (!type) { // delete everything setEmptyFactorization(); delete [] pivotVariable_; pivotVariable_ = NULL; delete dualRowPivot_; dualRowPivot_ = NULL; delete primalColumnPivot_; primalColumnPivot_ = NULL; delete baseModel_; baseModel_ = NULL; delete [] perturbationArray_; perturbationArray_ = NULL; maximumPerturbationSize_ = 0; } else { // delete any size information in methods if (type > 1) { //assert (factorization_); if (factorization_) factorization_->clearArrays(); delete [] pivotVariable_; pivotVariable_ = NULL; } dualRowPivot_->clearArrays(); primalColumnPivot_->clearArrays(); } } // This sets largest infeasibility and most infeasible void ClpSimplex::checkPrimalSolution(const double * rowActivities, const double * columnActivities) { double * solution; int iRow, iColumn; objectiveValue_ = 0.0; // now look at primal solution solution = rowActivityWork_; sumPrimalInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; double primalTolerance = primalTolerance_; double relaxedTolerance = primalTolerance_; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, largestPrimalError_); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; sumOfRelaxedPrimalInfeasibilities_ = 0.0; for (iRow = 0; iRow < numberRows_; iRow++) { //assert (fabs(solution[iRow])<1.0e15||getRowStatus(iRow) == basic); double infeasibility = 0.0; objectiveValue_ += solution[iRow] * rowObjectiveWork_[iRow]; if (solution[iRow] > rowUpperWork_[iRow]) { infeasibility = solution[iRow] - rowUpperWork_[iRow]; } else if (solution[iRow] < rowLowerWork_[iRow]) { infeasibility = rowLowerWork_[iRow] - solution[iRow]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_ ++; } infeasibility = fabs(rowActivities[iRow] - solution[iRow]); } // Check any infeasibilities from dynamic rows matrix_->primalExpanded(this, 2); solution = columnActivityWork_; if (!matrix_->rhsOffset(this)) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { //assert (fabs(solution[iColumn])<1.0e15||getColumnStatus(iColumn) == basic); double infeasibility = 0.0; objectiveValue_ += objectiveWork_[iColumn] * solution[iColumn]; if (solution[iColumn] > columnUpperWork_[iColumn]) { infeasibility = solution[iColumn] - columnUpperWork_[iColumn]; } else if (solution[iColumn] < columnLowerWork_[iColumn]) { infeasibility = columnLowerWork_[iColumn] - solution[iColumn]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_ ++; } infeasibility = fabs(columnActivities[iColumn] - solution[iColumn]); } } else { // as we are using effective rhs we only check basics // But we do need to get objective objectiveValue_ += innerProduct(objectiveWork_, numberColumns_, solution); for (int j = 0; j < numberRows_; j++) { int iColumn = pivotVariable_[j]; //assert (fabs(solution[iColumn])<1.0e15||getColumnStatus(iColumn) == basic); double infeasibility = 0.0; if (solution[iColumn] > columnUpperWork_[iColumn]) { infeasibility = solution[iColumn] - columnUpperWork_[iColumn]; } else if (solution[iColumn] < columnLowerWork_[iColumn]) { infeasibility = columnLowerWork_[iColumn] - solution[iColumn]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_ ++; } infeasibility = fabs(columnActivities[iColumn] - solution[iColumn]); } } objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); } void ClpSimplex::checkDualSolution() { int iRow, iColumn; sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; numberDualInfeasibilitiesWithoutFree_ = 0; if (matrix_->skipDualCheck() && algorithm_ > 0 && problemStatus_ == -2) { // pretend we found dual infeasibilities sumOfRelaxedDualInfeasibilities_ = 1.0; sumDualInfeasibilities_ = 1.0; numberDualInfeasibilities_ = 1; return; } int firstFreePrimal = -1; int firstFreeDual = -1; int numberSuperBasicWithDj = 0; bestPossibleImprovement_ = 0.0; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, largestDualError_); // allow tolerance at least slightly bigger than standard double relaxedTolerance = dualTolerance_ + error; // allow bigger tolerance for possible improvement double possTolerance = 5.0 * relaxedTolerance; sumOfRelaxedDualInfeasibilities_ = 0.0; // Check any djs from dynamic rows matrix_->dualExpanded(this, NULL, NULL, 3); numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_; objectiveValue_ = 0.0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { objectiveValue_ += objectiveWork_[iColumn] * columnActivityWork_[iColumn]; if (getColumnStatus(iColumn) != basic && !flagged(iColumn)) { // not basic double distanceUp = columnUpperWork_[iColumn] - columnActivityWork_[iColumn]; double distanceDown = columnActivityWork_[iColumn] - columnLowerWork_[iColumn]; if (distanceUp > primalTolerance_) { double value = reducedCostWork_[iColumn]; // Check if "free" if (distanceDown > primalTolerance_) { if (fabs(value) > 1.0e2 * relaxedTolerance) { numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iColumn; } if (firstFreePrimal < 0) firstFreePrimal = iColumn; } // should not be negative if (value < 0.0) { value = - value; if (value > dualTolerance_) { if (getColumnStatus(iColumn) != isFree) { numberDualInfeasibilitiesWithoutFree_ ++; sumDualInfeasibilities_ += value - dualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } else { // free so relax a lot value *= 0.01; if (value > dualTolerance_) { sumDualInfeasibilities_ += value - dualTolerance_; if (value > possTolerance) bestPossibleImprovement_ = 1.0e100; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } } } } if (distanceDown > primalTolerance_) { double value = reducedCostWork_[iColumn]; // should not be positive if (value > 0.0) { if (value > dualTolerance_) { sumDualInfeasibilities_ += value - dualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; if (getColumnStatus(iColumn) != isFree) numberDualInfeasibilitiesWithoutFree_ ++; // maybe we can make feasible by increasing tolerance } } } } } for (iRow = 0; iRow < numberRows_; iRow++) { objectiveValue_ += rowActivityWork_[iRow] * rowObjectiveWork_[iRow]; if (getRowStatus(iRow) != basic && !flagged(iRow + numberColumns_)) { // not basic double distanceUp = rowUpperWork_[iRow] - rowActivityWork_[iRow]; double distanceDown = rowActivityWork_[iRow] - rowLowerWork_[iRow]; if (distanceUp > primalTolerance_) { double value = rowReducedCost_[iRow]; // Check if "free" if (distanceDown > primalTolerance_) { if (fabs(value) > 1.0e2 * relaxedTolerance) { numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iRow + numberColumns_; } if (firstFreePrimal < 0) firstFreePrimal = iRow + numberColumns_; } // should not be negative if (value < 0.0) { value = - value; if (value > dualTolerance_) { sumDualInfeasibilities_ += value - dualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceUp, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; if (getRowStatus(iRow) != isFree) numberDualInfeasibilitiesWithoutFree_ ++; } } } if (distanceDown > primalTolerance_) { double value = rowReducedCost_[iRow]; // should not be positive if (value > 0.0) { if (value > dualTolerance_) { sumDualInfeasibilities_ += value - dualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; if (getRowStatus(iRow) != isFree) numberDualInfeasibilitiesWithoutFree_ ++; // maybe we can make feasible by increasing tolerance } } } } } if (algorithm_ < 0 && firstFreeDual >= 0) { // dual firstFree_ = firstFreeDual; } else if (numberSuperBasicWithDj || (progress_.lastIterationNumber(0) <= 0)) { firstFree_ = firstFreePrimal; } objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); } /* This sets sum and number of infeasibilities (Dual and Primal) */ void ClpSimplex::checkBothSolutions() { if ((matrix_->skipDualCheck() && algorithm_ > 0 && problemStatus_ == -2) || matrix_->rhsOffset(this)) { // Say may be free or superbasic moreSpecialOptions_ &= ~8; // old way checkPrimalSolution(rowActivityWork_, columnActivityWork_); checkDualSolution(); return; } int iSequence; assert (dualTolerance_ > 0.0 && dualTolerance_ < 1.0e10); assert (primalTolerance_ > 0.0 && primalTolerance_ < 1.0e10); objectiveValue_ = 0.0; sumPrimalInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; double primalTolerance = primalTolerance_; double relaxedToleranceP = primalTolerance_; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, largestPrimalError_); // allow tolerance at least slightly bigger than standard relaxedToleranceP = relaxedToleranceP + error; sumOfRelaxedPrimalInfeasibilities_ = 0.0; sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; double dualTolerance = dualTolerance_; double relaxedToleranceD = dualTolerance; // we can't really trust infeasibilities if there is dual error error = CoinMin(1.0e-2, largestDualError_); // allow tolerance at least slightly bigger than standard relaxedToleranceD = relaxedToleranceD + error; // allow bigger tolerance for possible improvement double possTolerance = 5.0 * relaxedToleranceD; sumOfRelaxedDualInfeasibilities_ = 0.0; bestPossibleImprovement_ = 0.0; // Check any infeasibilities from dynamic rows matrix_->primalExpanded(this, 2); // Check any djs from dynamic rows matrix_->dualExpanded(this, NULL, NULL, 3); int numberDualInfeasibilitiesFree = 0; int firstFreePrimal = -1; int firstFreeDual = -1; int numberSuperBasicWithDj = 0; int numberTotal = numberRows_ + numberColumns_; // Say no free or superbasic moreSpecialOptions_ |= 8; //#define PRINT_INFEAS #ifdef PRINT_INFEAS int seqInf[10]; #endif for (iSequence = 0; iSequence < numberTotal; iSequence++) { double value = solution_[iSequence]; #ifdef COIN_DEBUG if (fabs(value) > 1.0e20) printf("%d values %g %g %g - status %d\n", iSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], status_[iSequence]); #endif objectiveValue_ += value * cost_[iSequence]; double distanceUp = upper_[iSequence] - value; double distanceDown = value - lower_[iSequence]; if (distanceUp < -primalTolerance) { double infeasibility = -distanceUp; sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedToleranceP) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedToleranceP; #ifdef PRINT_INFEAS if (numberPrimalInfeasibilities_<10) { seqInf[numberPrimalInfeasibilities_]=iSequence; } #endif numberPrimalInfeasibilities_ ++; } else if (distanceDown < -primalTolerance) { double infeasibility = -distanceDown; sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedToleranceP) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedToleranceP; #ifdef PRINT_INFEAS if (numberPrimalInfeasibilities_<10) { seqInf[numberPrimalInfeasibilities_]=iSequence; } #endif numberPrimalInfeasibilities_ ++; } else { // feasible (so could be free) if (getStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double djValue = dj_[iSequence]; if (distanceDown < primalTolerance) { if (distanceUp > primalTolerance && djValue < -dualTolerance) { sumDualInfeasibilities_ -= djValue + dualTolerance; if (djValue < -possTolerance) bestPossibleImprovement_ -= distanceUp * djValue; if (djValue < -relaxedToleranceD) sumOfRelaxedDualInfeasibilities_ -= djValue + relaxedToleranceD; numberDualInfeasibilities_ ++; } } else if (distanceUp < primalTolerance) { if (djValue > dualTolerance) { sumDualInfeasibilities_ += djValue - dualTolerance; if (djValue > possTolerance) bestPossibleImprovement_ += distanceDown * djValue; if (djValue > relaxedToleranceD) sumOfRelaxedDualInfeasibilities_ += djValue - relaxedToleranceD; numberDualInfeasibilities_ ++; } } else { // may be free // Say free or superbasic moreSpecialOptions_ &= ~8; djValue *= 0.01; if (fabs(djValue) > dualTolerance) { if (getStatus(iSequence) == isFree) numberDualInfeasibilitiesFree++; sumDualInfeasibilities_ += fabs(djValue) - dualTolerance; bestPossibleImprovement_ = 1.0e100; numberDualInfeasibilities_ ++; if (fabs(djValue) > relaxedToleranceD) { sumOfRelaxedDualInfeasibilities_ += value - relaxedToleranceD; numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; } } if (firstFreePrimal < 0) firstFreePrimal = iSequence; } } } } objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_ - numberDualInfeasibilitiesFree; #ifdef PRINT_INFEAS if (numberPrimalInfeasibilities_<=10) { printf("---------------start-----------\n"); if (!rowScale_) { for (int i=0;i= 0) { // dual firstFree_ = firstFreeDual; } else if (numberSuperBasicWithDj || (progress_.lastIterationNumber(0) <= 0)) { firstFree_ = firstFreePrimal; } } /* Adds multiple of a column into an array */ void ClpSimplex::add(double * array, int sequence, double multiplier) const { if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) { //slack array [sequence-numberColumns_] -= multiplier; } else { // column matrix_->add(this, array, sequence, multiplier); } } /* Unpacks one column of the matrix into indexed array */ void ClpSimplex::unpack(CoinIndexedVector * rowArray) const { rowArray->clear(); if (sequenceIn_ >= numberColumns_ && sequenceIn_ < numberColumns_ + numberRows_) { //slack rowArray->insert(sequenceIn_ - numberColumns_, -1.0); } else { // column matrix_->unpack(this, rowArray, sequenceIn_); } } void ClpSimplex::unpack(CoinIndexedVector * rowArray, int sequence) const { rowArray->clear(); if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) { //slack rowArray->insert(sequence - numberColumns_, -1.0); } else { // column matrix_->unpack(this, rowArray, sequence); } } /* Unpacks one column of the matrix into indexed array */ void ClpSimplex::unpackPacked(CoinIndexedVector * rowArray) { rowArray->clear(); if (sequenceIn_ >= numberColumns_ && sequenceIn_ < numberColumns_ + numberRows_) { //slack int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); array[0] = -1.0; index[0] = sequenceIn_ - numberColumns_; rowArray->setNumElements(1); rowArray->setPackedMode(true); } else { // column matrix_->unpackPacked(this, rowArray, sequenceIn_); } } void ClpSimplex::unpackPacked(CoinIndexedVector * rowArray, int sequence) { rowArray->clear(); if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) { //slack int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); array[0] = -1.0; index[0] = sequence - numberColumns_; rowArray->setNumElements(1); rowArray->setPackedMode(true); } else { // column matrix_->unpackPacked(this, rowArray, sequence); } } //static int x_gaps[4]={0,0,0,0}; //static int scale_times[]={0,0,0,0}; bool ClpSimplex::createRim(int what, bool makeRowCopy, int startFinishOptions) { bool goodMatrix = true; int saveLevel = handler_->logLevel(); spareIntArray_[0] = 0; if (!matrix_->canGetRowCopy()) makeRowCopy = false; // switch off row copy if can't produce // Arrays will be there and correct size unless what is 63 bool newArrays = (what == 63); // We may be restarting with same size bool keepPivots = false; if (startFinishOptions == -1) { startFinishOptions = 0; keepPivots = true; } bool oldMatrix = ((startFinishOptions & 4) != 0 && (whatsChanged_ & 1) != 0); if (what == 63) { pivotRow_ = -1; if (!status_) createStatus(); if (oldMatrix) newArrays = false; if (problemStatus_ == 10) { handler_->setLogLevel(0); // switch off messages if (rowArray_[0]) { // stuff is still there oldMatrix = true; newArrays = false; keepPivots = true; for (int iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (int iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } } } else if (factorization_) { // match up factorization messages if (handler_->logLevel() < 3) factorization_->messageLevel(0); else factorization_->messageLevel(CoinMax(3, factorization_->messageLevel())); /* Faster to keep pivots rather than re-scan matrix. Matrix may have changed i.e. oldMatrix false but okay as long as same number rows and status array exists */ if ((startFinishOptions & 2) != 0 && factorization_->numberRows() == numberRows_ && status_) keepPivots = true; } numberExtraRows_ = matrix_->generalExpanded(this, 2, maximumBasic_); if (numberExtraRows_ && newArrays) { // make sure status array large enough assert (status_); int numberOld = numberRows_ + numberColumns_; int numberNew = numberRows_ + numberColumns_ + numberExtraRows_; unsigned char * newStatus = new unsigned char [numberNew]; memset(newStatus + numberOld, 0, numberExtraRows_); CoinMemcpyN(status_, numberOld, newStatus); delete [] status_; status_ = newStatus; } } int numberRows2 = numberRows_ + numberExtraRows_; int numberTotal = numberRows2 + numberColumns_; if ((specialOptions_ & 65536) != 0) { assert (!numberExtraRows_); if (!cost_ || numberRows2 > maximumInternalRows_ || numberColumns_ > maximumInternalColumns_) { newArrays = true; keepPivots = false; COIN_DETAIL_PRINT(printf("createrim a %d rows, %d maximum rows %d maxinternal\n", numberRows_, maximumRows_, maximumInternalRows_)); int oldMaximumRows = maximumInternalRows_; int oldMaximumColumns = maximumInternalColumns_; if (cost_) { if (numberRows2 > maximumInternalRows_) maximumInternalRows_ = numberRows2; if (numberColumns_ > maximumInternalColumns_) maximumInternalColumns_ = numberColumns_; } else { maximumInternalRows_ = numberRows2; maximumInternalColumns_ = numberColumns_; } //maximumRows_=CoinMax(maximumInternalRows_,maximumRows_); //maximumColumns_=CoinMax(maximumInternalColumns_,maximumColumns_); assert(maximumInternalRows_ == maximumRows_); assert(maximumInternalColumns_ == maximumColumns_); COIN_DETAIL_PRINT(printf("createrim b %d rows, %d maximum rows, %d maxinternal\n", numberRows_, maximumRows_, maximumInternalRows_)); int numberTotal2 = (maximumInternalRows_ + maximumInternalColumns_) * 2; delete [] cost_; cost_ = new double[numberTotal2]; delete [] lower_; delete [] upper_; lower_ = new double[numberTotal2]; upper_ = new double[numberTotal2]; delete [] dj_; dj_ = new double[numberTotal2]; delete [] solution_; solution_ = new double[numberTotal2]; // ***** should be non NULL but seems to be too much //printf("resize %d savedRowScale %x\n",maximumRows_,savedRowScale_); if (savedRowScale_) { assert (oldMaximumRows > 0); double * temp; temp = new double [4*maximumRows_]; CoinFillN(temp, 4 * maximumRows_, 1.0); CoinMemcpyN(savedRowScale_, numberRows_, temp); CoinMemcpyN(savedRowScale_ + oldMaximumRows, numberRows_, temp + maximumRows_); CoinMemcpyN(savedRowScale_ + 2 * oldMaximumRows, numberRows_, temp + 2 * maximumRows_); CoinMemcpyN(savedRowScale_ + 3 * oldMaximumRows, numberRows_, temp + 3 * maximumRows_); delete [] savedRowScale_; savedRowScale_ = temp; temp = new double [4*maximumColumns_]; CoinFillN(temp, 4 * maximumColumns_, 1.0); CoinMemcpyN(savedColumnScale_, numberColumns_, temp); CoinMemcpyN(savedColumnScale_ + oldMaximumColumns, numberColumns_, temp + maximumColumns_); CoinMemcpyN(savedColumnScale_ + 2 * oldMaximumColumns, numberColumns_, temp + 2 * maximumColumns_); CoinMemcpyN(savedColumnScale_ + 3 * oldMaximumColumns, numberColumns_, temp + 3 * maximumColumns_); delete [] savedColumnScale_; savedColumnScale_ = temp; } } } int i; bool doSanityCheck = true; if (what == 63) { // We may want to switch stuff off for speed if ((specialOptions_ & 256) != 0) makeRowCopy = false; // no row copy if ((specialOptions_ & 128) != 0) doSanityCheck = false; // no sanity check //check matrix if (!matrix_) matrix_ = new ClpPackedMatrix(); int checkType = (doSanityCheck) ? 15 : 14; if (oldMatrix) checkType = 14; bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; if (inCbcOrOther) checkType -= 4; // don't check for duplicates if (!matrix_->allElementsInRange(this, smallElement_, 1.0e20, checkType)) { problemStatus_ = 4; secondaryStatus_ = 8; //goodMatrix= false; return false; } bool rowCopyIsScaled; if (makeRowCopy) { if(!oldMatrix || !rowCopy_) { delete rowCopy_; // may return NULL if can't give row copy rowCopy_ = matrix_->reverseOrderedCopy(); rowCopyIsScaled = false; } else { rowCopyIsScaled = true; } } #if 0 if (what == 63) { int k = rowScale_ ? 1 : 0; if (oldMatrix) k += 2; scale_times[k]++; if ((scale_times[0] + scale_times[1] + scale_times[2] + scale_times[3]) % 1000 == 0) printf("scale counts %d %d %d %d\n", scale_times[0], scale_times[1], scale_times[2], scale_times[3]); } #endif // do scaling if needed if (!oldMatrix && scalingFlag_ < 0) { if (scalingFlag_ < 0 && rowScale_) { //if (handler_->logLevel()>0) printf("How did we get scalingFlag_ %d and non NULL rowScale_? - switching off scaling\n", scalingFlag_); scalingFlag_ = 0; } delete [] rowScale_; delete [] columnScale_; rowScale_ = NULL; columnScale_ = NULL; } inverseRowScale_ = NULL; inverseColumnScale_ = NULL; if (scalingFlag_ > 0 &&(specialOptions_ & 65536) != 0&& rowScale_&&rowScale_==savedRowScale_) rowScale_=NULL; if (scalingFlag_ > 0 && !rowScale_) { if ((specialOptions_ & 65536) != 0) { assert (!rowScale_); rowScale_ = savedRowScale_; columnScale_ = savedColumnScale_; // put back original if (savedRowScale_) { inverseRowScale_ = savedRowScale_ + maximumInternalRows_; inverseColumnScale_ = savedColumnScale_ + maximumInternalColumns_; CoinMemcpyN(savedRowScale_ + 2 * maximumInternalRows_, numberRows2, savedRowScale_); CoinMemcpyN(savedRowScale_ + 3 * maximumInternalRows_, numberRows2, inverseRowScale_); CoinMemcpyN(savedColumnScale_ + 2 * maximumColumns_, numberColumns_, savedColumnScale_); CoinMemcpyN(savedColumnScale_ + 3 * maximumColumns_, numberColumns_, inverseColumnScale_); } } if (matrix_->scale(this)) scalingFlag_ = -scalingFlag_; // not scaled after all if (rowScale_ && automaticScale_) { if (!savedRowScale_) { inverseRowScale_ = rowScale_ + numberRows2; inverseColumnScale_ = columnScale_ + numberColumns_; } // try automatic scaling double smallestObj = 1.0e100; double largestObj = 0.0; double largestRhs = 0.0; const double * obj = objective(); for (i = 0; i < numberColumns_; i++) { double value = fabs(obj[i]); value *= columnScale_[i]; if (value && columnLower_[i] != columnUpper_[i]) { smallestObj = CoinMin(smallestObj, value); largestObj = CoinMax(largestObj, value); } if (columnLower_[i] > 0.0 || columnUpper_[i] < 0.0) { double scale = 1.0 * inverseColumnScale_[i]; //printf("%d %g %g %g %g\n",i,scale,lower_[i],upper_[i],largestRhs); if (columnLower_[i] > 0) largestRhs = CoinMax(largestRhs, columnLower_[i] * scale); if (columnUpper_[i] < 0.0) largestRhs = CoinMax(largestRhs, -columnUpper_[i] * scale); } } for (i = 0; i < numberRows_; i++) { if (rowLower_[i] > 0.0 || rowUpper_[i] < 0.0) { double scale = rowScale_[i]; //printf("%d %g %g %g %g\n",i,scale,lower_[i],upper_[i],largestRhs); if (rowLower_[i] > 0) largestRhs = CoinMax(largestRhs, rowLower_[i] * scale); if (rowUpper_[i] < 0.0) largestRhs = CoinMax(largestRhs, -rowUpper_[i] * scale); } } COIN_DETAIL_PRINT(printf("small obj %g, large %g - rhs %g\n", smallestObj, largestObj, largestRhs)); bool scalingDone = false; // look at element range double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive); largestPositive = CoinMax(fabs(largestNegative), largestPositive); if (largestObj) { double ratio = largestObj / smallestObj; double scale = 1.0; if (ratio < 1.0e8) { // reasonable if (smallestObj < 1.0e-4) { // may as well scale up scalingDone = true; scale = 1.0e-3 / smallestObj; } else if (largestObj < 1.0e6 || (algorithm_ > 0 && largestObj < 1.0e-4 * infeasibilityCost_)) { //done=true; } else { scalingDone = true; if (algorithm_ < 0) { scale = 1.0e6 / largestObj; } else { scale = CoinMax(1.0e6, 1.0e-4 * infeasibilityCost_) / largestObj; } } } else if (ratio < 1.0e12) { // not so good if (smallestObj < 1.0e-7) { // may as well scale up scalingDone = true; scale = 1.0e-6 / smallestObj; } else if (largestObj < 1.0e7 || (algorithm_ > 0 && largestObj < 1.0e-3 * infeasibilityCost_)) { //done=true; } else { scalingDone = true; if (algorithm_ < 0) { scale = 1.0e7 / largestObj; } else { scale = CoinMax(1.0e7, 1.0e-3 * infeasibilityCost_) / largestObj; } } } else { // Really nasty problem if (smallestObj < 1.0e-8) { // may as well scale up scalingDone = true; scale = 1.0e-7 / smallestObj; largestObj *= scale; } if (largestObj < 1.0e7 || (algorithm_ > 0 && largestObj < 1.0e-3 * infeasibilityCost_)) { //done=true; } else { scalingDone = true; if (algorithm_ < 0) { scale = 1.0e7 / largestObj; } else { scale = CoinMax(1.0e7, 1.0e-3 * infeasibilityCost_) / largestObj; } } } objectiveScale_ = scale; } if (largestRhs > 1.0e12) { scalingDone = true; rhsScale_ = 1.0e9 / largestRhs; } else if (largestPositive > 1.0e-14 * smallestPositive && largestRhs > 1.0e6) { scalingDone = true; rhsScale_ = 1.0e6 / largestRhs; } else { rhsScale_ = 1.0; } if (scalingDone) { handler_->message(CLP_RIM_SCALE, messages_) << objectiveScale_ << rhsScale_ << CoinMessageEol; } } } else if (makeRowCopy && scalingFlag_ > 0 && !rowCopyIsScaled) { matrix_->scaleRowCopy(this); } if (rowScale_ && !savedRowScale_) { inverseRowScale_ = rowScale_ + numberRows2; inverseColumnScale_ = columnScale_ + numberColumns_; } // See if we can try for faster row copy if (makeRowCopy && !oldMatrix) { ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); if (clpMatrix && numberThreads_) clpMatrix->specialRowCopy(this, rowCopy_); if (clpMatrix) clpMatrix->specialColumnCopy(this); } } if (what == 63) { #if 0 { x_gaps[0]++; ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); if (clpMatrix) { if (!clpMatrix->getPackedMatrix()->hasGaps()) x_gaps[1]++; if ((clpMatrix->flags() & 2) == 0) x_gaps[3]++; } else { x_gaps[2]++; } if ((x_gaps[0] % 1000) == 0) printf("create %d times, no gaps %d times - not clp %d times - flagged %d\n", x_gaps[0], x_gaps[1], x_gaps[2], x_gaps[3]); } #endif if (newArrays && (specialOptions_ & 65536) == 0) { delete [] cost_; cost_ = new double[2*numberTotal]; delete [] lower_; delete [] upper_; lower_ = new double[numberTotal]; upper_ = new double[numberTotal]; delete [] dj_; dj_ = new double[numberTotal]; delete [] solution_; solution_ = new double[numberTotal]; } reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; columnActivityWork_ = solution_; rowActivityWork_ = solution_ + numberColumns_; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; } if ((what & 4) != 0) { double direction = optimizationDirection_ * objectiveScale_; const double * obj = objective(); const double * rowScale = rowScale_; const double * columnScale = columnScale_; // and also scale by scale factors if (rowScale) { if (rowObjective_) { for (i = 0; i < numberRows_; i++) rowObjectiveWork_[i] = rowObjective_[i] * direction / rowScale[i]; } else { memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double)); } // If scaled then do all columns later in one loop if (what != 63) { for (i = 0; i < numberColumns_; i++) { CoinAssert(fabs(obj[i]) < 1.0e25); objectiveWork_[i] = obj[i] * direction * columnScale[i]; } } } else { if (rowObjective_) { for (i = 0; i < numberRows_; i++) rowObjectiveWork_[i] = rowObjective_[i] * direction; } else { memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double)); } for (i = 0; i < numberColumns_; i++) { CoinAssert(fabs(obj[i]) < 1.0e25); objectiveWork_[i] = obj[i] * direction; } } } if ((what & 1) != 0) { const double * rowScale = rowScale_; // clean up any mismatches on infinity // and fix any variables with tiny gaps double primalTolerance = dblParam_[ClpPrimalTolerance]; if(rowScale) { // If scaled then do all columns later in one loop if (what != 63) { const double * inverseScale = inverseColumnScale_; for (i = 0; i < numberColumns_; i++) { double multiplier = rhsScale_ * inverseScale[i]; double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue * multiplier; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue * multiplier; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue * multiplier; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } } for (i = 0; i < numberRows_; i++) { double multiplier = rhsScale_ * rowScale[i]; double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue * multiplier; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue * multiplier; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue * multiplier; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } else if (rhsScale_ != 1.0) { for (i = 0; i < numberColumns_; i++) { double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue * rhsScale_; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue * rhsScale_; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue * rhsScale_; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } for (i = 0; i < numberRows_; i++) { double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue * rhsScale_; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue * rhsScale_; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue * rhsScale_; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } else { for (i = 0; i < numberColumns_; i++) { double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } for (i = 0; i < numberRows_; i++) { double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } } if (what == 63) { // move information to work arrays double direction = optimizationDirection_; // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; if (direction != 1.0) { // reverse all dual signs for (i = 0; i < numberColumns_; i++) reducedCost_[i] *= direction; for (i = 0; i < numberRows_; i++) dual_[i] *= direction; } for (i = 0; i < numberRows_ + numberColumns_; i++) { setFakeBound(i, noFake); } if (rowScale_) { const double * obj = objective(); double direction = optimizationDirection_ * objectiveScale_; // clean up any mismatches on infinity // and fix any variables with tiny gaps double primalTolerance = dblParam_[ClpPrimalTolerance]; // on entry const double * inverseScale = inverseColumnScale_; for (i = 0; i < numberColumns_; i++) { CoinAssert(fabs(obj[i]) < 1.0e25); double scaleFactor = columnScale_[i]; double multiplier = rhsScale_ * inverseScale[i]; scaleFactor *= direction; objectiveWork_[i] = obj[i] * scaleFactor; reducedCostWork_[i] = reducedCost_[i] * scaleFactor; double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue * multiplier; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue * multiplier; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue * multiplier; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } double value = columnActivity_[i] * multiplier; if (fabs(value) > 1.0e20) { //printf("bad value of %g for column %d\n",value,i); setColumnStatus(i, superBasic); if (columnUpperWork_[i] < 0.0) { value = columnUpperWork_[i]; } else if (columnLowerWork_[i] > 0.0) { value = columnLowerWork_[i]; } else { value = 0.0; } } columnActivityWork_[i] = value; } inverseScale = inverseRowScale_; for (i = 0; i < numberRows_; i++) { dual_[i] *= inverseScale[i]; dual_[i] *= objectiveScale_; rowReducedCost_[i] = dual_[i]; double multiplier = rhsScale_ * rowScale_[i]; double value = rowActivity_[i] * multiplier; if (fabs(value) > 1.0e20) { //printf("bad value of %g for row %d\n",value,i); setRowStatus(i, superBasic); if (rowUpperWork_[i] < 0.0) { value = rowUpperWork_[i]; } else if (rowLowerWork_[i] > 0.0) { value = rowLowerWork_[i]; } else { value = 0.0; } } rowActivityWork_[i] = value; } } else if (objectiveScale_ != 1.0 || rhsScale_ != 1.0) { // on entry for (i = 0; i < numberColumns_; i++) { double value = columnActivity_[i]; value *= rhsScale_; if (fabs(value) > 1.0e20) { //printf("bad value of %g for column %d\n",value,i); setColumnStatus(i, superBasic); if (columnUpperWork_[i] < 0.0) { value = columnUpperWork_[i]; } else if (columnLowerWork_[i] > 0.0) { value = columnLowerWork_[i]; } else { value = 0.0; } } columnActivityWork_[i] = value; reducedCostWork_[i] = reducedCost_[i] * objectiveScale_; } for (i = 0; i < numberRows_; i++) { double value = rowActivity_[i]; value *= rhsScale_; if (fabs(value) > 1.0e20) { //printf("bad value of %g for row %d\n",value,i); setRowStatus(i, superBasic); if (rowUpperWork_[i] < 0.0) { value = rowUpperWork_[i]; } else if (rowLowerWork_[i] > 0.0) { value = rowLowerWork_[i]; } else { value = 0.0; } } rowActivityWork_[i] = value; dual_[i] *= objectiveScale_; rowReducedCost_[i] = dual_[i]; } } else { // on entry for (i = 0; i < numberColumns_; i++) { double value = columnActivity_[i]; if (fabs(value) > 1.0e20) { //printf("bad value of %g for column %d\n",value,i); setColumnStatus(i, superBasic); if (columnUpperWork_[i] < 0.0) { value = columnUpperWork_[i]; } else if (columnLowerWork_[i] > 0.0) { value = columnLowerWork_[i]; } else { value = 0.0; } } columnActivityWork_[i] = value; reducedCostWork_[i] = reducedCost_[i]; } for (i = 0; i < numberRows_; i++) { double value = rowActivity_[i]; if (fabs(value) > 1.0e20) { //printf("bad value of %g for row %d\n",value,i); setRowStatus(i, superBasic); if (rowUpperWork_[i] < 0.0) { value = rowUpperWork_[i]; } else if (rowLowerWork_[i] > 0.0) { value = rowLowerWork_[i]; } else { value = 0.0; } } rowActivityWork_[i] = value; rowReducedCost_[i] = dual_[i]; } } } if (what == 63 && doSanityCheck) { // check rim of problem okay if (!sanityCheck()) goodMatrix = false; } // we need to treat matrix as if each element by rowScaleIn and columnScaleout?? // maybe we need to move scales to SimplexModel for factorization? if ((what == 63 && !pivotVariable_) || (newArrays && !keepPivots)) { delete [] pivotVariable_; pivotVariable_ = new int[numberRows2]; for (int i = 0; i < numberRows2; i++) pivotVariable_[i] = -1; } else if (what == 63 && !keepPivots) { // just reset for (int i = 0; i < numberRows2; i++) pivotVariable_[i] = -1; } else if (what == 63) { // check pivots for (int i = 0; i < numberRows2; i++) { int iSequence = pivotVariable_[i]; if (iSequence<0||(iSequence < numberRows_ + numberColumns_ && getStatus(iSequence) != basic)) { keepPivots = false; break; } } if (!keepPivots) { // reset for (int i = 0; i < numberRows2; i++) pivotVariable_[i] = -1; } else { // clean for (int i = 0; i < numberColumns_ + numberRows_; i++) { Status status = getStatus(i); if (status != basic) { if (upper_[i] == lower_[i]) { setStatus(i, isFixed); solution_[i] = lower_[i]; } else if (status == atLowerBound) { if (lower_[i] > -1.0e20) { solution_[i] = lower_[i]; } else { //printf("seq %d at lower of %g\n",i,lower_[i]); if (upper_[i] < 1.0e20) { solution_[i] = upper_[i]; setStatus(i, atUpperBound); } else { setStatus(i, isFree); } } } else if (status == atUpperBound) { if (upper_[i] < 1.0e20) { solution_[i] = upper_[i]; } else { //printf("seq %d at upper of %g\n",i,upper_[i]); if (lower_[i] > -1.0e20) { solution_[i] = lower_[i]; setStatus(i, atLowerBound); } else { setStatus(i, isFree); } } } else if (status == isFixed && upper_[i] > lower_[i]) { // was fixed - not now if (solution_[i] <= lower_[i]) { setStatus(i, atLowerBound); } else if (solution_[i] >= upper_[i]) { setStatus(i, atUpperBound); } else { setStatus(i, superBasic); } } } } } } if (what == 63) { if (newArrays) { // get some arrays int iRow, iColumn; // these are "indexed" arrays so we always know where nonzeros are /********************************************************** rowArray_[3] is long enough for rows+columns rowArray_[1] is long enough for max(rows,columns) *********************************************************/ for (iRow = 0; iRow < 4; iRow++) { int length = numberRows2 + factorization_->maximumPivots(); if (iRow == 3 || objective_->type() > 1) length += numberColumns_; else if (iRow == 1) length = CoinMax(length, numberColumns_); if ((specialOptions_ & 65536) == 0 || !rowArray_[iRow]) { delete rowArray_[iRow]; rowArray_[iRow] = new CoinIndexedVector(); } rowArray_[iRow]->reserve(length); } for (iColumn = 0; iColumn < 2; iColumn++) { if ((specialOptions_ & 65536) == 0 || !columnArray_[iColumn]) { delete columnArray_[iColumn]; columnArray_[iColumn] = new CoinIndexedVector(); } columnArray_[iColumn]->reserve(numberColumns_+numberRows2); } } else { int iRow, iColumn; for (iRow = 0; iRow < 4; iRow++) { int length = numberRows2 + factorization_->maximumPivots(); if (iRow == 3 || objective_->type() > 1) length += numberColumns_; if(rowArray_[iRow]->capacity() >= length) { rowArray_[iRow]->clear(); } else { // model size or maxinv changed rowArray_[iRow]->reserve(length); } #ifndef NDEBUG rowArray_[iRow]->checkClear(); #endif } for (iColumn = 0; iColumn < 2; iColumn++) { int length = numberColumns_; if (iColumn) length = CoinMax(numberRows2, numberColumns_); if(columnArray_[iColumn]->capacity() >= length) { columnArray_[iColumn]->clear(); } else { // model size or maxinv changed columnArray_[iColumn]->reserve(length); } #ifndef NDEBUG columnArray_[iColumn]->checkClear(); #endif } } } if (problemStatus_ == 10) { problemStatus_ = -1; handler_->setLogLevel(saveLevel); // switch back messages } if ((what & 5) != 0) matrix_->generalExpanded(this, 9, what); // update costs and bounds if necessary if (goodMatrix && (specialOptions_ & 65536) != 0) { int save = maximumColumns_ + maximumRows_; CoinMemcpyN(cost_, numberTotal, cost_ + save); CoinMemcpyN(lower_, numberTotal, lower_ + save); CoinMemcpyN(upper_, numberTotal, upper_ + save); CoinMemcpyN(dj_, numberTotal, dj_ + save); CoinMemcpyN(solution_, numberTotal, solution_ + save); if (rowScale_ && !savedRowScale_) { double * temp; temp = new double [4*maximumRows_]; CoinFillN(temp, 4 * maximumRows_, 1.0); CoinMemcpyN(rowScale_, numberRows2, temp); CoinMemcpyN(rowScale_ + numberRows2, numberRows2, temp + maximumRows_); CoinMemcpyN(rowScale_, numberRows2, temp + 2 * maximumRows_); CoinMemcpyN(rowScale_ + numberRows2, numberRows2, temp + 3 * maximumRows_); delete [] rowScale_; savedRowScale_ = temp; rowScale_ = savedRowScale_; inverseRowScale_ = savedRowScale_ + maximumInternalRows_; temp = new double [4*maximumColumns_]; CoinFillN(temp, 4 * maximumColumns_, 1.0); CoinMemcpyN(columnScale_, numberColumns_, temp); CoinMemcpyN(columnScale_ + numberColumns_, numberColumns_, temp + maximumColumns_); CoinMemcpyN(columnScale_, numberColumns_, temp + 2 * maximumColumns_); CoinMemcpyN(columnScale_ + numberColumns_, numberColumns_, temp + 3 * maximumColumns_); delete [] columnScale_; savedColumnScale_ = temp; columnScale_ = savedColumnScale_; inverseColumnScale_ = savedColumnScale_ + maximumInternalColumns_; } } #ifdef CLP_USER_DRIVEN eventHandler_->event(ClpEventHandler::endOfCreateRim); #endif return goodMatrix; } // Does rows and columns void ClpSimplex::createRim1(bool initial) { int i; int numberRows2 = numberRows_ + numberExtraRows_; int numberTotal = numberRows2 + numberColumns_; if ((specialOptions_ & 65536) != 0 && true) { assert (!initial); int save = maximumColumns_ + maximumRows_; CoinMemcpyN(lower_ + save, numberTotal, lower_); CoinMemcpyN(upper_ + save, numberTotal, upper_); return; } const double * rowScale = rowScale_; // clean up any mismatches on infinity // and fix any variables with tiny gaps double primalTolerance = dblParam_[ClpPrimalTolerance]; if(rowScale) { // If scaled then do all columns later in one loop if (!initial) { const double * inverseScale = inverseColumnScale_; for (i = 0; i < numberColumns_; i++) { double multiplier = rhsScale_ * inverseScale[i]; double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue * multiplier; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue * multiplier; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue * multiplier; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } } for (i = 0; i < numberRows_; i++) { double multiplier = rhsScale_ * rowScale[i]; double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue * multiplier; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue * multiplier; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue * multiplier; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } else if (rhsScale_ != 1.0) { for (i = 0; i < numberColumns_; i++) { double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue * rhsScale_; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue * rhsScale_; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue * rhsScale_; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } for (i = 0; i < numberRows_; i++) { double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue * rhsScale_; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue * rhsScale_; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue * rhsScale_; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } else { for (i = 0; i < numberColumns_; i++) { double lowerValue = columnLower_[i]; double upperValue = columnUpper_[i]; if (lowerValue > -1.0e20) { columnLowerWork_[i] = lowerValue; if (upperValue >= 1.0e20) { columnUpperWork_[i] = COIN_DBL_MAX; } else { columnUpperWork_[i] = upperValue; if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) { if (columnLowerWork_[i] >= 0.0) { columnUpperWork_[i] = columnLowerWork_[i]; } else if (columnUpperWork_[i] <= 0.0) { columnLowerWork_[i] = columnUpperWork_[i]; } else { columnUpperWork_[i] = 0.0; columnLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = upperValue; } else { // free columnLowerWork_[i] = -COIN_DBL_MAX; columnUpperWork_[i] = COIN_DBL_MAX; } } for (i = 0; i < numberRows_; i++) { double lowerValue = rowLower_[i]; double upperValue = rowUpper_[i]; if (lowerValue > -1.0e20) { rowLowerWork_[i] = lowerValue; if (upperValue >= 1.0e20) { rowUpperWork_[i] = COIN_DBL_MAX; } else { rowUpperWork_[i] = upperValue; if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) { if (rowLowerWork_[i] >= 0.0) { rowUpperWork_[i] = rowLowerWork_[i]; } else if (rowUpperWork_[i] <= 0.0) { rowLowerWork_[i] = rowUpperWork_[i]; } else { rowUpperWork_[i] = 0.0; rowLowerWork_[i] = 0.0; } } } } else if (upperValue < 1.0e20) { rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = upperValue; } else { // free rowLowerWork_[i] = -COIN_DBL_MAX; rowUpperWork_[i] = COIN_DBL_MAX; } } } #ifndef NDEBUG if ((specialOptions_ & 65536) != 0 && false) { assert (!initial); int save = maximumColumns_ + maximumRows_; for (int i = 0; i < numberTotal; i++) { assert (fabs(lower_[i] - lower_[i+save]) < 1.0e-5); assert (fabs(upper_[i] - upper_[i+save]) < 1.0e-5); } } #endif } // Does objective void ClpSimplex::createRim4(bool initial) { int i; int numberRows2 = numberRows_ + numberExtraRows_; int numberTotal = numberRows2 + numberColumns_; if ((specialOptions_ & 65536) != 0 && true) { assert (!initial); int save = maximumColumns_ + maximumRows_; CoinMemcpyN(cost_ + save, numberTotal, cost_); return; } double direction = optimizationDirection_ * objectiveScale_; const double * obj = objective(); const double * rowScale = rowScale_; const double * columnScale = columnScale_; // and also scale by scale factors if (rowScale) { if (rowObjective_) { for (i = 0; i < numberRows_; i++) rowObjectiveWork_[i] = rowObjective_[i] * direction / rowScale[i]; } else { memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double)); } // If scaled then do all columns later in one loop if (!initial) { for (i = 0; i < numberColumns_; i++) { CoinAssert(fabs(obj[i]) < 1.0e25); objectiveWork_[i] = obj[i] * direction * columnScale[i]; } } } else { if (rowObjective_) { for (i = 0; i < numberRows_; i++) rowObjectiveWork_[i] = rowObjective_[i] * direction; } else { memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double)); } for (i = 0; i < numberColumns_; i++) { CoinAssert(fabs(obj[i]) < 1.0e25); objectiveWork_[i] = obj[i] * direction; } } } // Does rows and columns and objective void ClpSimplex::createRim5(bool initial) { createRim4(initial); createRim1(initial); } void ClpSimplex::deleteRim(int getRidOfFactorizationData) { // Just possible empty problem int numberRows = numberRows_; int numberColumns = numberColumns_; if (!numberRows || !numberColumns) { numberRows = 0; if (objective_->type() < 2) numberColumns = 0; } int i; if (problemStatus_ != 1 && problemStatus_ != 2) { delete [] ray_; ray_ = NULL; } // set upperOut_ to furthest away from bound so can use in dual for dualBound_ upperOut_ = 1.0; #if 0 { int nBad = 0; for (i = 0; i < numberColumns; i++) { if (lower_[i] == upper_[i] && getColumnStatus(i) == basic) nBad++; } if (nBad) printf("yy %d basic fixed\n", nBad); } #endif // ray may be null if in branch and bound if (rowScale_) { // Collect infeasibilities int numberPrimalScaled = 0; int numberPrimalUnscaled = 0; int numberDualScaled = 0; int numberDualUnscaled = 0; double scaleC = 1.0 / objectiveScale_; double scaleR = 1.0 / rhsScale_; const double * inverseScale = inverseColumnScale_; for (i = 0; i < numberColumns; i++) { double scaleFactor = columnScale_[i]; double valueScaled = columnActivityWork_[i]; double lowerScaled = columnLowerWork_[i]; double upperScaled = columnUpperWork_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } columnActivity_[i] = valueScaled * scaleFactor * scaleR; double value = columnActivity_[i]; if (value < columnLower_[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > columnUpper_[i] + primalTolerance_) numberPrimalUnscaled++; double valueScaledDual = reducedCostWork_[i]; if (valueScaled > columnLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_) numberDualScaled++; if (valueScaled < columnUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_) numberDualScaled++; reducedCost_[i] = (valueScaledDual * scaleC) * inverseScale[i]; double valueDual = reducedCost_[i]; if (value > columnLower_[i] + primalTolerance_ && valueDual > dualTolerance_) numberDualUnscaled++; if (value < columnUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_) numberDualUnscaled++; } inverseScale = inverseRowScale_; for (i = 0; i < numberRows; i++) { double scaleFactor = rowScale_[i]; double valueScaled = rowActivityWork_[i]; double lowerScaled = rowLowerWork_[i]; double upperScaled = rowUpperWork_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } rowActivity_[i] = (valueScaled * scaleR) * inverseScale[i]; double value = rowActivity_[i]; if (value < rowLower_[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > rowUpper_[i] + primalTolerance_) numberPrimalUnscaled++; double valueScaledDual = dual_[i] + rowObjectiveWork_[i];; if (valueScaled > rowLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_) numberDualScaled++; if (valueScaled < rowUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_) numberDualScaled++; dual_[i] *= scaleFactor * scaleC; double valueDual = dual_[i]; if (rowObjective_) valueDual += rowObjective_[i]; if (value > rowLower_[i] + primalTolerance_ && valueDual > dualTolerance_) numberDualUnscaled++; if (value < rowUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_) numberDualUnscaled++; } if (!problemStatus_ && !secondaryStatus_) { // See if we need to set secondary status if (numberPrimalUnscaled) { if (numberDualUnscaled) secondaryStatus_ = 4; else secondaryStatus_ = 2; } else { if (numberDualUnscaled) secondaryStatus_ = 3; } } if (problemStatus_ == 2 && ray_) { for (i = 0; i < numberColumns; i++) { ray_[i] *= columnScale_[i]; } } else if (problemStatus_ == 1 && ray_) { for (i = 0; i < numberRows; i++) { ray_[i] *= rowScale_[i]; } } } else if (rhsScale_ != 1.0 || objectiveScale_ != 1.0) { // Collect infeasibilities int numberPrimalScaled = 0; int numberPrimalUnscaled = 0; int numberDualScaled = 0; int numberDualUnscaled = 0; double scaleC = 1.0 / objectiveScale_; double scaleR = 1.0 / rhsScale_; for (i = 0; i < numberColumns; i++) { double valueScaled = columnActivityWork_[i]; double lowerScaled = columnLowerWork_[i]; double upperScaled = columnUpperWork_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } columnActivity_[i] = valueScaled * scaleR; double value = columnActivity_[i]; if (value < columnLower_[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > columnUpper_[i] + primalTolerance_) numberPrimalUnscaled++; double valueScaledDual = reducedCostWork_[i]; if (valueScaled > columnLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_) numberDualScaled++; if (valueScaled < columnUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_) numberDualScaled++; reducedCost_[i] = valueScaledDual * scaleC; double valueDual = reducedCost_[i]; if (value > columnLower_[i] + primalTolerance_ && valueDual > dualTolerance_) numberDualUnscaled++; if (value < columnUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_) numberDualUnscaled++; } for (i = 0; i < numberRows; i++) { double valueScaled = rowActivityWork_[i]; double lowerScaled = rowLowerWork_[i]; double upperScaled = rowUpperWork_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } rowActivity_[i] = valueScaled * scaleR; double value = rowActivity_[i]; if (value < rowLower_[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > rowUpper_[i] + primalTolerance_) numberPrimalUnscaled++; double valueScaledDual = dual_[i] + rowObjectiveWork_[i];; if (valueScaled > rowLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_) numberDualScaled++; if (valueScaled < rowUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_) numberDualScaled++; dual_[i] *= scaleC; double valueDual = dual_[i]; if (rowObjective_) valueDual += rowObjective_[i]; if (value > rowLower_[i] + primalTolerance_ && valueDual > dualTolerance_) numberDualUnscaled++; if (value < rowUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_) numberDualUnscaled++; } if (!problemStatus_ && !secondaryStatus_) { // See if we need to set secondary status if (numberPrimalUnscaled) { if (numberDualUnscaled) secondaryStatus_ = 4; else secondaryStatus_ = 2; } else { if (numberDualUnscaled) secondaryStatus_ = 3; } } } else { if (columnActivityWork_) { for (i = 0; i < numberColumns; i++) { double value = columnActivityWork_[i]; double lower = columnLowerWork_[i]; double upper = columnUpperWork_[i]; if (lower > -1.0e20 || upper < 1.0e20) { if (value > lower && value < upper) upperOut_ = CoinMax(upperOut_, CoinMin(value - lower, upper - value)); } columnActivity_[i] = columnActivityWork_[i]; reducedCost_[i] = reducedCostWork_[i]; } for (i = 0; i < numberRows; i++) { double value = rowActivityWork_[i]; double lower = rowLowerWork_[i]; double upper = rowUpperWork_[i]; if (lower > -1.0e20 || upper < 1.0e20) { if (value > lower && value < upper) upperOut_ = CoinMax(upperOut_, CoinMin(value - lower, upper - value)); } rowActivity_[i] = rowActivityWork_[i]; } } } // switch off scalefactor if auto if (automaticScale_) { rhsScale_ = 1.0; objectiveScale_ = 1.0; } if (optimizationDirection_ != 1.0) { // and modify all dual signs for (i = 0; i < numberColumns; i++) reducedCost_[i] *= optimizationDirection_; for (i = 0; i < numberRows; i++) dual_[i] *= optimizationDirection_; } // scaling may have been turned off scalingFlag_ = abs(scalingFlag_); if(getRidOfFactorizationData > 0) { gutsOfDelete(getRidOfFactorizationData + 1); } else { // at least get rid of nonLinearCost_ delete nonLinearCost_; nonLinearCost_ = NULL; } if (!rowObjective_ && problemStatus_ == 0 && objective_->type() == 1 && numberRows && numberColumns) { // Redo objective value double objectiveValue = 0.0; const double * cost = objective(); for (int i = 0; i < numberColumns; i++) { double value = columnActivity_[i]; objectiveValue += value * cost[i]; } //if (fabs(objectiveValue_ -objectiveValue*optimizationDirection())>1.0e-5) //printf("old obj %g new %g\n",objectiveValue_, objectiveValue*optimizationDirection()); objectiveValue_ = objectiveValue * optimizationDirection(); } // get rid of data matrix_->generalExpanded(this, 13, scalingFlag_); } void ClpSimplex::setDualBound(double value) { if (value > 0.0) dualBound_ = value; } void ClpSimplex::setInfeasibilityCost(double value) { if (value > 0.0) infeasibilityCost_ = value; } void ClpSimplex::setNumberRefinements( int value) { if (value >= 0 && value < 10) numberRefinements_ = value; } // Sets row pivot choice algorithm in dual void ClpSimplex::setDualRowPivotAlgorithm(ClpDualRowPivot & choice) { delete dualRowPivot_; dualRowPivot_ = choice.clone(true); dualRowPivot_->setModel(this); } // Sets row pivot choice algorithm in dual void ClpSimplex::setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot & choice) { delete primalColumnPivot_; primalColumnPivot_ = choice.clone(true); primalColumnPivot_->setModel(this); } void ClpSimplex::setFactorization( ClpFactorization & factorization) { if (factorization_) factorization_->setFactorization(factorization); else factorization_ = new ClpFactorization(factorization, numberRows_); } // Swaps factorization ClpFactorization * ClpSimplex::swapFactorization( ClpFactorization * factorization) { ClpFactorization * swap = factorization_; factorization_ = factorization; return swap; } // Copies in factorization to existing one void ClpSimplex::copyFactorization( ClpFactorization & factorization) { *factorization_ = factorization; } /* Perturbation: -50 to +50 - perturb by this power of ten (-6 sounds good) 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 */ void ClpSimplex::setPerturbation(int value) { if(value <= 100 && value >= -1000) { perturbation_ = value; } } // Sparsity on or off bool ClpSimplex::sparseFactorization() const { return factorization_->sparseThreshold() != 0; } void ClpSimplex::setSparseFactorization(bool value) { if (value) { if (!factorization_->sparseThreshold()) factorization_->goSparse(); } else { factorization_->sparseThreshold(0); } } void checkCorrect(ClpSimplex * /*model*/, int iRow, const double * element, const int * rowStart, const int * rowLength, const int * column, const double * columnLower_, const double * columnUpper_, int /*infiniteUpperC*/, int /*infiniteLowerC*/, double &maximumUpC, double &maximumDownC) { int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; double large = 1.0e15; int iColumn; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; iColumn = column[j]; if (value > 0.0) { if (columnUpper_[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper_[iColumn] * value; } if (columnLower_[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower_[iColumn] * value; } } else if (value < 0.0) { if (columnUpper_[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper_[iColumn] * value; } if (columnLower_[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower_[iColumn] * value; } } } //assert (infiniteLowerC==infiniteLower); //assert (infiniteUpperC==infiniteUpper); if (fabs(maximumUp - maximumUpC) > 1.0e-12 * CoinMax(fabs(maximumUp), fabs(maximumUpC))) COIN_DETAIL_PRINT(printf("row %d comp up %g, true up %g\n", iRow, maximumUpC, maximumUp)); if (fabs(maximumDown - maximumDownC) > 1.0e-12 * CoinMax(fabs(maximumDown), fabs(maximumDownC))) COIN_DETAIL_PRINT(printf("row %d comp down %g, true down %g\n", iRow, maximumDownC, maximumDown)); maximumUpC = maximumUp; maximumDownC = maximumDown; } /* Tightens primal bounds to make dual faster. Unless fixed, bounds are slightly looser than they could be. This is to make dual go faster and is probably not needed with a presolve. Returns non-zero if problem infeasible Fudge for branch and bound - put bounds on columns of factor * largest value (at continuous) - should improve stability in branch and bound on infeasible branches (0.0 is off) */ int ClpSimplex::tightenPrimalBounds(double factor, int doTight, bool tightIntegers) { // Get a row copy in standard format CoinPackedMatrix copy; copy.setExtraGap(0.0); copy.setExtraMajor(0.0); copy.reverseOrderedCopyOf(*matrix()); // Matrix may have been created so get rid of it matrix_->releasePackedMatrix(); // get matrix data pointers const int * column = copy.getIndices(); const CoinBigIndex * rowStart = copy.getVectorStarts(); const int * rowLength = copy.getVectorLengths(); const double * element = copy.getElements(); int numberChanged = 1, iPass = 0; double large = largeValue(); // treat bounds > this as infinite #ifndef NDEBUG double large2 = 1.0e10 * large; #endif int numberInfeasible = 0; int totalTightened = 0; double tolerance = primalTolerance(); // Save column bounds double * saveLower = new double [numberColumns_]; CoinMemcpyN(columnLower_, numberColumns_, saveLower); double * saveUpper = new double [numberColumns_]; CoinMemcpyN(columnUpper_, numberColumns_, saveUpper); int iRow, iColumn; // If wanted compute a reasonable dualBound_ if (factor == COIN_DBL_MAX) { factor = 0.0; if (dualBound_ == 1.0e10) { // get largest scaled away from bound double largest = 1.0e-12; double largestScaled = 1.0e-12; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { double value = rowActivity_[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 iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double value = columnActivity_[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; dualBound_ = CoinMax(1.0001e7, CoinMin(100.0 * largest, 1.00001e10)); } } // If wanted - tighten column bounds using solution if (factor) { double largest = 0.0; if (factor > 0.0) { assert (factor > 1.0); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnUpper_[iColumn] - columnLower_[iColumn] > tolerance) { largest = CoinMax(largest, fabs(columnActivity_[iColumn])); } } largest *= factor; } else { // absolute largest = - factor; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnUpper_[iColumn] - columnLower_[iColumn] > tolerance) { columnUpper_[iColumn] = CoinMin(columnUpper_[iColumn], largest); columnLower_[iColumn] = CoinMax(columnLower_[iColumn], -largest); } } } #define MAXPASS 10 // Loop round seeing if we can tighten bounds // Would be faster to have a stack of possible rows // and we put altered rows back on stack int numberCheck = -1; while(numberChanged > numberCheck) { numberChanged = 0; // Bounds tightened this pass if (iPass == MAXPASS) break; iPass++; for (iRow = 0; iRow < numberRows_; iRow++) { if (rowLower_[iRow] > -large || rowUpper_[iRow] < large) { // 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; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; iColumn = column[j]; if (value > 0.0) { if (columnUpper_[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper_[iColumn] * value; } if (columnLower_[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower_[iColumn] * value; } } else if (value < 0.0) { if (columnUpper_[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper_[iColumn] * value; } if (columnLower_[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower_[iColumn] * 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) { // Row is redundant - make totally free // NO - can't do this for postsolve // rowLower_[iRow]=-COIN_DBL_MAX; // rowUpper_[iRow]=COIN_DBL_MAX; //printf("Redundant row in presolveX %d\n",iRow); } else { if (maxUp < rowLower_[iRow] - 100.0 * tolerance || maxDown > rowUpper_[iRow] + 100.0 * tolerance) { // problem is infeasible - exit at once numberInfeasible++; break; } double lower = rowLower_[iRow]; double upper = rowUpper_[iRow]; for (j = rStart; j < rEnd; ++j) { double value = element[j]; iColumn = column[j]; double nowLower = columnLower_[iColumn]; double nowUpper = columnUpper_[iColumn]; 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 numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower_[iColumn] = newBound; // adjust double now; if (nowLower < -large) { now = 0.0; infiniteLower--; } else { now = nowLower; } maximumDown += (newBound - now) * value; nowLower = newBound; #ifdef DEBUG checkCorrect(this, iRow, element, rowStart, rowLength, column, columnLower_, columnUpper_, infiniteUpper, infiniteLower, maximumUp, maximumDown); #endif } } 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 numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper_[iColumn] = newBound; // adjust double now; if (nowUpper > large) { now = 0.0; infiniteUpper--; } else { now = nowUpper; } maximumUp += (newBound - now) * value; nowUpper = newBound; #ifdef DEBUG checkCorrect(this, iRow, element, rowStart, rowLength, column, columnLower_, columnUpper_, infiniteUpper, infiniteLower, maximumUp, maximumDown); #endif } } } 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 numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper_[iColumn] = newBound; // adjust double now; if (nowUpper > large) { now = 0.0; infiniteLower--; } else { now = nowUpper; } maximumDown += (newBound - now) * value; nowUpper = newBound; #ifdef DEBUG checkCorrect(this, iRow, element, rowStart, rowLength, column, columnLower_, columnUpper_, infiniteUpper, infiniteLower, maximumUp, maximumDown); #endif } } 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 numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower_[iColumn] = newBound; // adjust double now; if (nowLower < -large) { now = 0.0; infiniteUpper--; } else { now = nowLower; } maximumUp += (newBound - now) * value; nowLower = newBound; #ifdef DEBUG checkCorrect(this, iRow, element, rowStart, rowLength, column, columnLower_, columnUpper_, infiniteUpper, infiniteLower, maximumUp, maximumDown); #endif } } } } } } } totalTightened += numberChanged; if (iPass == 1) numberCheck = numberChanged >> 4; if (numberInfeasible) break; } if (!numberInfeasible) { handler_->message(CLP_SIMPLEX_BOUNDTIGHTEN, messages_) << totalTightened << CoinMessageEol; // Set bounds slightly loose double useTolerance = 1.0e-3; if (doTight > 0) { if (doTight > 10) { useTolerance = 0.0; } else { while (doTight) { useTolerance *= 0.1; doTight--; } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (saveUpper[iColumn] > saveLower[iColumn] + useTolerance) { // Make large bounds stay infinite if (saveUpper[iColumn] > 1.0e30 && columnUpper_[iColumn] > 1.0e10) { columnUpper_[iColumn] = COIN_DBL_MAX; } if (saveLower[iColumn] < -1.0e30 && columnLower_[iColumn] < -1.0e10) { columnLower_[iColumn] = -COIN_DBL_MAX; } #ifdef KEEP_GOING_IF_FIXED double multiplier = 5.0e-3 * floor(100.0 * randomNumberGenerator_.randomDouble()) + 1.0; multiplier *= 100.0; #else double multiplier = 100.0; #endif if (columnUpper_[iColumn] - columnLower_[iColumn] < useTolerance + 1.0e-8) { // relax enough so will have correct dj #if 1 columnLower_[iColumn] = CoinMax(saveLower[iColumn], columnLower_[iColumn] - multiplier * useTolerance); columnUpper_[iColumn] = CoinMin(saveUpper[iColumn], columnUpper_[iColumn] + multiplier * useTolerance); #else if (fabs(columnUpper_[iColumn]) < fabs(columnLower_[iColumn])) { if (columnUpper_[iColumn] - multiplier * useTolerance > saveLower[iColumn]) { columnLower_[iColumn] = columnUpper_[iColumn] - multiplier * useTolerance; } else { columnLower_[iColumn] = saveLower[iColumn]; columnUpper_[iColumn] = CoinMin(saveUpper[iColumn], saveLower[iColumn] + multiplier * useTolerance); } } else { if (columnLower_[iColumn] + multiplier * useTolerance < saveUpper[iColumn]) { columnUpper_[iColumn] = columnLower_[iColumn] + multiplier * useTolerance; } else { columnUpper_[iColumn] = saveUpper[iColumn]; columnLower_[iColumn] = CoinMax(saveLower[iColumn], saveUpper[iColumn] - multiplier * useTolerance); } } #endif } else { if (columnUpper_[iColumn] < saveUpper[iColumn]) { // relax a bit columnUpper_[iColumn] = CoinMin(columnUpper_[iColumn] + multiplier * useTolerance, saveUpper[iColumn]); } if (columnLower_[iColumn] > saveLower[iColumn]) { // relax a bit columnLower_[iColumn] = CoinMax(columnLower_[iColumn] - multiplier * useTolerance, saveLower[iColumn]); } } } } if (tightIntegers && integerType_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (integerType_[iColumn]) { double value; value = floor(columnLower_[iColumn] + 0.5); if (fabs(value - columnLower_[iColumn]) > primalTolerance_) value = ceil(columnLower_[iColumn]); columnLower_[iColumn] = value; value = floor(columnUpper_[iColumn] + 0.5); if (fabs(value - columnUpper_[iColumn]) > primalTolerance_) value = floor(columnUpper_[iColumn]); columnUpper_[iColumn] = value; if (columnLower_[iColumn] > columnUpper_[iColumn]) numberInfeasible++; } } if (numberInfeasible) { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } } } else { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } delete [] saveLower; delete [] saveUpper; return (numberInfeasible); } //#define SAVE_AND_RESTORE // dual #include "ClpSimplexDual.hpp" #include "ClpSimplexPrimal.hpp" #ifndef SAVE_AND_RESTORE int ClpSimplex::dual (int ifValuesPass , int startFinishOptions) #else int ClpSimplex::dual (int ifValuesPass , int startFinishOptions) { // May be empty problem if (numberRows_ && numberColumns_) { // Save on file for debug int returnCode; returnCode = saveModel("debug.sav"); if (returnCode) { printf("** Unable to save model to debug.sav\n"); abort(); } ClpSimplex temp; returnCode = temp.restoreModel("debug.sav"); if (returnCode) { printf("** Unable to restore model from debug.sav\n"); abort(); } temp.setLogLevel(handler_->logLevel()); // Now do dual returnCode = temp.dualDebug(ifValuesPass, startFinishOptions); // Move status and solution back int numberTotal = numberRows_ + numberColumns_; CoinMemcpyN(temp.statusArray(), numberTotal, status_); CoinMemcpyN(temp.primalColumnSolution(), numberColumns_, columnActivity_); CoinMemcpyN(temp.primalRowSolution(), numberRows_, rowActivity_); CoinMemcpyN(temp.dualColumnSolution(), numberColumns_, reducedCost_); CoinMemcpyN(temp.dualRowSolution(), numberRows_, dual_); problemStatus_ = temp.problemStatus_; setObjectiveValue(temp.objectiveValue()); setSumDualInfeasibilities(temp.sumDualInfeasibilities()); setNumberDualInfeasibilities(temp.numberDualInfeasibilities()); setSumPrimalInfeasibilities(temp.sumPrimalInfeasibilities()); setNumberPrimalInfeasibilities(temp.numberPrimalInfeasibilities()); setNumberIterations(temp.numberIterations()); onStopped(); // set secondary status if stopped return returnCode; } else { // empty return dualDebug(ifValuesPass, startFinishOptions); } } int ClpSimplex::dualDebug (int ifValuesPass , int startFinishOptions) #endif { //double savedPivotTolerance = factorization_->pivotTolerance(); int saveQuadraticActivated = 0; if (objective_) { saveQuadraticActivated = objective_->activated(); objective_->setActivated(0); } else { // create dummy stuff assert (!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } ClpObjective * saveObjective = objective_; CoinAssert (ifValuesPass >= 0 && ifValuesPass < 3); /* Note use of "down casting". The only class the user sees is ClpSimplex. Classes ClpSimplexDual, ClpSimplexPrimal, (ClpSimplexNonlinear) and ClpSimplexOther all exist and inherit from ClpSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ #ifdef COIN_DEVELOP //#define EXPENSIVE #endif #ifdef EXPENSIVE static int dualCount = 0; static int dualCheckCount = -1; dualCount++; if (dualCount == dualCheckCount) { printf("Bad dual coming up\n"); } ClpSimplex saveModel = *this; #endif int returnCode = static_cast (this)->dual(ifValuesPass, startFinishOptions); #ifdef EXPENSIVE if (problemStatus_ == 1) { saveModel.allSlackBasis(true); static_cast (&saveModel)->dual(0, 0); if (saveModel.problemStatus_ == 0) { if (saveModel.objectiveValue() < dblParam_[0] - 1.0e-8 * (1.0 + fabs(dblParam_[0]))) { if (objectiveValue() < dblParam_[0] - 1.0e-6 * (1.0 + fabs(dblParam_[0]))) { printf("BAD dual - objs %g ,savemodel %g cutoff %g at count %d\n", objectiveValue(), saveModel.objectiveValue(), dblParam_[0], dualCount); saveModel = *this; saveModel.setLogLevel(63); static_cast (&saveModel)->dual(0, 0); // flatten solution and try again int iRow, iColumn; for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) != basic) { setRowStatus(iRow, superBasic); // but put to bound if close if (fabs(rowActivity_[iRow] - rowLower_[iRow]) <= primalTolerance_) { rowActivity_[iRow] = rowLower_[iRow]; setRowStatus(iRow, atLowerBound); } else if (fabs(rowActivity_[iRow] - rowUpper_[iRow]) <= primalTolerance_) { rowActivity_[iRow] = rowUpper_[iRow]; setRowStatus(iRow, atUpperBound); } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) != basic) { setColumnStatus(iColumn, superBasic); // but put to bound if close if (fabs(columnActivity_[iColumn] - columnLower_[iColumn]) <= primalTolerance_) { columnActivity_[iColumn] = columnLower_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else if (fabs(columnActivity_[iColumn] - columnUpper_[iColumn]) <= primalTolerance_) { columnActivity_[iColumn] = columnUpper_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } } static_cast (&saveModel)->primal(0, 0); } else { printf("bad? dual - objs %g ,savemodel %g cutoff %g at count %d\n", objectiveValue(), saveModel.objectiveValue(), dblParam_[0], dualCount); } if (dualCount > dualCheckCount && dualCheckCount >= 0) abort(); } } } #endif //int lastAlgorithm = -1; if ((specialOptions_ & 2048) != 0 && problemStatus_ == 10 && !numberPrimalInfeasibilities_ && sumDualInfeasibilities_ < 1000.0 * dualTolerance_ && perturbation_ >= 100) problemStatus_ = 0; // ignore if (problemStatus_==1&&((specialOptions_&(1024 | 4096)) == 0 || (specialOptions_ & 32) != 0) &&numberFake_) { problemStatus_ = 10; // clean up in primal as fake bounds } if (problemStatus_ == 10) { //printf("Cleaning up with primal\n"); #ifdef COIN_DEVELOP int saveNumberIterations = numberIterations_; #endif //lastAlgorithm=1; int savePerturbation = perturbation_; int saveLog = handler_->logLevel(); //handler_->setLogLevel(63); perturbation_ = 100; bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // Allow for catastrophe int saveMax = intParam_[ClpMaxNumIteration]; if (numberIterations_) { // normal if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_) intParam_[ClpMaxNumIteration] = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_; } else { // Not normal allow more baseIteration_ += 2 * (numberRows_ + numberColumns_); } // check which algorithms allowed int dummy; ClpPackedMatrix * ordinary = dynamic_cast< ClpPackedMatrix*>(matrix_); if (problemStatus_ == 10 && saveObjective == objective_ && ordinary) startFinishOptions |= 2; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; if ((matrix_->generalExpanded(this, 4, dummy) & 1) != 0) returnCode = static_cast (this)->primal(1, startFinishOptions); else returnCode = static_cast (this)->dual(0, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; if (saveObjective != objective_) { // We changed objective to see if infeasible delete objective_; objective_ = saveObjective; if (!problemStatus_) { // carry on returnCode = static_cast (this)->primal(1, startFinishOptions); } } if (problemStatus_ == 3 && numberIterations_ < saveMax) { #ifdef COIN_DEVELOP if (handler_->logLevel() > 0) printf("looks like trouble - too many iterations in clean up - trying again\n"); #endif // flatten solution and try again int iRow, iColumn; for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) != basic) { setRowStatus(iRow, superBasic); // but put to bound if close if (fabs(rowActivity_[iRow] - rowLower_[iRow]) <= primalTolerance_) { rowActivity_[iRow] = rowLower_[iRow]; setRowStatus(iRow, atLowerBound); } else if (fabs(rowActivity_[iRow] - rowUpper_[iRow]) <= primalTolerance_) { rowActivity_[iRow] = rowUpper_[iRow]; setRowStatus(iRow, atUpperBound); } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) != basic) { setColumnStatus(iColumn, superBasic); // but put to bound if close if (fabs(columnActivity_[iColumn] - columnLower_[iColumn]) <= primalTolerance_) { columnActivity_[iColumn] = columnLower_[iColumn]; setColumnStatus(iColumn, atLowerBound); } else if (fabs(columnActivity_[iColumn] - columnUpper_[iColumn]) <= primalTolerance_) { columnActivity_[iColumn] = columnUpper_[iColumn]; setColumnStatus(iColumn, atUpperBound); } } } problemStatus_ = -1; intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_, saveMax); perturbation_ = savePerturbation; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; returnCode = static_cast (this)->primal(0, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; computeObjectiveValue(); // can't rely on djs either memset(reducedCost_, 0, numberColumns_ * sizeof(double)); #ifdef COIN_DEVELOP if (problemStatus_ == 3 && numberIterations_ < saveMax && handler_->logLevel() > 0) printf("looks like real trouble - too many iterations in second clean up - giving up\n"); #endif } intParam_[ClpMaxNumIteration] = saveMax; setInitialDenseFactorization(denseFactorization); perturbation_ = savePerturbation; if (problemStatus_ == 10) { if (!numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = 4; } handler_->setLogLevel(saveLog); #ifdef COIN_DEVELOP if (numberIterations_ > 200) printf("after primal status %d - %d iterations (save %d)\n", problemStatus_, numberIterations_, saveNumberIterations); #endif } objective_->setActivated(saveQuadraticActivated); //factorization_->pivotTolerance(savedPivotTolerance); onStopped(); // set secondary status if stopped //if (problemStatus_==1&&lastAlgorithm==1) //returnCode=10; // so will do primal after postsolve if (!problemStatus_) { //assert (!numberPrimalInfeasibilities_); //if (returnCode!=10) //assert (!numberDualInfeasibilities_); } return returnCode; } // primal int ClpSimplex::primal (int ifValuesPass , int startFinishOptions) { //double savedPivotTolerance = factorization_->pivotTolerance(); #ifndef SLIM_CLP // See if nonlinear if (objective_->type() > 1 && objective_->activated()) return reducedGradient(); #endif CoinAssert ((ifValuesPass >= 0 && ifValuesPass < 3) || (ifValuesPass >= 12 && ifValuesPass < 100) || (ifValuesPass >= 112 && ifValuesPass < 200)); if (ifValuesPass >= 12) { int numberProblems = (ifValuesPass - 10) % 100; ifValuesPass = (ifValuesPass < 100) ? 1 : 2; // Go parallel to do solve // Only if all slack basis int i; for ( i = 0; i < numberColumns_; i++) { if (getColumnStatus(i) == basic) break; } if (i == numberColumns_) { // try if vaguely feasible CoinZeroN(rowActivity_, numberRows_); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * element = matrix_->getElements(); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex j; double value = columnActivity_[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (j = start; j < end; j++) { int iRow = row[j]; rowActivity_[iRow] += value * element[j]; } } } checkSolutionInternal(); if (sumPrimalInfeasibilities_ * sqrt(static_cast(numberRows_)) < 1.0) { // Could do better if can decompose // correction to get feasible double scaleFactor = 1.0 / numberProblems; double * correction = new double [numberRows_]; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = rowActivity_[iRow]; if (value > rowUpper_[iRow]) value = rowUpper_[iRow] - value; else if (value < rowLower_[iRow]) value = rowLower_[iRow] - value; else value = 0.0; correction[iRow] = value * scaleFactor; } int numberColumns = (numberColumns_ + numberProblems - 1) / numberProblems; int * whichRows = new int [numberRows_]; for (int i = 0; i < numberRows_; i++) whichRows[i] = i; int * whichColumns = new int [numberColumns_]; ClpSimplex ** model = new ClpSimplex * [numberProblems]; int startColumn = 0; double * saveLower = CoinCopyOfArray(rowLower_, numberRows_); double * saveUpper = CoinCopyOfArray(rowUpper_, numberRows_); for (int i = 0; i < numberProblems; i++) { int endColumn = CoinMin(startColumn + numberColumns, numberColumns_); CoinZeroN(rowActivity_, numberRows_); for (int iColumn = startColumn; iColumn < endColumn; iColumn++) { whichColumns[iColumn-startColumn] = iColumn; CoinBigIndex j; double value = columnActivity_[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (j = start; j < end; j++) { int iRow = row[j]; rowActivity_[iRow] += value * element[j]; } } } // adjust rhs for (int iRow = 0; iRow < numberRows_; iRow++) { double value = rowActivity_[iRow] + correction[iRow]; if (saveUpper[iRow] < 1.0e30) rowUpper_[iRow] = value; if (saveLower[iRow] > -1.0e30) rowLower_[iRow] = value; } model[i] = new ClpSimplex(this, numberRows_, whichRows, endColumn - startColumn, whichColumns); //#define FEB_TRY #ifdef FEB_TRY model[i]->setPerturbation(perturbation_); #endif startColumn = endColumn; } memcpy(rowLower_, saveLower, numberRows_ * sizeof(double)); memcpy(rowUpper_, saveUpper, numberRows_ * sizeof(double)); delete [] saveLower; delete [] saveUpper; delete [] correction; // solve (in parallel) for (int i = 0; i < numberProblems; i++) { model[i]->primal(1/*ifValuesPass*/); } startColumn = 0; int numberBasic = 0; // use whichRows as counter for (int iRow = 0; iRow < numberRows_; iRow++) { int startValue = 0; if (rowUpper_[iRow] > rowLower_[iRow]) startValue++; if (rowUpper_[iRow] > 1.0e30) startValue++; if (rowLower_[iRow] < -1.0e30) startValue++; whichRows[iRow] = 1000 * startValue; } for (int i = 0; i < numberProblems; i++) { int endColumn = CoinMin(startColumn + numberColumns, numberColumns_); ClpSimplex * simplex = model[i]; const double * solution = simplex->columnActivity_; for (int iColumn = startColumn; iColumn < endColumn; iColumn++) { columnActivity_[iColumn] = solution[iColumn-startColumn]; Status status = simplex->getColumnStatus(iColumn - startColumn); setColumnStatus(iColumn, status); if (status == basic) numberBasic++; } for (int iRow = 0; iRow < numberRows_; iRow++) { if (simplex->getRowStatus(iRow) == basic) whichRows[iRow]++; } delete model[i]; startColumn = endColumn; } delete [] model; for (int iRow = 0; iRow < numberRows_; iRow++) setRowStatus(iRow, superBasic); CoinZeroN(rowActivity_, numberRows_); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex j; double value = columnActivity_[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (j = start; j < end; j++) { int iRow = row[j]; rowActivity_[iRow] += value * element[j]; } } } checkSolutionInternal(); if (numberBasic < numberRows_) { int * order = new int [numberRows_]; for (int iRow = 0; iRow < numberRows_; iRow++) { setRowStatus(iRow, superBasic); int nTimes = whichRows[iRow] % 1000; if (nTimes) nTimes += whichRows[iRow] / 500; whichRows[iRow] = -nTimes; order[iRow] = iRow; } CoinSort_2(whichRows, whichRows + numberRows_, order); int nPut = numberRows_ - numberBasic; for (int i = 0; i < nPut; i++) { int iRow = order[i]; setRowStatus(iRow, basic); } delete [] order; } else if (numberBasic > numberRows_) { double * away = new double [numberBasic]; numberBasic = 0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) == basic) { double value = columnActivity_[iColumn]; value = CoinMin(value - columnLower_[iColumn], columnUpper_[iColumn] - value); away[numberBasic] = value; whichColumns[numberBasic++] = iColumn; } } CoinSort_2(away, away + numberBasic, whichColumns); int nPut = numberBasic - numberRows_; for (int i = 0; i < nPut; i++) { int iColumn = whichColumns[i]; double value = columnActivity_[iColumn]; if (value - columnLower_[iColumn] < columnUpper_[iColumn] - value) setColumnStatus(iColumn, atLowerBound); else setColumnStatus(iColumn, atUpperBound); } delete [] away; } delete [] whichColumns; delete [] whichRows; } } } //firstFree_=-1; /* Note use of "down casting". The only class the user sees is ClpSimplex. Classes ClpSimplexDual, ClpSimplexPrimal, (ClpSimplexNonlinear) and ClpSimplexOther all exist and inherit from ClpSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ int returnCode = static_cast (this)->primal(ifValuesPass, startFinishOptions); //int lastAlgorithm=1; if (problemStatus_ == 10) { //lastAlgorithm=-1; //printf("Cleaning up with dual\n"); int savePerturbation = perturbation_; perturbation_ = 100; bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // check which algorithms allowed int dummy; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0 && (specialOptions_ & 8192) == 0) { double saveBound = dualBound_; // upperOut_ has largest away from bound dualBound_ = CoinMin(CoinMax(2.0 * upperOut_, 1.0e8), dualBound_); returnCode = static_cast (this)->dual(0, startFinishOptions); dualBound_ = saveBound; } else { returnCode = static_cast (this)->primal(0, startFinishOptions); } // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; setInitialDenseFactorization(denseFactorization); perturbation_ = savePerturbation; if (problemStatus_ == 10) { if (!numberPrimalInfeasibilities_) { problemStatus_ = 0; numberDualInfeasibilities_ = 0; } else { problemStatus_ = 4; } } } //factorization_->pivotTolerance(savedPivotTolerance); onStopped(); // set secondary status if stopped //if (problemStatus_==1&&lastAlgorithm==1) //returnCode=10; // so will do primal after postsolve return returnCode; } #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" /* Dual ranging. This computes increase/decrease in cost for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For non-basic variables the sequence number will be that of the non-basic variables. Up to user to provide correct length arrays. Returns non-zero if infeasible unbounded etc */ #include "ClpSimplexOther.hpp" int ClpSimplex::dualRanging(int numberCheck, const int * which, double * costIncrease, int * sequenceIncrease, double * costDecrease, int * sequenceDecrease, double * valueIncrease, double * valueDecrease) { int savePerturbation = perturbation_; perturbation_ = 100; /*int returnCode =*/ static_cast (this)->primal(0, 1); if (problemStatus_ == 10) { //printf("Cleaning up with dual\n"); bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // check which algorithms allowed int dummy; if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0) { // upperOut_ has largest away from bound double saveBound = dualBound_; if (upperOut_ > 0.0) dualBound_ = 2.0 * upperOut_; /*returnCode =*/ static_cast (this)->dual(0, 1); dualBound_ = saveBound; } else { /*returnCode =*/ static_cast (this)->primal(0, 1); } setInitialDenseFactorization(denseFactorization); if (problemStatus_ == 10) problemStatus_ = 0; } perturbation_ = savePerturbation; if (problemStatus_ || secondaryStatus_ == 6) { finish(); // get rid of arrays return 1; // odd status } static_cast (this)->dualRanging(numberCheck, which, costIncrease, sequenceIncrease, costDecrease, sequenceDecrease, valueIncrease, valueDecrease); finish(); // get rid of arrays return 0; } /* Primal ranging. This computes increase/decrease in value for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For basic variables the sequence number will be that of the basic variables. Up to user to providen correct length arrays. Returns non-zero if infeasible unbounded etc */ int ClpSimplex::primalRanging(int numberCheck, const int * which, double * valueIncrease, int * sequenceIncrease, double * valueDecrease, int * sequenceDecrease) { int savePerturbation = perturbation_; perturbation_ = 100; /*int returnCode =*/ static_cast (this)->primal(0, 1); if (problemStatus_ == 10) { //printf("Cleaning up with dual\n"); bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // check which algorithms allowed int dummy; if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0) { // upperOut_ has largest away from bound double saveBound = dualBound_; if (upperOut_ > 0.0) dualBound_ = 2.0 * upperOut_; /*returnCode =*/ static_cast (this)->dual(0, 1); dualBound_ = saveBound; } else { /*returnCode =*/ static_cast (this)->primal(0, 1); } setInitialDenseFactorization(denseFactorization); if (problemStatus_ == 10) problemStatus_ = 0; } perturbation_ = savePerturbation; if (problemStatus_ || secondaryStatus_ == 6) { finish(); // get rid of arrays return 1; // odd status } static_cast (this)->primalRanging(numberCheck, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); finish(); // get rid of arrays return 0; } /* Write the basis in MPS format to the specified file. If writeValues true writes values of structurals (and adds VALUES to end of NAME card) Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex (later)
Returns non-zero on I/O error */ int ClpSimplex::writeBasis(const char *filename, bool writeValues, int formatType) const { return static_cast (this)->writeBasis(filename, writeValues, formatType); } // Read a basis from the given filename int ClpSimplex::readBasis(const char *filename) { return static_cast (this)->readBasis(filename); } #include "ClpSimplexNonlinear.hpp" /* Solves nonlinear problem using SLP - may be used as crash for other algorithms when number of iterations small */ int ClpSimplex::nonlinearSLP(int numberPasses, double deltaTolerance) { return static_cast (this)->primalSLP(numberPasses, deltaTolerance); } /* Solves problem with nonlinear constraints 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 */ int ClpSimplex::nonlinearSLP(int numberConstraints, ClpConstraint ** constraints, int numberPasses, double deltaTolerance) { return static_cast (this)->primalSLP(numberConstraints, constraints, numberPasses, deltaTolerance); } // Solves non-linear using reduced gradient int ClpSimplex::reducedGradient(int phase) { if (objective_->type() < 2 || !objective_->activated()) { // no quadratic part return primal(0); } // get feasible if ((this->status() < 0 || numberPrimalInfeasibilities()) && phase == 0) { objective_->setActivated(0); double saveDirection = optimizationDirection(); setOptimizationDirection(0.0); primal(1); setOptimizationDirection(saveDirection); objective_->setActivated(1); // still infeasible if (numberPrimalInfeasibilities()) return 0; } // Now enter method int returnCode = static_cast (this)->primal(); return returnCode; } #include "ClpPredictorCorrector.hpp" #include "ClpCholeskyBase.hpp" // Preference is WSSMP, UFL (just ordering), MUMPS, TAUCS then base #include "ClpCholeskyWssmp.hpp" #include "ClpCholeskyWssmpKKT.hpp" #include "ClpCholeskyUfl.hpp" #include "ClpCholeskyMumps.hpp" #if TAUCS_BARRIER #include "ClpCholeskyTaucs.hpp" #endif #include "ClpPresolve.hpp" /* Solves using barrier (assumes you have good cholesky factor code). Does crossover to simplex if asked*/ int ClpSimplex::barrier(bool crossover) { ClpSimplex * model2 = this; int savePerturbation = perturbation_; ClpInterior barrier; barrier.borrowModel(*model2); // See if quadratic objective ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); // If Quadratic we need KKT bool doKKT = (quadraticObj != NULL); // Preference is WSSMP, UFL, MUMPS, TAUCS then base #ifdef WSSMP_BARRIER if (!doKKT) { ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(CoinMax(100, model2->numberRows() / 10)); barrier.setCholesky(cholesky); } else { //ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(); ClpCholeskyWssmpKKT * cholesky = new ClpCholeskyWssmpKKT(CoinMax(100, model2->numberRows() / 10)); barrier.setCholesky(cholesky); } #elif defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) if (!doKKT) { ClpCholeskyUfl * cholesky = new ClpCholeskyUfl(); barrier.setCholesky(cholesky); } else { ClpCholeskyBase * cholesky = new ClpCholeskyBase(); // not yetClpCholeskyUfl * cholesky = new ClpCholeskyUfl(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } #elif TAUCS_BARRIER assert (!doKKT); ClpCholeskyTaucs * cholesky = new ClpCholeskyTaucs(); barrier.setCholesky(cholesky); #elifdef COIN_HAS_MUMPS if (!doKKT) { ClpCholeskyMumps * cholesky = new ClpCholeskyMumps(); barrier.setCholesky(cholesky); } else { printf("***** Unable to do Mumps with KKT\n"); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } #else if (!doKKT) { ClpCholeskyBase * cholesky = new ClpCholeskyBase(); barrier.setCholesky(cholesky); } else { ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } #endif barrier.setDiagonalPerturbation(1.0e-14); int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); int saveMaxIts = model2->maximumIterations(); if (saveMaxIts < 1000) { barrier.setMaximumBarrierIterations(saveMaxIts); model2->setMaximumIterations(1000000); } barrier.primalDual(); int barrierStatus = barrier.status(); double gap = static_cast(barrier.complementarityGap()); // get which variables are fixed double * saveLower = NULL; double * saveUpper = NULL; ClpPresolve pinfo2; ClpSimplex * saveModel2 = NULL; int numberFixed = barrier.numberFixed(); if (numberFixed * 20 > barrier.numberRows() && numberFixed > 5000 && crossover && 0) { // may as well do presolve int numberRows = barrier.numberRows(); int numberColumns = barrier.numberColumns(); int numberTotal = numberRows + numberColumns; saveLower = new double [numberTotal]; saveUpper = new double [numberTotal]; CoinMemcpyN(barrier.columnLower(), numberColumns, saveLower); CoinMemcpyN(barrier.rowLower(), numberRows, saveLower + numberColumns); CoinMemcpyN(barrier.columnUpper(), numberColumns, saveUpper); CoinMemcpyN(barrier.rowUpper(), numberRows, saveUpper + numberColumns); barrier.fixFixed(); saveModel2 = model2; } barrier.returnModel(*model2); double * rowPrimal = new double [numberRows]; double * columnPrimal = new double [numberColumns]; double * rowDual = new double [numberRows]; double * columnDual = new double [numberColumns]; // move solutions other way CoinMemcpyN(model2->primalRowSolution(), numberRows, rowPrimal); CoinMemcpyN(model2->dualRowSolution(), numberRows, rowDual); CoinMemcpyN(model2->primalColumnSolution(), numberColumns, columnPrimal); CoinMemcpyN(model2->dualColumnSolution(), numberColumns, columnDual); if (saveModel2) { // do presolve model2 = pinfo2.presolvedModel(*model2, 1.0e-8, false, 5, true); } if (barrierStatus < 4 && crossover) { // make sure no status left model2->createStatus(); // solve model2->setPerturbation(100); // throw some into basis { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); double * dsort = new double[numberColumns]; int * sort = new int[numberColumns]; int n = 0; const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); const double * primalSolution = model2->primalColumnSolution(); double tolerance = 10.0 * primalTolerance_; int i; for ( i = 0; i < numberRows; i++) model2->setRowStatus(i, superBasic); for ( i = 0; i < numberColumns; i++) { double distance = CoinMin(columnUpper[i] - primalSolution[i], primalSolution[i] - columnLower[i]); if (distance > tolerance) { dsort[n] = -distance; sort[n++] = i; model2->setStatus(i, superBasic); } else if (distance > primalTolerance_) { model2->setStatus(i, superBasic); } else if (primalSolution[i] <= columnLower[i] + primalTolerance_) { model2->setStatus(i, atLowerBound); } else { model2->setStatus(i, atUpperBound); } } CoinSort_2(dsort, dsort + n, sort); n = CoinMin(numberRows, n); for ( i = 0; i < n; i++) { int iColumn = sort[i]; model2->setStatus(iColumn, basic); } delete [] sort; delete [] dsort; } if (gap < 1.0e-3 * (static_cast (numberRows + numberColumns))) { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); // just primal values pass double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); // save primal solution and copy back dual CoinMemcpyN(model2->primalRowSolution(), numberRows, rowPrimal); CoinMemcpyN(rowDual, numberRows, model2->dualRowSolution()); CoinMemcpyN(model2->primalColumnSolution(), numberColumns, columnPrimal); CoinMemcpyN(columnDual, numberColumns, model2->dualColumnSolution()); //model2->primal(1); // clean up reduced costs and flag variables { double * dj = model2->dualColumnSolution(); double * cost = model2->objective(); double * saveCost = new double[numberColumns]; CoinMemcpyN(cost, numberColumns, saveCost); double * saveLower = new double[numberColumns]; double * lower = model2->columnLower(); CoinMemcpyN(lower, numberColumns, saveLower); double * saveUpper = new double[numberColumns]; double * upper = model2->columnUpper(); CoinMemcpyN(upper, numberColumns, saveUpper); int i; double tolerance = 10.0 * dualTolerance_; for ( i = 0; i < numberColumns; i++) { if (model2->getStatus(i) == basic) { dj[i] = 0.0; } else if (model2->getStatus(i) == atLowerBound) { if (optimizationDirection_ * dj[i] < tolerance) { if (optimizationDirection_ * dj[i] < 0.0) { //if (dj[i]<-1.0e-3) //printf("bad dj at lb %d %g\n",i,dj[i]); cost[i] -= dj[i]; dj[i] = 0.0; } } else { upper[i] = lower[i]; } } else if (model2->getStatus(i) == atUpperBound) { if (optimizationDirection_ * dj[i] > tolerance) { if (optimizationDirection_ * dj[i] > 0.0) { //if (dj[i]>1.0e-3) //printf("bad dj at ub %d %g\n",i,dj[i]); cost[i] -= dj[i]; dj[i] = 0.0; } } else { lower[i] = upper[i]; } } } // just dual values pass //model2->setLogLevel(63); //model2->setFactorizationFrequency(1); model2->dual(2); CoinMemcpyN(saveCost, numberColumns, cost); delete [] saveCost; CoinMemcpyN(saveLower, numberColumns, lower); delete [] saveLower; CoinMemcpyN(saveUpper, numberColumns, upper); delete [] saveUpper; } // and finish // move solutions CoinMemcpyN(rowPrimal, numberRows, model2->primalRowSolution()); CoinMemcpyN(columnPrimal, numberColumns, model2->primalColumnSolution()); } // double saveScale = model2->objectiveScale(); // model2->setObjectiveScale(1.0e-3); // model2->primal(2); // model2->setObjectiveScale(saveScale); model2->primal(1); } else if (barrierStatus == 4 && crossover) { // memory problems model2->setPerturbation(savePerturbation); model2->createStatus(); model2->dual(); } model2->setMaximumIterations(saveMaxIts); delete [] rowPrimal; delete [] columnPrimal; delete [] rowDual; delete [] columnDual; if (saveLower) { pinfo2.postsolve(true); delete model2; model2 = saveModel2; int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); CoinMemcpyN(saveLower, numberColumns, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower()); delete [] saveLower; CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper()); delete [] saveUpper; model2->primal(1); } model2->setPerturbation(savePerturbation); return model2->status(); } /* For strong branching. On input lower and upper are new bounds while on output they are objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) */ int ClpSimplex::strongBranching(int numberVariables, const int * variables, double * newLower, double * newUpper, double ** outputSolution, int * outputStatus, int * outputIterations, bool stopOnFirstInfeasible, bool alwaysFinish, int startFinishOptions) { return static_cast (this)->strongBranching(numberVariables, variables, newLower, newUpper, outputSolution, outputStatus, outputIterations, stopOnFirstInfeasible, alwaysFinish, startFinishOptions); } #endif /* Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm. This is same as ClpModel one, but sets scaling on etc. */ void ClpSimplex::borrowModel(ClpModel & otherModel) { ClpModel::borrowModel(otherModel); createStatus(); //ClpDualRowSteepest steep1; //setDualRowPivotAlgorithm(steep1); //ClpPrimalColumnSteepest steep2; //setPrimalColumnPivotAlgorithm(steep2); } void ClpSimplex::borrowModel(ClpSimplex & otherModel) { ClpModel::borrowModel(otherModel); createStatus(); dualBound_ = otherModel.dualBound_; dualTolerance_ = otherModel.dualTolerance_; primalTolerance_ = otherModel.primalTolerance_; delete dualRowPivot_; dualRowPivot_ = otherModel.dualRowPivot_->clone(true); dualRowPivot_->setModel(this); delete primalColumnPivot_; primalColumnPivot_ = otherModel.primalColumnPivot_->clone(true); primalColumnPivot_->setModel(this); perturbation_ = otherModel.perturbation_; moreSpecialOptions_ = otherModel.moreSpecialOptions_; automaticScale_ = otherModel.automaticScale_; maximumPerturbationSize_ = otherModel.maximumPerturbationSize_; perturbationArray_ = otherModel.perturbationArray_; } /// Saves scalars for ClpSimplex typedef struct { double optimizationDirection; double dblParam[ClpLastDblParam]; double objectiveValue; double dualBound; double dualTolerance; double primalTolerance; double sumDualInfeasibilities; double sumPrimalInfeasibilities; double infeasibilityCost; int numberRows; int numberColumns; int intParam[ClpLastIntParam]; int numberIterations; int problemStatus; int maximumIterations; int lengthNames; int numberDualInfeasibilities; int numberDualInfeasibilitiesWithoutFree; int numberPrimalInfeasibilities; int numberRefinements; int scalingFlag; int algorithm; unsigned int specialOptions; int dualPivotChoice; int primalPivotChoice; int matrixStorageChoice; } Clp_scalars; #ifndef SLIM_NOIO int outDoubleArray(double * array, int length, FILE * fp) { size_t numberWritten; if (array && length) { numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; numberWritten = fwrite(array, sizeof(double), length, fp); if (numberWritten != static_cast(length)) return 1; } else { length = 0; numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; } return 0; } // Save model to file, returns 0 if success int ClpSimplex::saveModel(const char * fileName) { FILE * fp = fopen(fileName, "wb"); if (fp) { Clp_scalars scalars; size_t numberWritten; // Fill in scalars scalars.optimizationDirection = optimizationDirection_; CoinMemcpyN( dblParam_, ClpLastDblParam, scalars.dblParam); scalars.objectiveValue = objectiveValue_; scalars.dualBound = dualBound_; scalars.dualTolerance = dualTolerance_; scalars.primalTolerance = primalTolerance_; scalars.sumDualInfeasibilities = sumDualInfeasibilities_; scalars.sumPrimalInfeasibilities = sumPrimalInfeasibilities_; scalars.infeasibilityCost = infeasibilityCost_; scalars.numberRows = numberRows_; scalars.numberColumns = numberColumns_; CoinMemcpyN( intParam_, ClpLastIntParam, scalars.intParam); scalars.numberIterations = numberIterations_; scalars.problemStatus = problemStatus_; scalars.maximumIterations = maximumIterations(); scalars.lengthNames = lengthNames_; scalars.numberDualInfeasibilities = numberDualInfeasibilities_; scalars.numberDualInfeasibilitiesWithoutFree = numberDualInfeasibilitiesWithoutFree_; scalars.numberPrimalInfeasibilities = numberPrimalInfeasibilities_; scalars.numberRefinements = numberRefinements_; scalars.scalingFlag = scalingFlag_; scalars.algorithm = algorithm_; scalars.specialOptions = specialOptions_; scalars.dualPivotChoice = dualRowPivot_->type(); scalars.primalPivotChoice = primalColumnPivot_->type(); scalars.matrixStorageChoice = matrix_->type(); // put out scalars numberWritten = fwrite(&scalars, sizeof(Clp_scalars), 1, fp); if (numberWritten != 1) return 1; size_t length; #ifndef CLP_NO_STD int i; // strings for (i = 0; i < ClpLastStrParam; i++) { length = strParam_[i].size(); numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; if (length) { numberWritten = fwrite(strParam_[i].c_str(), length, 1, fp); if (numberWritten != 1) return 1; } } #endif // arrays - in no particular order if (outDoubleArray(rowActivity_, numberRows_, fp)) return 1; if (outDoubleArray(columnActivity_, numberColumns_, fp)) return 1; if (outDoubleArray(dual_, numberRows_, fp)) return 1; if (outDoubleArray(reducedCost_, numberColumns_, fp)) return 1; if (outDoubleArray(rowLower_, numberRows_, fp)) return 1; if (outDoubleArray(rowUpper_, numberRows_, fp)) return 1; if (outDoubleArray(objective(), numberColumns_, fp)) return 1; if (outDoubleArray(rowObjective_, numberRows_, fp)) return 1; if (outDoubleArray(columnLower_, numberColumns_, fp)) return 1; if (outDoubleArray(columnUpper_, numberColumns_, fp)) return 1; if (ray_) { if (problemStatus_ == 1) { if (outDoubleArray(ray_, numberRows_, fp)) return 1; } else if (problemStatus_ == 2) { if (outDoubleArray(ray_, numberColumns_, fp)) return 1; } else { if (outDoubleArray(NULL, 0, fp)) return 1; } } else { if (outDoubleArray(NULL, 0, fp)) return 1; } if (status_ && (numberRows_ + numberColumns_) > 0) { length = numberRows_ + numberColumns_; numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; numberWritten = fwrite(status_, sizeof(char), length, fp); if (numberWritten != length) return 1; } else { length = 0; numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; } #ifndef CLP_NO_STD if (lengthNames_) { char * array = new char[CoinMax(numberRows_, numberColumns_)*(lengthNames_+1)]; char * put = array; CoinAssert (numberRows_ == static_cast (rowNames_.size())); for (i = 0; i < numberRows_; i++) { assert(static_cast(rowNames_[i].size()) <= lengthNames_); strcpy(put, rowNames_[i].c_str()); put += lengthNames_ + 1; } numberWritten = fwrite(array, lengthNames_ + 1, numberRows_, fp); if (numberWritten != static_cast(numberRows_)) return 1; put = array; CoinAssert (numberColumns_ == static_cast (columnNames_.size())); for (i = 0; i < numberColumns_; i++) { assert(static_cast (columnNames_[i].size()) <= lengthNames_); strcpy(put, columnNames_[i].c_str()); put += lengthNames_ + 1; } numberWritten = fwrite(array, lengthNames_ + 1, numberColumns_, fp); if (numberWritten != static_cast(numberColumns_)) return 1; delete [] array; } #endif // integers if (integerType_) { int marker = 1; numberWritten = fwrite(&marker, sizeof(int), 1, fp); numberWritten = fwrite(integerType_, 1, numberColumns_, fp); if (numberWritten != static_cast(numberColumns_)) return 1; } else { int marker = 0; numberWritten = fwrite(&marker, sizeof(int), 1, fp); } // just standard type at present assert (matrix_->type() == 1); CoinAssert (matrix_->getNumCols() == numberColumns_); CoinAssert (matrix_->getNumRows() == numberRows_); // we are going to save with gaps length = matrix_->getVectorStarts()[numberColumns_-1] + matrix_->getVectorLengths()[numberColumns_-1]; numberWritten = fwrite(&length, sizeof(int), 1, fp); if (numberWritten != 1) return 1; numberWritten = fwrite(matrix_->getElements(), sizeof(double), length, fp); if (numberWritten != length) return 1; numberWritten = fwrite(matrix_->getIndices(), sizeof(int), length, fp); if (numberWritten != length) return 1; numberWritten = fwrite(matrix_->getVectorStarts(), sizeof(int), numberColumns_ + 1, fp); if (numberWritten != static_cast(numberColumns_) + 1) return 1; numberWritten = fwrite(matrix_->getVectorLengths(), sizeof(int), numberColumns_, fp); if (numberWritten != static_cast(numberColumns_)) return 1; // finished fclose(fp); return 0; } else { return -1; } } int inDoubleArray(double * &array, int length, FILE * fp) { size_t numberRead; int length2; numberRead = fread(&length2, sizeof(int), 1, fp); if (numberRead != 1) return 1; if (length2) { // lengths must match if (length != length2) return 2; array = new double[length]; numberRead = fread(array, sizeof(double), length, fp); if (numberRead != static_cast(length)) return 1; } return 0; } /* Restore model from file, returns 0 if success, deletes current model */ int ClpSimplex::restoreModel(const char * fileName) { FILE * fp = fopen(fileName, "rb"); if (fp) { // Get rid of current model // save event handler in case already set ClpEventHandler * handler = eventHandler_->clone(); ClpModel::gutsOfDelete(0); eventHandler_ = handler; gutsOfDelete(0); int i; for (i = 0; i < 6; i++) { rowArray_[i] = NULL; columnArray_[i] = NULL; } // get an empty factorization so we can set tolerances etc getEmptyFactorization(); // Say sparse factorization_->sparseThreshold(1); Clp_scalars scalars; size_t numberRead; // get scalars numberRead = fread(&scalars, sizeof(Clp_scalars), 1, fp); if (numberRead != 1) return 1; // Fill in scalars optimizationDirection_ = scalars.optimizationDirection; CoinMemcpyN( scalars.dblParam, ClpLastDblParam, dblParam_); objectiveValue_ = scalars.objectiveValue; dualBound_ = scalars.dualBound; dualTolerance_ = scalars.dualTolerance; primalTolerance_ = scalars.primalTolerance; sumDualInfeasibilities_ = scalars.sumDualInfeasibilities; sumPrimalInfeasibilities_ = scalars.sumPrimalInfeasibilities; infeasibilityCost_ = scalars.infeasibilityCost; numberRows_ = scalars.numberRows; numberColumns_ = scalars.numberColumns; CoinMemcpyN( scalars.intParam, ClpLastIntParam, intParam_); numberIterations_ = scalars.numberIterations; problemStatus_ = scalars.problemStatus; setMaximumIterations(scalars.maximumIterations); lengthNames_ = scalars.lengthNames; numberDualInfeasibilities_ = scalars.numberDualInfeasibilities; numberDualInfeasibilitiesWithoutFree_ = scalars.numberDualInfeasibilitiesWithoutFree; numberPrimalInfeasibilities_ = scalars.numberPrimalInfeasibilities; numberRefinements_ = scalars.numberRefinements; scalingFlag_ = scalars.scalingFlag; algorithm_ = scalars.algorithm; specialOptions_ = scalars.specialOptions; // strings CoinBigIndex length; #ifndef CLP_NO_STD for (i = 0; i < ClpLastStrParam; i++) { numberRead = fread(&length, sizeof(int), 1, fp); if (numberRead != 1) return 1; if (length) { char * array = new char[length+1]; numberRead = fread(array, length, 1, fp); if (numberRead != 1) return 1; array[length] = '\0'; strParam_[i] = array; delete [] array; } } #endif // arrays - in no particular order if (inDoubleArray(rowActivity_, numberRows_, fp)) return 1; if (inDoubleArray(columnActivity_, numberColumns_, fp)) return 1; if (inDoubleArray(dual_, numberRows_, fp)) return 1; if (inDoubleArray(reducedCost_, numberColumns_, fp)) return 1; if (inDoubleArray(rowLower_, numberRows_, fp)) return 1; if (inDoubleArray(rowUpper_, numberRows_, fp)) return 1; double * objective = NULL; if (inDoubleArray(objective, numberColumns_, fp)) return 1; delete objective_; objective_ = new ClpLinearObjective(objective, numberColumns_); delete [] objective; if (inDoubleArray(rowObjective_, numberRows_, fp)) return 1; if (inDoubleArray(columnLower_, numberColumns_, fp)) return 1; if (inDoubleArray(columnUpper_, numberColumns_, fp)) return 1; if (problemStatus_ == 1) { if (inDoubleArray(ray_, numberRows_, fp)) return 1; } else if (problemStatus_ == 2) { if (inDoubleArray(ray_, numberColumns_, fp)) return 1; } else { // ray should be null numberRead = fread(&length, sizeof(int), 1, fp); if (numberRead != 1) return 1; if (length) return 2; } delete [] status_; status_ = NULL; // status region numberRead = fread(&length, sizeof(int), 1, fp); if (numberRead != 1) return 1; if (length) { if (length != numberRows_ + numberColumns_) return 1; status_ = new char unsigned[length]; numberRead = fread(status_, sizeof(char), length, fp); if (numberRead != static_cast(length)) return 1; } #ifndef CLP_NO_STD if (lengthNames_) { char * array = new char[CoinMax(numberRows_, numberColumns_)*(lengthNames_+1)]; char * get = array; numberRead = fread(array, lengthNames_ + 1, numberRows_, fp); if (numberRead != static_cast(numberRows_)) return 1; rowNames_ = std::vector (); rowNames_.resize(numberRows_); for (i = 0; i < numberRows_; i++) { rowNames_.push_back(get); get += lengthNames_ + 1; } get = array; numberRead = fread(array, lengthNames_ + 1, numberColumns_, fp); if (numberRead != static_cast(numberColumns_)) return 1; columnNames_ = std::vector (); columnNames_.resize(numberColumns_); for (i = 0; i < numberColumns_; i++) { columnNames_.push_back(get); get += lengthNames_ + 1; } delete [] array; } #endif // integers int ifInteger; delete [] integerType_; numberRead = fread(&ifInteger, sizeof(int), 1, fp); // But try and stay compatible with previous version bool alreadyGotLength = false; if (numberRead != 1) return 1; if (ifInteger == 1) { integerType_ = new char [numberColumns_]; numberRead = fread(integerType_, 1, numberColumns_, fp); if (numberRead != static_cast(numberColumns_)) return 1; } else { integerType_ = NULL; if (ifInteger) { // probably old style save alreadyGotLength = true; length = ifInteger; } } // Pivot choices assert(scalars.dualPivotChoice > 0 && (scalars.dualPivotChoice & 63) < 3); delete dualRowPivot_; switch ((scalars.dualPivotChoice & 63)) { default: printf("Need another dualPivot case %d\n", scalars.dualPivotChoice & 63); case 1: // Dantzig dualRowPivot_ = new ClpDualRowDantzig(); break; case 2: // Steepest - use mode dualRowPivot_ = new ClpDualRowSteepest(scalars.dualPivotChoice >> 6); break; } assert(scalars.primalPivotChoice > 0 && (scalars.primalPivotChoice & 63) < 3); delete primalColumnPivot_; switch ((scalars.primalPivotChoice & 63)) { default: printf("Need another primalPivot case %d\n", scalars.primalPivotChoice & 63); case 1: // Dantzig primalColumnPivot_ = new ClpPrimalColumnDantzig(); break; case 2: // Steepest - use mode primalColumnPivot_ = new ClpPrimalColumnSteepest(scalars.primalPivotChoice >> 6); break; } assert(scalars.matrixStorageChoice == 1); delete matrix_; // get arrays if (!alreadyGotLength) { numberRead = fread(&length, sizeof(int), 1, fp); if (numberRead != 1) return 1; } double * elements = new double[length]; int * indices = new int[length]; CoinBigIndex * starts = new CoinBigIndex[numberColumns_+1]; int * lengths = new int[numberColumns_]; numberRead = fread(elements, sizeof(double), length, fp); if (numberRead != static_cast(length)) return 1; numberRead = fread(indices, sizeof(int), length, fp); if (numberRead != static_cast(length)) return 1; numberRead = fread(starts, sizeof(int), numberColumns_ + 1, fp); if (numberRead != static_cast(numberColumns_) + 1) return 1; numberRead = fread(lengths, sizeof(int), numberColumns_, fp); if (numberRead != static_cast(numberColumns_)) return 1; // assign matrix CoinPackedMatrix * matrix = new CoinPackedMatrix(); matrix->setExtraGap(0.0); matrix->setExtraMajor(0.0); // Pack down length = 0; for (i = 0; i < numberColumns_; i++) { int start = starts[i]; starts[i] = length; for (CoinBigIndex j = start; j < start + lengths[i]; j++) { elements[length] = elements[j]; indices[length++] = indices[j]; } lengths[i] = length - starts[i]; } starts[numberColumns_] = length; matrix->assignMatrix(true, numberRows_, numberColumns_, length, elements, indices, starts, lengths); // and transfer to Clp matrix_ = new ClpPackedMatrix(matrix); // finished fclose(fp); return 0; } else { return -1; } return 0; } #endif // value of incoming variable (in Dual) double ClpSimplex::valueIncomingDual() const { // Need value of incoming for list of infeasibilities as may be infeasible double valueIncoming = (dualOut_ / alpha_) * directionOut_; if (directionIn_ == -1) valueIncoming = upperIn_ - valueIncoming; else valueIncoming = lowerIn_ - valueIncoming; return valueIncoming; } // Sanity check on input data - returns true if okay bool ClpSimplex::sanityCheck() { // bad if empty if (!numberColumns_ || ((!numberRows_ || !matrix_->getNumElements()) && objective_->type() < 2)) { int infeasNumber[2]; double infeasSum[2]; problemStatus_ = emptyProblem(infeasNumber, infeasSum, false); numberDualInfeasibilities_ = infeasNumber[0]; sumDualInfeasibilities_ = infeasSum[0]; numberPrimalInfeasibilities_ = infeasNumber[1]; sumPrimalInfeasibilities_ = infeasSum[1]; return false; } int numberBad ; double largestBound, smallestBound, minimumGap; double smallestObj, largestObj; int firstBad; int modifiedBounds = 0; int i; numberBad = 0; firstBad = -1; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; smallestObj = 1.0e100; largestObj = 0.0; // If bounds are too close - fix double fixTolerance = primalTolerance_; if (fixTolerance < 2.0e-8) fixTolerance *= 1.1; for (i = numberColumns_; i < numberColumns_ + numberRows_; i++) { double value; value = fabs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance_) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = fabs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = fabs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } if (largestBound) handler_->message(CLP_RIMSTATISTICS3, messages_) << smallestBound << largestBound << minimumGap << CoinMessageEol; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; for (i = 0; i < numberColumns_; i++) { double value; value = fabs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance_) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = fabs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = fabs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } char rowcol[] = {'R', 'C'}; if (numberBad) { handler_->message(CLP_BAD_BOUNDS, messages_) << numberBad << rowcol[isColumn(firstBad)] << sequenceWithin(firstBad) << CoinMessageEol; problemStatus_ = 4; return false; } if (modifiedBounds) handler_->message(CLP_MODIFIEDBOUNDS, messages_) << modifiedBounds << CoinMessageEol; handler_->message(CLP_RIMSTATISTICS1, messages_) << smallestObj << largestObj << CoinMessageEol; if (largestBound) handler_->message(CLP_RIMSTATISTICS2, messages_) << smallestBound << largestBound << minimumGap << CoinMessageEol; return true; } // Set up status array (for OsiClp) void ClpSimplex::createStatus() { if(!status_) status_ = new unsigned char [numberColumns_+numberRows_]; memset(status_, 0, (numberColumns_ + numberRows_)*sizeof(char)); int i; // set column status to one nearest zero for (i = 0; i < numberColumns_; i++) { #if 0 if (columnLower_[i] >= 0.0) { setColumnStatus(i, atLowerBound); } else if (columnUpper_[i] <= 0.0) { setColumnStatus(i, atUpperBound); } else if (columnLower_[i] < -1.0e20 && columnUpper_[i] > 1.0e20) { // free setColumnStatus(i, isFree); } else if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) { setColumnStatus(i, atLowerBound); } else { setColumnStatus(i, atUpperBound); } #else setColumnStatus(i, atLowerBound); #endif } for (i = 0; i < numberRows_; i++) { setRowStatus(i, basic); } } /* Sets up all slack basis and resets solution to as it was after initial load or readMps */ void ClpSimplex::allSlackBasis(bool resetSolution) { createStatus(); if (resetSolution) { // put back to as it was originally int i; // set column status to one nearest zero // But set value to zero if lb <0.0 and ub>0.0 for (i = 0; i < numberColumns_; i++) { if (columnLower_[i] >= 0.0) { columnActivity_[i] = columnLower_[i]; setColumnStatus(i, atLowerBound); } else if (columnUpper_[i] <= 0.0) { columnActivity_[i] = columnUpper_[i]; setColumnStatus(i, atUpperBound); } else if (columnLower_[i] < -1.0e20 && columnUpper_[i] > 1.0e20) { // free columnActivity_[i] = 0.0; setColumnStatus(i, isFree); } else if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) { columnActivity_[i] = 0.0; setColumnStatus(i, atLowerBound); } else { columnActivity_[i] = 0.0; setColumnStatus(i, atUpperBound); } } if (solution_) { // do that as well if (!columnScale_) { for (i = 0; i < numberColumns_; i++) { solution_[i] = columnActivity_[i]; } } else { double * inverseColumnScale = columnScale_ + numberColumns_; for (i = 0; i < numberColumns_; i++) { solution_[i] = columnActivity_[i] * (rhsScale_ * inverseColumnScale[i]); } } } } } /* Loads a problem (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
*/ void ClpSimplex::loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); createStatus(); } void ClpSimplex::loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); createStatus(); } /* Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ void ClpSimplex::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, const double * rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub, rowObjective); createStatus(); } #ifndef SLIM_NOIO // This loads a model from a coinModel object - returns number of errors int ClpSimplex::loadProblem ( CoinModel & modelObject, bool /*keepSolution*/) { unsigned char * status = NULL; double * psol = NULL; double * dsol = NULL; if (status_ && numberRows_ && numberRows_ == modelObject.numberRows() && numberColumns_ == modelObject.numberColumns()) { status = new unsigned char [numberRows_+numberColumns_]; CoinMemcpyN(status_, numberRows_ + numberColumns_, status); psol = new double [numberRows_+numberColumns_]; CoinMemcpyN(columnActivity_, numberColumns_, psol); CoinMemcpyN(rowActivity_, numberRows_, psol + numberColumns_); dsol = new double [numberRows_+numberColumns_]; CoinMemcpyN(reducedCost_, numberColumns_, dsol); CoinMemcpyN(dual_, numberRows_, dsol + numberColumns_); } int returnCode = ClpModel::loadProblem(modelObject); const int * integerType = modelObject.integerTypeArray(); if (integerType) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (integerType[iColumn]) setInteger(iColumn); } } createStatus(); if (status) { // copy back CoinMemcpyN(status, numberRows_ + numberColumns_, status_); CoinMemcpyN(psol, numberColumns_, columnActivity_); CoinMemcpyN(psol + numberColumns_, numberRows_, rowActivity_); CoinMemcpyN(dsol, numberColumns_, reducedCost_); CoinMemcpyN(dsol + numberColumns_, numberRows_, dual_); delete [] status; delete [] psol; delete [] dsol; } optimizationDirection_ = modelObject.optimizationDirection(); return returnCode; } #endif void ClpSimplex::loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int * length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, length, collb, colub, obj, rowlb, rowub, rowObjective); createStatus(); } #ifndef SLIM_NOIO // Read an mps file from the given filename int ClpSimplex::readMps(const char *filename, bool keepNames, bool ignoreErrors) { int status = ClpModel::readMps(filename, keepNames, ignoreErrors); createStatus(); return status; } // Read GMPL files from the given filenames int ClpSimplex::readGMPL(const char *filename, const char * dataName, bool keepNames) { int status = ClpModel::readGMPL(filename, dataName, keepNames); createStatus(); return status; } // Read file in LP format from file with name filename. int ClpSimplex::readLp(const char *filename, const double epsilon ) { FILE *fp; if (strcmp(filename,"-")) fp = fopen(filename, "r"); else fp = stdin; if(!fp) { printf("### ERROR: ClpSimplex::readLp(): Unable to open file %s for reading\n", filename); return(1); } CoinLpIO m; m.readLp(fp, epsilon); fclose(fp); // set problem name setStrParam(ClpProbName, m.getProblemName()); // no errors loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (m.integerColumns()) { integerType_ = new char[numberColumns_]; CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_); } else { integerType_ = NULL; } createStatus(); unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { const char * name = m.rowName(iRow); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); rowNames_.push_back(name); } else { rowNames_.push_back(""); } } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { const char * name = m.columnName(iColumn); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); columnNames_.push_back(name); } else { columnNames_.push_back(""); } } lengthNames_ = static_cast (maxLength); return 0; } #endif // Just check solution (for external use) void ClpSimplex::checkSolution(int setToBounds) { if (setToBounds) { // Set all ones that look at bounds to bounds bool changed = false; int i; for (i = 0; i < numberRows_; i++) { double newValue = 0.0; switch(getRowStatus(i)) { case basic: newValue = rowActivity_[i]; break; case atUpperBound: newValue = rowUpper_[i]; if (newValue > largeValue_) { if (rowLower_[i] > -largeValue_) { newValue = rowLower_[i]; setRowStatus(i, atLowerBound); } else { // say free setRowStatus(i, isFree); newValue = 0.0; } } break; case ClpSimplex::isFixed: case atLowerBound: newValue = rowLower_[i]; if (newValue < -largeValue_) { if (rowUpper_[i] < largeValue_) { newValue = rowUpper_[i]; setRowStatus(i, atUpperBound); } else { // say free setRowStatus(i, isFree); newValue = 0.0; } } break; case isFree: newValue = rowActivity_[i]; break; // not really free - fall through to superbasic case superBasic: if (rowUpper_[i] > largeValue_) { if (rowLower_[i] > -largeValue_) { newValue = rowLower_[i]; setRowStatus(i, atLowerBound); } else { // say free setRowStatus(i, isFree); newValue = 0.0; } } else { if (rowLower_[i] > -largeValue_) { // set to nearest if (fabs(newValue - rowLower_[i]) < fabs(newValue - rowUpper_[i])) { newValue = rowLower_[i]; setRowStatus(i, atLowerBound); } else { newValue = rowUpper_[i]; setRowStatus(i, atUpperBound); } } else { newValue = rowUpper_[i]; setRowStatus(i, atUpperBound); } } break; } if (fabs(newValue - rowActivity_[i]) > 1.0e-12) { changed = true; rowActivity_[i] = newValue; } } for (i = 0; i < numberColumns_; i++) { double newValue = 0.0; switch(getColumnStatus(i)) { case basic: newValue = columnActivity_[i]; break; case atUpperBound: newValue = columnUpper_[i]; if (newValue > largeValue_) { if (columnLower_[i] > -largeValue_) { newValue = columnLower_[i]; setColumnStatus(i, atLowerBound); } else { // say free setColumnStatus(i, isFree); newValue = 0.0; } } break; case ClpSimplex::isFixed: case atLowerBound: newValue = columnLower_[i]; if (newValue < -largeValue_) { if (columnUpper_[i] < largeValue_) { newValue = columnUpper_[i]; setColumnStatus(i, atUpperBound); } else { // say free setColumnStatus(i, isFree); newValue = 0.0; } } break; case isFree: newValue = columnActivity_[i]; break; // not really free - fall through to superbasic case superBasic: if (columnUpper_[i] > largeValue_) { if (columnLower_[i] > -largeValue_) { newValue = columnLower_[i]; setColumnStatus(i, atLowerBound); } else { // say free setColumnStatus(i, isFree); newValue = 0.0; } } else { if (columnLower_[i] > -largeValue_) { // set to nearest if (fabs(newValue - columnLower_[i]) < fabs(newValue - columnUpper_[i])) { newValue = columnLower_[i]; setColumnStatus(i, atLowerBound); } else { newValue = columnUpper_[i]; setColumnStatus(i, atUpperBound); } } else { newValue = columnUpper_[i]; setColumnStatus(i, atUpperBound); } } break; } if (fabs(newValue - columnActivity_[i]) > 1.0e-12) { changed = true; columnActivity_[i] = newValue; } } if (!changed && setToBounds == 1) // no need to do anything setToBounds = 0; } if (!setToBounds) { // Just use column solution CoinZeroN(rowActivity_, numberRows_); matrix()->times(columnActivity_, rowActivity_) ; // put in standard form createRim(7 + 8 + 16 + 32); dualTolerance_ = dblParam_[ClpDualTolerance]; primalTolerance_ = dblParam_[ClpPrimalTolerance]; checkPrimalSolution( rowActivityWork_, columnActivityWork_); checkDualSolution(); } else { startup(0, 0); gutsOfSolution(NULL, NULL); } if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = -1; #ifdef CLP_DEBUG int i; double value = 0.0; for (i = 0; i < numberRows_ + numberColumns_; i++) value += dj_[i] * solution_[i]; printf("dual value %g, primal %g\n", value, objectiveValue()); #endif // release extra memory deleteRim(0); } // Check unscaled primal solution but allow for rounding error void ClpSimplex::checkUnscaledSolution() { if (problemStatus_==1 && matrix_->getNumElements()) { const double * element = matrix_->getElements(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const int * row = matrix_->getIndices(); memset(rowActivity_,0,numberRows_*sizeof(double)); double * sum = new double [numberRows_+100000]; memset(sum,0,numberRows_*sizeof(double)); // clean column activity for (int i=0;i=0&&iRowrowUpper_[i]) { sumPrimalInfeasibilities2 += value - rowUpper_[i]; numberPrimalInfeasibilities2++; if (value>rowUpper_[i]+useTolerance) { sumPrimalInfeasibilities_ += value - (rowUpper_[i]+useTolerance); numberPrimalInfeasibilities_++; } } else if (valuemessage(CLP_GENERAL, messages_) << line << CoinMessageEol; } if (!numberPrimalInfeasibilities_) { if (!numberDualInfeasibilities_) problemStatus_=0; } else { sprintf(line,"%d relaxed row infeasibilities - summing to %g", numberPrimalInfeasibilities_, sumPrimalInfeasibilities_); handler_->message(CLP_GENERAL, messages_) << line << CoinMessageEol; } delete [] sum; } } /* Crash - at present just aimed at dual, returns -2 if dual preferred and crash basis created -1 if dual preferred and all slack basis preferred 0 if basis going in was not all slack 1 if primal preferred and all slack basis preferred 2 if primal preferred and crash basis created. if gap between bounds <="gap" variables can be flipped ( If pivot -1 then can be made super basic!) If "pivot" is -1 No pivoting - always primal 0 No pivoting (so will just be choice of algorithm) 1 Simple pivoting e.g. gub 2 Mini iterations 3 Just throw all free variables in basis */ int ClpSimplex::crash(double gap, int pivot) { //CoinAssert(!rowObjective_); // not coded int iColumn; int numberBad = 0; int numberBasic = 0; double dualTolerance = dblParam_[ClpDualTolerance]; //double primalTolerance=dblParam_[ClpPrimalTolerance]; int returnCode = 0; // If no basis then make all slack one if (!status_) createStatus(); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) == basic) numberBasic++; } if (!numberBasic || pivot == 3) { #if 0 int nFree=0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLower_[iColumn] < -1.0e20 && columnUpper_[iColumn] > 1.0e20) nFree++; } if (nFree>numberColumns_/10) pivot=3; #endif if (pivot == 3) { // Get column copy CoinPackedMatrix * columnCopy = matrix(); const int * row = columnCopy->getIndices(); const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); const int * columnLength = columnCopy->getVectorLengths(); const double * element = columnCopy->getElements(); int nFree=0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLower_[iColumn] < -1.0e20 && columnUpper_[iColumn] > 1.0e20) { // find triangular row int kRow=-1; double largest=0.0; double largestOther=0.0; for (CoinBigIndex j=columnStart[iColumn]; jlargest) { kRow=row[j]; largest=fabs(element[j]); } } else { if (fabs(element[j])>largestOther) { largestOther=fabs(element[j]); } } } if (kRow>=0&&largest*2.5>=largestOther) { nFree++; setColumnStatus(iColumn, basic); if (fabs(rowLower_[kRow]) < fabs(rowUpper_[kRow])) setRowStatus(kRow, atLowerBound); else setRowStatus(kRow, atUpperBound); for (CoinBigIndex j=columnStart[iColumn]; j -1.0e20 || upperBound < 1.0e20) { bool atLower; if (fabs(upperBound) < fabs(lowerBound)) { atLower = false; setColumnStatus(iColumn, atUpperBound); solution[iColumn] = upperBound; } else { atLower = true; setColumnStatus(iColumn, atLowerBound); solution[iColumn] = lowerBound; } if (dj[iColumn] < -dualTolerance_) { // should be at upper bound if (atLower) { // can we flip if (upperBound - lowerBound <= gap) { columnActivity_[iColumn] = upperBound; setColumnStatus(iColumn, atUpperBound); } else if (pivot < 0) { // set superbasic columnActivity_[iColumn] = lowerBound + gap; setColumnStatus(iColumn, superBasic); } else if (dj[iColumn] < -dualTolerance) { numberBad++; } } } else if (dj[iColumn] > dualTolerance_) { // should be at lower bound if (!atLower) { // can we flip if (upperBound - lowerBound <= gap) { columnActivity_[iColumn] = lowerBound; setColumnStatus(iColumn, atLowerBound); } else if (pivot < 0) { // set superbasic columnActivity_[iColumn] = upperBound - gap; setColumnStatus(iColumn, superBasic); } else if (dj[iColumn] > dualTolerance) { numberBad++; } } } } else { // free setColumnStatus(iColumn, isFree); if (fabs(dj[iColumn]) > dualTolerance) numberBad++; } } if (numberBad || pivot) { if (pivot <= 0) { delete [] dj; returnCode = 1; } else { // see if can be made dual feasible with gubs etc double * pi = new double[numberRows_]; memset (pi, 0, numberRows_ * sizeof(double)); int * way = new int[numberColumns_]; int numberIn = 0; // Get column copy CoinPackedMatrix * columnCopy = matrix(); // Get a row copy in standard format CoinPackedMatrix copy; copy.setExtraGap(0.0); copy.setExtraMajor(0.0); copy.reverseOrderedCopyOf(*columnCopy); // get matrix data pointers const int * column = copy.getIndices(); const CoinBigIndex * rowStart = copy.getVectorStarts(); const int * rowLength = copy.getVectorLengths(); const double * elementByRow = copy.getElements(); //const int * row = columnCopy->getIndices(); //const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); //const int * columnLength = columnCopy->getVectorLengths(); //const double * element = columnCopy->getElements(); // if equality row and bounds mean artificial in basis bad // then do anyway for (iColumn = 0; iColumn < numberColumns_; iColumn++) { // - if we want to reduce dj, + if we want to increase int thisWay = 100; double lowerBound = columnLower_[iColumn]; double upperBound = columnUpper_[iColumn]; if (upperBound > lowerBound) { switch(getColumnStatus(iColumn)) { case basic: thisWay = 0; case ClpSimplex::isFixed: break; case isFree: case superBasic: if (dj[iColumn] < -dualTolerance) thisWay = 1; else if (dj[iColumn] > dualTolerance) thisWay = -1; else thisWay = 0; break; case atUpperBound: if (dj[iColumn] > dualTolerance) thisWay = -1; else if (dj[iColumn] < -dualTolerance) thisWay = -3; else thisWay = -2; break; case atLowerBound: if (dj[iColumn] < -dualTolerance) thisWay = 1; else if (dj[iColumn] > dualTolerance) thisWay = 3; else thisWay = 2; break; } } way[iColumn] = thisWay; } /*if (!numberBad) printf("Was dual feasible before passes - rows %d\n", numberRows_);*/ int lastNumberIn = -100000; int numberPasses = 5; while (numberIn > lastNumberIn + numberRows_ / 100) { lastNumberIn = numberIn; // we need to maximize chance of doing good int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { double lowerBound = rowLower_[iRow]; double upperBound = rowUpper_[iRow]; if (getRowStatus(iRow) == basic) { // see if we can find a column to pivot on int j; // down is amount pi can go down double maximumDown = COIN_DBL_MAX; double maximumUp = COIN_DBL_MAX; double minimumDown = 0.0; double minimumUp = 0.0; int iUp = -1; int iDown = -1; int iUpB = -1; int iDownB = -1; if (lowerBound < -1.0e20) maximumUp = -1.0; if (upperBound > 1.0e20) maximumDown = -1.0; for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double djValue = dj[iColumn]; /* way - -3 - okay at upper bound with negative dj -2 - marginal at upper bound with zero dj - can only decrease -1 - bad at upper bound 0 - we can never pivot on this row 1 - bad at lower bound 2 - marginal at lower bound with zero dj - can only increase 3 - okay at lower bound with positive dj 100 - fine we can just ignore */ if (way[iColumn] != 100) { switch(way[iColumn]) { case -3: if (value > 0.0) { if (maximumDown * value > -djValue) { maximumDown = -djValue / value; iDown = iColumn; } } else { if (-maximumUp * value > -djValue) { maximumUp = djValue / value; iUp = iColumn; } } break; case -2: if (value > 0.0) { maximumDown = 0.0; } else { maximumUp = 0.0; } break; case -1: // see if could be satisfied // dj value > 0 if (value > 0.0) { maximumDown = 0.0; if (maximumUp * value < djValue - dualTolerance) { maximumUp = 0.0; // would improve but not enough } else { if (minimumUp * value < djValue) { minimumUp = djValue / value; iUpB = iColumn; } } } else { maximumUp = 0.0; if (-maximumDown * value < djValue - dualTolerance) { maximumDown = 0.0; // would improve but not enough } else { if (-minimumDown * value < djValue) { minimumDown = -djValue / value; iDownB = iColumn; } } } break; case 0: maximumDown = -1.0; maximumUp = -1.0; break; case 1: // see if could be satisfied // dj value < 0 if (value > 0.0) { maximumUp = 0.0; if (maximumDown * value < -djValue - dualTolerance) { maximumDown = 0.0; // would improve but not enough } else { if (minimumDown * value < -djValue) { minimumDown = -djValue / value; iDownB = iColumn; } } } else { maximumDown = 0.0; if (-maximumUp * value < -djValue - dualTolerance) { maximumUp = 0.0; // would improve but not enough } else { if (-minimumUp * value < -djValue) { minimumUp = djValue / value; iUpB = iColumn; } } } break; case 2: if (value > 0.0) { maximumUp = 0.0; } else { maximumDown = 0.0; } break; case 3: if (value > 0.0) { if (maximumUp * value > djValue) { maximumUp = djValue / value; iUp = iColumn; } } else { if (-maximumDown * value > djValue) { maximumDown = -djValue / value; iDown = iColumn; } } break; default: break; } } } if (iUpB >= 0) iUp = iUpB; if (maximumUp <= dualTolerance || maximumUp < minimumUp) iUp = -1; if (iDownB >= 0) iDown = iDownB; if (maximumDown <= dualTolerance || maximumDown < minimumDown) iDown = -1; if (iUp >= 0 || iDown >= 0) { // do something if (iUp >= 0 && iDown >= 0) { if (maximumDown > maximumUp) iUp = -1; } double change; int kColumn; if (iUp >= 0) { kColumn = iUp; change = maximumUp; // just do minimum if was dual infeasible // ? only if maximum large? if (minimumUp > 0.0) change = minimumUp; setRowStatus(iRow, atUpperBound); } else { kColumn = iDown; change = -maximumDown; // just do minimum if was dual infeasible // ? only if maximum large? if (minimumDown > 0.0) change = -minimumDown; setRowStatus(iRow, atLowerBound); } assert (fabs(change) < 1.0e200); setColumnStatus(kColumn, basic); numberIn++; pi[iRow] = change; for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; double value = elementByRow[j]; double djValue = dj[iColumn] - change * value; dj[iColumn] = djValue; if (abs(way[iColumn]) == 1) { numberBad--; /*if (!numberBad) printf("Became dual feasible at row %d out of %d\n", iRow, numberRows_);*/ lastNumberIn = -1000000; } int thisWay = 100; double lowerBound = columnLower_[iColumn]; double upperBound = columnUpper_[iColumn]; if (upperBound > lowerBound) { switch(getColumnStatus(iColumn)) { case basic: thisWay = 0; case isFixed: break; case isFree: case superBasic: if (djValue < -dualTolerance) thisWay = 1; else if (djValue > dualTolerance) thisWay = -1; else { thisWay = 0; } break; case atUpperBound: if (djValue > dualTolerance) { thisWay = -1; } else if (djValue < -dualTolerance) thisWay = -3; else thisWay = -2; break; case atLowerBound: if (djValue < -dualTolerance) { thisWay = 1; } else if (djValue > dualTolerance) thisWay = 3; else thisWay = 2; break; } } way[iColumn] = thisWay; } } } } if (numberIn == lastNumberIn || numberBad || pivot < 2) break; if (!(--numberPasses)) break; //printf("%d put in so far\n",numberIn); } // last attempt to flip for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double lowerBound = columnLower_[iColumn]; double upperBound = columnUpper_[iColumn]; if (upperBound - lowerBound <= gap && upperBound > lowerBound) { double djValue = dj[iColumn]; switch(getColumnStatus(iColumn)) { case basic: case ClpSimplex::isFixed: break; case isFree: case superBasic: break; case atUpperBound: if (djValue > dualTolerance) { setColumnStatus(iColumn, atUpperBound); solution[iColumn] = upperBound; } break; case atLowerBound: if (djValue < -dualTolerance) { setColumnStatus(iColumn, atUpperBound); solution[iColumn] = upperBound; } break; } } } delete [] pi; delete [] dj; delete [] way; handler_->message(CLP_CRASH, messages_) << numberIn << numberBad << CoinMessageEol; // could do elsewhere and could even if something done // see if some MUST be in basis if (!numberIn) { } returnCode = -1; } } else { delete [] dj; returnCode = -1; } //cleanStatus(); } return returnCode; } /* Pivot in a variable and out a variable. Returns 0 if okay, 1 if inaccuracy forced re-factorization, -1 if would be singular. Also updates primal/dual infeasibilities. Assumes sequenceIn_ and pivotRow_ set and also directionIn and Out. */ int ClpSimplex::pivot() { // scaling not allowed assert (!scalingFlag_); // assume In_ and Out_ are correct and directionOut_ set // (or In_ if flip lowerIn_ = lower_[sequenceIn_]; valueIn_ = solution_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; lowerOut_ = lower_[sequenceOut_]; valueOut_ = solution_[sequenceOut_]; upperOut_ = upper_[sequenceOut_]; // for now assume primal is feasible (or in dual) dualOut_ = dj_[sequenceOut_]; assert(fabs(dualOut_) < 1.0e-5); bool roundAgain = true; int returnCode = 0; bool updateSolution = true; while (roundAgain) { roundAgain = false; unpack(rowArray_[1]); factorization_->updateColumnFT(rowArray_[2], rowArray_[1]); alpha_ = 0.0; int i; int * index = rowArray_[1]->getIndices(); int number = rowArray_[1]->getNumElements(); double * element = rowArray_[1]->denseVector(); assert ( !rowArray_[3]->getNumElements()); double * saveSolution = rowArray_[3]->denseVector(); for (i = 0; i < number; i++) { int ii = index[i]; if ( pivotVariable_[ii] == sequenceOut_) { pivotRow_ = ii; alpha_ = element[pivotRow_]; break; } } if (fabs(alpha_) < 1.0e-8) { // be on safe side and clear arrays rowArray_[0]->clear(); rowArray_[1]->clear(); return -1; // will be singular } // we are going to subtract movement from current basic double movement; // see where incoming will go to if (sequenceOut_ < 0 || sequenceIn_ == sequenceOut_) { // flip so go to bound movement = ((directionIn_ > 0) ? upperIn_ : lowerIn_) - valueIn_; } else { // get where outgoing needs to get to double outValue = (directionOut_ < 0) ? upperOut_ : lowerOut_; // solutionOut_ - movement*alpha_ == outValue movement = (valueOut_ - outValue) / alpha_; // set directionIn_ correctly directionIn_ = (movement > 0) ? 1 : -1; } theta_ = movement; double oldValueIn = valueIn_; // update primal solution for (i = 0; i < number; i++) { int ii = index[i]; // get column int ij = pivotVariable_[ii]; double value = element[ii]; saveSolution[ii] = solution_[ij]; solution_[ij] -= movement * value; } //rowArray_[1]->setNumElements(0); // see where something went to #ifndef NDEBUG CoinRelFltEq eq(1.0e-7); #endif if (sequenceOut_ < 0) { if (directionIn_ < 0) { assert (eq(solution_[sequenceIn_], upperIn_)); solution_[sequenceIn_] = upperIn_; } else { assert (eq(solution_[sequenceIn_], lowerIn_)); solution_[sequenceIn_] = lowerIn_; } } else { if (directionOut_ < 0) { assert (eq(solution_[sequenceOut_], upperOut_)); solution_[sequenceOut_] = upperOut_; } else { assert (eq(solution_[sequenceOut_], lowerOut_)); solution_[sequenceOut_] = lowerOut_; } valueOut_ = solution_[sequenceOut_]; solution_[sequenceIn_] = valueIn_ + movement; } valueIn_ = solution_[sequenceIn_]; double objectiveChange = dualIn_ * movement; // update duals if (pivotRow_ >= 0) { if (fabs(alpha_) < 1.0e-8) { // be on safe side and clear arrays rowArray_[0]->clear(); rowArray_[1]->clear(); return -1; // will be singular } double multiplier = dualIn_ / alpha_; rowArray_[0]->insert(pivotRow_, multiplier); factorization_->updateColumnTranspose(rowArray_[2], rowArray_[0]); // put row of tableau in rowArray[0] and columnArray[0] matrix_->transposeTimes(this, -1.0, rowArray_[0], columnArray_[1], columnArray_[0]); // update column djs int i; int * index = columnArray_[0]->getIndices(); int number = columnArray_[0]->getNumElements(); double * element = columnArray_[0]->denseVector(); for (i = 0; i < number; i++) { int ii = index[i]; dj_[ii] += element[ii]; reducedCost_[ii] = dj_[ii]; element[ii] = 0.0; } columnArray_[0]->setNumElements(0); // and row djs index = rowArray_[0]->getIndices(); number = rowArray_[0]->getNumElements(); element = rowArray_[0]->denseVector(); for (i = 0; i < number; i++) { int ii = index[i]; dj_[ii+numberColumns_] += element[ii]; dual_[ii] = dj_[ii+numberColumns_]; element[ii] = 0.0; } rowArray_[0]->setNumElements(0); // check incoming assert (fabs(dj_[sequenceIn_]) < 1.0e-6 || CoinAbs(solveType_) == 2); } // if stable replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_); bool takePivot = true; // See if Factorization updated if (updateStatus) { updateSolution = false; returnCode = 1; } // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4 || fabs(alpha_) < 1.0e-6) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { returnCode = 1; } } else if (updateStatus == 2) { // major error - put back solution valueIn_ = oldValueIn; solution_[sequenceIn_] = valueIn_; int * index = rowArray_[1]->getIndices(); int number = rowArray_[1]->getNumElements(); for (i = 0; i < number; i++) { int ii = index[i]; // get column int ij = pivotVariable_[ii]; solution_[ij] = saveSolution[ii]; } if (sequenceOut_ >= 0) valueOut_ = solution_[sequenceOut_]; takePivot = false; if (factorization_->pivots()) { // refactorize here int factorStatus = internalFactorize(1); if (factorStatus) { printf("help in user pivot\n"); abort(); } gutsOfSolution(NULL, NULL); valueIn_ = solution_[sequenceIn_]; if (sequenceOut_ >= 0) valueOut_ = solution_[sequenceOut_]; roundAgain = true; } else { returnCode = -1; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); returnCode = 1; // factorize now } { // clear saveSolution int * index = rowArray_[1]->getIndices(); int number = rowArray_[1]->getNumElements(); for (i = 0; i < number; i++) { int ii = index[i]; saveSolution[ii] = 0.0; } } rowArray_[1]->clear(); if (takePivot) { int save = algorithm_; // make simple so always primal algorithm_ = 1; housekeeping(objectiveChange); algorithm_ = save; } } if (returnCode == 1) { // refactorize here int factorStatus = internalFactorize(1); if (factorStatus) { printf("help in user pivot\n"); abort(); } updateSolution = true; } if (updateSolution) { // just for now - recompute anyway gutsOfSolution(NULL, NULL); } return returnCode; } /* Pivot in a variable and choose an outgoing one. Assumes primal feasible - will not go through a bound. Returns step length in theta Returns ray in ray_ (or NULL if no pivot) Return codes as before but -1 means no acceptable pivot */ int ClpSimplex::primalPivotResult() { assert (sequenceIn_ >= 0); valueIn_ = solution_[sequenceIn_]; lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (!nonLinearCost_) nonLinearCost_ = new ClpNonLinearCost(this); int returnCode = static_cast (this)->pivotResult(); if (returnCode < 0 && returnCode > -4) { return 0; } else { COIN_DETAIL_PRINT(printf("Return code of %d from ClpSimplexPrimal::pivotResult\n", returnCode)); return -1; } } // Factorization frequency int ClpSimplex::factorizationFrequency() const { if (factorization_) return factorization_->maximumPivots(); else return -1; } void ClpSimplex::setFactorizationFrequency(int value) { if (factorization_) factorization_->maximumPivots(value); } // Common bits of coding for dual and primal int ClpSimplex::startup(int ifValuesPass, int startFinishOptions) { // Get rid of some arrays and empty factorization int useFactorization = false; if ((startFinishOptions & 2) != 0 && (whatsChanged_&(2 + 512)) == 2 + 512) useFactorization = true; // Keep factorization if possible #if 0 // seems to be needed if rows deleted later in CbcModel! if (!solution_ && scaledMatrix_) { // get rid of scaled matrix if (scaledMatrix_->getNumRows() != numberRows_) { delete scaledMatrix_; scaledMatrix_ = NULL; } } #endif // sanity check // bad if empty (trap here to avoid using bad matrix_) #if 0 // but also check bounds { int badProblem = 0; int i; for (i = 0; i < numberColumns_; i++) { if (columnLower_[i] > columnUpper_[i]) badProblem++; } for (i = 0; i < numberRows_; i++) { if (rowLower_[i] > rowUpper_[i]) badProblem++; } if (badProblem) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = badProblem; sumPrimalInfeasibilities_ = badProblem; secondaryStatus_ = 6; // so user can see something odd problemStatus_ = 1; bool printIt = (specialOptions_ & 32768) == 0 ? true : false; // no message if from Osi if (printIt) handler_->message(CLP_INFEASIBLE, messages_) << CoinMessageEol; return 2; } } #endif if (!matrix_ || (!matrix_->getNumElements() && objective_->type() < 2)) { int infeasNumber[2]; double infeasSum[2]; bool printIt = (specialOptions_ & 32768) == 0 ? true : false; // no message if from Osi problemStatus_ = emptyProblem(infeasNumber, infeasSum, printIt); if ((startFinishOptions & 1) != 0) { // User may expect user data - fill in as required if (numberRows_) { if (!pivotVariable_) pivotVariable_ = new int [numberRows_]; CoinIotaN(pivotVariable_, numberRows_, numberColumns_); } } numberDualInfeasibilities_ = infeasNumber[0]; sumDualInfeasibilities_ = infeasSum[0]; numberPrimalInfeasibilities_ = infeasNumber[1]; sumPrimalInfeasibilities_ = infeasSum[1]; return 2; } pivotRow_ = -1; sequenceIn_ = -1; sequenceOut_ = -1; secondaryStatus_ = 0; primalTolerance_ = dblParam_[ClpPrimalTolerance]; dualTolerance_ = dblParam_[ClpDualTolerance]; if (problemStatus_ != 10) numberIterations_ = 0; // put in standard form (and make row copy) // create modifiable copies of model rim and do optional scaling bool goodMatrix = createRim(7 + 8 + 16 + 32, true, startFinishOptions); if (goodMatrix) { // switch off factorization if bad if (pivotVariable_[0] < 0) useFactorization = false; // Model looks okay // Do initial factorization // and set certain stuff // We can either set increasing rows so ...IsBasic gives pivot row // or we can just increment iBasic one by one // for now let ...iBasic give pivot row int saveThreshold = factorization_->denseThreshold(); if (!useFactorization || factorization_->numberRows() != numberRows_) { useFactorization = false; factorization_->setDefaultValues(); // Switch off dense (unless special option set) if ((specialOptions_ & 8) == 0) factorization_->setDenseThreshold(0); } // If values pass then perturb (otherwise may be optimal so leave a bit) if (ifValuesPass) { // do perturbation if asked for if (perturbation_ < 100) { if (algorithm_ > 0 && (objective_->type() < 2 || !objective_->activated())) { #ifndef FEB_TRY //static_cast (this)->perturb(0); #endif } else if (algorithm_ < 0) { static_cast (this)->perturb(); } } } // for primal we will change bounds using infeasibilityCost_ if (nonLinearCost_ == NULL && algorithm_ > 0) { // get a valid nonlinear cost function nonLinearCost_ = new ClpNonLinearCost(this); } // loop round to clean up solution if values pass int numberThrownOut = -1; int totalNumberThrownOut = 0; problemStatus_ = -1; // see if we are re-using factorization if (!useFactorization) { while(numberThrownOut) { int status = internalFactorize(ifValuesPass ? 10 : 0); if (status < 0) return 1; // some error else numberThrownOut = status; // for this we need clean basis so it is after factorize if (!numberThrownOut || numberThrownOut == numberRows_ + 1) { // solution will be done again - skip if absolutely sure if ((specialOptions_ & 512) == 0 || numberThrownOut == numberRows_ + 1) { //int saveFirstFree=firstFree_; numberThrownOut = gutsOfSolution( NULL, NULL, ifValuesPass != 0); //firstFree_=saveFirstFree; if (largestPrimalError_ > 10.0 && !ifValuesPass && !numberThrownOut) { // throw out up to 1000 structurals int iRow; int * sort = new int[numberRows_]; double * array = rowArray_[0]->denseVector(); memset(array, 0, numberRows_ * sizeof(double)); times(-1.0, columnActivityWork_, array); int numberBasic = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_) { // column double difference = fabs(array[iRow] + rowActivityWork_[iRow]); if (difference > 1.0e-4) { sort[numberThrownOut] = iPivot; array[numberThrownOut++] = difference; if (getStatus(iPivot) == basic) numberBasic++; } } } if (!numberBasic) { allSlackBasis(true); numberThrownOut = 1; // force another go } else { CoinSort_2(array, array + numberThrownOut, sort); numberThrownOut = CoinMin(1000, numberThrownOut); for (iRow = 0; iRow < numberThrownOut; iRow++) { int iColumn = sort[iRow]; setColumnStatus(iColumn, superBasic); if (fabs(solution_[iColumn]) > 1.0e10) { if (upper_[iColumn] < 0.0) { solution_[iColumn] = upper_[iColumn]; } else if (lower_[iColumn] > 0.0) { solution_[iColumn] = lower_[iColumn]; } else { solution_[iColumn] = 0.0; } } } } CoinZeroN(array, numberRows_); delete [] sort; } } else { // make sure not optimal at once numberPrimalInfeasibilities_ = 1; numberThrownOut = 0; } } else { matrix_->rhsOffset(this, true); // redo rhs offset } totalNumberThrownOut += numberThrownOut; } } else { // using previous factorization - we assume fine if ((moreSpecialOptions_ & 8) == 0) { // but we need to say not optimal numberPrimalInfeasibilities_ = 1; numberDualInfeasibilities_ = 1; } matrix_->rhsOffset(this, true); // redo rhs offset } if (totalNumberThrownOut) handler_->message(CLP_SINGULARITIES, messages_) << totalNumberThrownOut << CoinMessageEol; // Switch back dense factorization_->setDenseThreshold(saveThreshold); if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilities_ && !ifValuesPass && (!nonLinearCost_ || !nonLinearCost_->numberInfeasibilities())) problemStatus_ = 0; else assert(problemStatus_ == -1); // number of times we have declared optimality numberTimesOptimal_ = 0; if (disasterArea_) disasterArea_->intoSimplex(); return 0; } else { // bad matrix return 2; } } /* Get a clean factorization - i.e. throw out singularities may do more later */ int ClpSimplex::cleanFactorization(int ifValuesPass) { int status = internalFactorize(ifValuesPass ? 10 : 0); if (status < 0) { return 1; // some error } else { firstFree_=0; return 0; } } void ClpSimplex::finish(int startFinishOptions) { // Get rid of some arrays and empty factorization int getRidOfData = 1; if (upper_ && ((startFinishOptions & 1) != 0 || problemStatus_ == 10)) { getRidOfData = 0; // Keep stuff // mark all as current whatsChanged_ = 0x3ffffff; } else { whatsChanged_ &= ~0xffff; } double saveObjValue = objectiveValue_; deleteRim(getRidOfData); if (matrix_->type()>=15) objectiveValue_ = saveObjValue; // Skip message if changing algorithms if (problemStatus_ != 10) { if (problemStatus_ == -1) problemStatus_ = 4; assert(problemStatus_ >= 0 && problemStatus_ < 6); if (handler_->detail(CLP_SIMPLEX_FINISHED, messages_) < 100) { handler_->message(CLP_SIMPLEX_FINISHED + problemStatus_, messages_) << objectiveValue() << CoinMessageEol; } } factorization_->relaxAccuracyCheck(1.0); // get rid of any network stuff - could do more factorization_->cleanUp(); } // Save data ClpDataSave ClpSimplex::saveData() { ClpDataSave saved; saved.dualBound_ = dualBound_; saved.infeasibilityCost_ = infeasibilityCost_; saved.sparseThreshold_ = factorization_->sparseThreshold(); saved.pivotTolerance_ = factorization_->pivotTolerance(); saved.zeroFactorizationTolerance_ = factorization_->zeroTolerance(); saved.zeroSimplexTolerance_ = zeroTolerance_; saved.perturbation_ = perturbation_; saved.forceFactorization_ = forceFactorization_; saved.acceptablePivot_ = acceptablePivot_; saved.objectiveScale_ = objectiveScale_; // Progress indicator progress_.fillFromModel (this); return saved; } // Restore data void ClpSimplex::restoreData(ClpDataSave saved) { //factorization_->sparseThreshold(saved.sparseThreshold_); factorization_->pivotTolerance(saved.pivotTolerance_); factorization_->zeroTolerance(saved.zeroFactorizationTolerance_); zeroTolerance_ = saved.zeroSimplexTolerance_; perturbation_ = saved.perturbation_; infeasibilityCost_ = saved.infeasibilityCost_; dualBound_ = saved.dualBound_; forceFactorization_ = saved.forceFactorization_; objectiveScale_ = saved.objectiveScale_; acceptablePivot_ = saved.acceptablePivot_; } // To flag a variable (not inline to allow for column generation) void ClpSimplex::setFlagged( int sequence) { status_[sequence] |= 64; matrix_->generalExpanded(this, 7, sequence); lastFlaggedIteration_ = numberIterations_; } /* Factorizes and returns true if optimal. Used by user */ bool ClpSimplex::statusOfProblem(bool initial) { // We don't want scaling int saveFlag = scalingFlag_; if (!rowScale_) scalingFlag_ = 0; bool goodMatrix = createRim(7 + 8 + 16 + 32); if (!goodMatrix) { problemStatus_ = 4; scalingFlag_ = saveFlag; return false; } // is factorization okay? if (initial) { // First time - allow singularities int numberThrownOut = -1; int totalNumberThrownOut = 0; while(numberThrownOut) { int status = internalFactorize(0); if (status == numberRows_ + 1) status = 0; // all slack if (status < 0) { deleteRim(-1); scalingFlag_ = saveFlag; return false; // some error } else { numberThrownOut = status; } // for this we need clean basis so it is after factorize //if (!numberThrownOut) //numberThrownOut = gutsOfSolution( NULL,NULL, // false); //else //matrix_->rhsOffset(this,true); // redo rhs offset totalNumberThrownOut += numberThrownOut; } if (totalNumberThrownOut) handler_->message(CLP_SINGULARITIES, messages_) << totalNumberThrownOut << CoinMessageEol; } else { #ifndef NDEBUG int returnCode = internalFactorize(1); assert (!returnCode); #else internalFactorize(1); #endif } CoinMemcpyN(rowActivity_, numberRows_, rowActivityWork_); CoinMemcpyN(columnActivity_, numberColumns_, columnActivityWork_); gutsOfSolution(NULL, NULL); CoinMemcpyN(rowActivityWork_, numberRows_, rowActivity_); CoinMemcpyN(columnActivityWork_, numberColumns_, columnActivity_); CoinMemcpyN(dj_, numberColumns_, reducedCost_); deleteRim(-1); scalingFlag_ = saveFlag; return (primalFeasible() && dualFeasible()); } /* Return model - updates any scalars */ void ClpSimplex::returnModel(ClpSimplex & otherModel) { ClpModel::returnModel(otherModel); otherModel.bestPossibleImprovement_ = bestPossibleImprovement_; otherModel.columnPrimalSequence_ = columnPrimalSequence_; otherModel.zeroTolerance_ = zeroTolerance_; otherModel.rowPrimalSequence_ = rowPrimalSequence_; otherModel.bestObjectiveValue_ = bestObjectiveValue_; otherModel.moreSpecialOptions_ = moreSpecialOptions_; otherModel.baseIteration_ = baseIteration_; otherModel.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_; otherModel.largestPrimalError_ = largestPrimalError_; otherModel.largestDualError_ = largestDualError_; otherModel.alphaAccuracy_ = alphaAccuracy_; otherModel.alpha_ = alpha_; otherModel.theta_ = theta_; otherModel.lowerIn_ = lowerIn_; otherModel.valueIn_ = valueIn_; otherModel.upperIn_ = upperIn_; otherModel.dualIn_ = dualIn_; otherModel.sequenceIn_ = sequenceIn_; otherModel.directionIn_ = directionIn_; otherModel.lowerOut_ = lowerOut_; otherModel.valueOut_ = valueOut_; otherModel.upperOut_ = upperOut_; otherModel.dualOut_ = dualOut_; otherModel.sequenceOut_ = sequenceOut_; otherModel.directionOut_ = directionOut_; otherModel.pivotRow_ = pivotRow_; otherModel.algorithm_ = algorithm_; otherModel.sumDualInfeasibilities_ = sumDualInfeasibilities_; otherModel.numberDualInfeasibilities_ = numberDualInfeasibilities_; otherModel.numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilitiesWithoutFree_; otherModel.sumPrimalInfeasibilities_ = sumPrimalInfeasibilities_; otherModel.numberPrimalInfeasibilities_ = numberPrimalInfeasibilities_; otherModel.numberTimesOptimal_ = numberTimesOptimal_; otherModel.disasterArea_ = NULL; otherModel.sumOfRelaxedDualInfeasibilities_ = sumOfRelaxedDualInfeasibilities_; otherModel.sumOfRelaxedPrimalInfeasibilities_ = sumOfRelaxedPrimalInfeasibilities_; if (perturbationArray_ != otherModel.perturbationArray_) delete [] perturbationArray_; perturbationArray_ = NULL; } /* Constructs a non linear cost from list of non-linearities (columns only) First lower of each column is taken as real lower Last lower is taken as real upper and cost ignored Returns nonzero if bad data e.g. lowers not monotonic */ int ClpSimplex::createPiecewiseLinearCosts(const int * starts, const double * lower, const double * gradient) { delete nonLinearCost_; // Set up feasible bounds and check monotonicity int iColumn; int returnCode = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { int iIndex = starts[iColumn]; int end = starts[iColumn+1] - 1; columnLower_[iColumn] = lower[iIndex]; columnUpper_[iColumn] = lower[end]; double value = columnLower_[iColumn]; iIndex++; for (; iIndex < end; iIndex++) { if (lower[iIndex] < value) returnCode++; // not monotonic value = lower[iIndex]; } } nonLinearCost_ = new ClpNonLinearCost(this, starts, lower, gradient); specialOptions_ |= 2; // say keep return returnCode; } /* For advanced use. When doing iterative solves things can get nasty so on values pass if incoming solution has largest infeasibility < incomingInfeasibility throw out variables from basis until largest infeasibility < allowedInfeasibility or incoming largest infeasibility. If allowedInfeasibility>= incomingInfeasibility this is always possible altough you may end up with an all slack basis. Defaults are 1.0,10.0 */ void ClpSimplex::setValuesPassAction(double incomingInfeasibility, double allowedInfeasibility) { incomingInfeasibility_ = incomingInfeasibility; allowedInfeasibility_ = allowedInfeasibility; CoinAssert(incomingInfeasibility_ >= 0.0); CoinAssert(allowedInfeasibility_ >= incomingInfeasibility_); } // Allow initial dense factorization void ClpSimplex::setInitialDenseFactorization(bool onOff) { if (onOff) specialOptions_ |= 8; else specialOptions_ &= ~8; } bool ClpSimplex::initialDenseFactorization() const { return (specialOptions_ & 8) != 0; } /* This constructor modifies original ClpSimplex and stores original stuff in created ClpSimplex. It is only to be used in conjunction with originalModel */ ClpSimplex::ClpSimplex (ClpSimplex * wholeModel, int numberColumns, const int * whichColumns) { // Set up dummy row selection list numberRows_ = wholeModel->numberRows_; int * whichRow = new int [numberRows_]; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) whichRow[iRow] = iRow; // ClpModel stuff (apart from numberColumns_) matrix_ = wholeModel->matrix_; rowCopy_ = wholeModel->rowCopy_; if (wholeModel->rowCopy_) { // note reversal of order wholeModel->rowCopy_ = wholeModel->rowCopy_->subsetClone(numberRows_, whichRow, numberColumns, whichColumns); } else { wholeModel->rowCopy_ = NULL; } whatsChanged_ &= ~0xffff; CoinAssert (wholeModel->matrix_); wholeModel->matrix_ = wholeModel->matrix_->subsetClone(numberRows_, whichRow, numberColumns, whichColumns); delete [] whichRow; numberColumns_ = wholeModel->numberColumns_; // Now ClpSimplex stuff and status_ delete wholeModel->primalColumnPivot_; wholeModel->primalColumnPivot_ = new ClpPrimalColumnSteepest(0); nonLinearCost_ = wholeModel->nonLinearCost_; // Now main arrays int iColumn; int numberTotal = numberRows_ + numberColumns; COIN_DETAIL_PRINT(printf("%d %d %d\n", numberTotal, numberRows_, numberColumns)); // mapping int * mapping = new int[numberRows_+numberColumns_]; for (iColumn = 0; iColumn < numberColumns_; iColumn++) mapping[iColumn] = -1; for (iRow = 0; iRow < numberRows_; iRow++) mapping[iRow+numberColumns_] = iRow + numberColumns; // Redo costs and bounds of whole model wholeModel->createRim(1 + 4, false); lower_ = wholeModel->lower_; wholeModel->lower_ = new double [numberTotal]; CoinMemcpyN(lower_ + numberColumns_, numberRows_, wholeModel->lower_ + numberColumns); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = whichColumns[iColumn]; wholeModel->lower_[iColumn] = lower_[jColumn]; // and pointer back mapping[jColumn] = iColumn; } #ifdef CLP_DEBUG for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) printf("mapx %d %d\n", iColumn, mapping[iColumn]); #endif // Re-define pivotVariable_ for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = wholeModel->pivotVariable_[iRow]; wholeModel->pivotVariable_[iRow] = mapping[iPivot]; #ifdef CLP_DEBUG printf("p row %d, pivot %d -> %d\n", iRow, iPivot, mapping[iPivot]); #endif assert (wholeModel->pivotVariable_[iRow] >= 0); } // Reverse mapping (so extended version of whichColumns) for (iColumn = 0; iColumn < numberColumns; iColumn++) mapping[iColumn] = whichColumns[iColumn]; for (; iColumn < numberRows_ + numberColumns; iColumn++) mapping[iColumn] = iColumn + (numberColumns_ - numberColumns); #ifdef CLP_DEBUG for (iColumn = 0; iColumn < numberRows_ + numberColumns; iColumn++) printf("map %d %d\n", iColumn, mapping[iColumn]); #endif // Save mapping somewhere - doesn't matter rowUpper_ = reinterpret_cast (mapping); upper_ = wholeModel->upper_; wholeModel->upper_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->upper_[iColumn] = upper_[jColumn]; } cost_ = wholeModel->cost_; wholeModel->cost_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->cost_[iColumn] = cost_[jColumn]; } dj_ = wholeModel->dj_; wholeModel->dj_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->dj_[iColumn] = dj_[jColumn]; } solution_ = wholeModel->solution_; wholeModel->solution_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->solution_[iColumn] = solution_[jColumn]; } // now see what variables left out do to row solution double * rowSolution = wholeModel->solution_ + numberColumns; double * fullSolution = solution_; double * sumFixed = new double[numberRows_]; memset (sumFixed, 0, numberRows_ * sizeof(double)); // zero out ones in small problem for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = mapping[iColumn]; fullSolution[jColumn] = 0.0; } // Get objective offset double originalOffset; wholeModel->getDblParam(ClpObjOffset, originalOffset); double offset = 0.0; const double * cost = cost_; for (iColumn = 0; iColumn < numberColumns_; iColumn++) offset += fullSolution[iColumn] * cost[iColumn]; wholeModel->setDblParam(ClpObjOffset, originalOffset - offset); setDblParam(ClpObjOffset, originalOffset); matrix_->times(1.0, fullSolution, sumFixed, wholeModel->rowScale_, wholeModel->columnScale_); double * lower = lower_ + numberColumns; double * upper = upper_ + numberColumns; double fixed = 0.0; for (iRow = 0; iRow < numberRows_; iRow++) { fixed += fabs(sumFixed[iRow]); if (lower[iRow] > -1.0e50) lower[iRow] -= sumFixed[iRow]; if (upper[iRow] < 1.0e50) upper[iRow] -= sumFixed[iRow]; rowSolution[iRow] -= sumFixed[iRow]; } COIN_DETAIL_PRINT(printf("offset %g sumfixed %g\n", offset, fixed)); delete [] sumFixed; columnScale_ = wholeModel->columnScale_; if (columnScale_) { wholeModel->columnScale_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->columnScale_[iColumn] = columnScale_[jColumn]; } } status_ = wholeModel->status_; wholeModel->status_ = new unsigned char [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->status_[iColumn] = status_[jColumn]; } savedSolution_ = wholeModel->savedSolution_; if (savedSolution_) { wholeModel->savedSolution_ = new double [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->savedSolution_[iColumn] = savedSolution_[jColumn]; } } saveStatus_ = wholeModel->saveStatus_; if (saveStatus_) { wholeModel->saveStatus_ = new unsigned char [numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; wholeModel->saveStatus_[iColumn] = saveStatus_[jColumn]; } } wholeModel->numberColumns_ = numberColumns; // Initialize weights wholeModel->primalColumnPivot_->saveWeights(wholeModel, 2); // Costs wholeModel->nonLinearCost_ = new ClpNonLinearCost(wholeModel); wholeModel->nonLinearCost_->checkInfeasibilities(); COIN_DETAIL_PRINT(printf("after contraction %d infeasibilities summing to %g\n", nonLinearCost_->numberInfeasibilities(), nonLinearCost_->sumInfeasibilities())); // Redo some stuff wholeModel->reducedCostWork_ = wholeModel->dj_; wholeModel->rowReducedCost_ = wholeModel->dj_ + wholeModel->numberColumns_; wholeModel->columnActivityWork_ = wholeModel->solution_; wholeModel->rowActivityWork_ = wholeModel->solution_ + wholeModel->numberColumns_; wholeModel->objectiveWork_ = wholeModel->cost_; wholeModel->rowObjectiveWork_ = wholeModel->cost_ + wholeModel->numberColumns_; wholeModel->rowLowerWork_ = wholeModel->lower_ + wholeModel->numberColumns_; wholeModel->columnLowerWork_ = wholeModel->lower_; wholeModel->rowUpperWork_ = wholeModel->upper_ + wholeModel->numberColumns_; wholeModel->columnUpperWork_ = wholeModel->upper_; #ifndef NDEBUG // Check status ClpSimplex * xxxx = wholeModel; int nBasic = 0; for (iColumn = 0; iColumn < xxxx->numberRows_ + xxxx->numberColumns_; iColumn++) if (xxxx->getStatus(iColumn) == basic) nBasic++; assert (nBasic == xxxx->numberRows_); for (iRow = 0; iRow < xxxx->numberRows_; iRow++) { int iPivot = xxxx->pivotVariable_[iRow]; assert (xxxx->getStatus(iPivot) == basic); } #endif } /* This copies back stuff from miniModel and then deletes miniModel. Only to be used with mini constructor */ void ClpSimplex::originalModel(ClpSimplex * miniModel) { int numberSmall = numberColumns_; numberColumns_ = miniModel->numberColumns_; int numberTotal = numberSmall + numberRows_; // copy back int iColumn; int * mapping = reinterpret_cast (miniModel->rowUpper_); #ifdef CLP_DEBUG for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) printf("mapb %d %d\n", iColumn, mapping[iColumn]); #endif // miniModel actually has full arrays // now see what variables left out do to row solution double * fullSolution = miniModel->solution_; double * sumFixed = new double[numberRows_]; memset (sumFixed, 0, numberRows_ * sizeof(double)); miniModel->matrix_->times(1.0, fullSolution, sumFixed, rowScale_, miniModel->columnScale_); for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; miniModel->lower_[jColumn] = lower_[iColumn]; miniModel->upper_[jColumn] = upper_[iColumn]; miniModel->cost_[jColumn] = cost_[iColumn]; miniModel->dj_[jColumn] = dj_[iColumn]; miniModel->solution_[jColumn] = solution_[iColumn]; miniModel->status_[jColumn] = status_[iColumn]; #ifdef CLP_DEBUG printf("%d in small -> %d in original\n", iColumn, jColumn); #endif } delete [] lower_; lower_ = miniModel->lower_; delete [] upper_; upper_ = miniModel->upper_; delete [] cost_; cost_ = miniModel->cost_; delete [] dj_; dj_ = miniModel->dj_; delete [] solution_; solution_ = miniModel->solution_; delete [] status_; status_ = miniModel->status_; if (columnScale_) { for (iColumn = 0; iColumn < numberSmall; iColumn++) { int jColumn = mapping[iColumn]; miniModel->columnScale_[jColumn] = columnScale_[iColumn]; } delete [] columnScale_; columnScale_ = miniModel->columnScale_; } if (savedSolution_) { if (!miniModel->savedSolution_) { miniModel->savedSolution_ = ClpCopyOfArray(solution_, numberColumns_ + numberRows_); } else { for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; miniModel->savedSolution_[jColumn] = savedSolution_[iColumn]; } } delete [] savedSolution_; savedSolution_ = miniModel->savedSolution_; } if (saveStatus_) { if (!miniModel->saveStatus_) { miniModel->saveStatus_ = ClpCopyOfArray(status_, numberColumns_ + numberRows_); } else { for (iColumn = 0; iColumn < numberTotal; iColumn++) { int jColumn = mapping[iColumn]; miniModel->saveStatus_[jColumn] = saveStatus_[iColumn]; } } delete [] saveStatus_; saveStatus_ = miniModel->saveStatus_; } // Re-define pivotVariable_ int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; #ifdef CLP_DEBUG printf("pb row %d, pivot %d -> %d\n", iRow, iPivot, mapping[iPivot]); #endif pivotVariable_[iRow] = mapping[iPivot]; assert (pivotVariable_[iRow] >= 0); } // delete stuff and move back delete matrix_; delete rowCopy_; delete primalColumnPivot_; delete nonLinearCost_; matrix_ = miniModel->matrix_; rowCopy_ = miniModel->rowCopy_; nonLinearCost_ = miniModel->nonLinearCost_; double originalOffset; miniModel->getDblParam(ClpObjOffset, originalOffset); setDblParam(ClpObjOffset, originalOffset); // Redo some stuff reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; columnActivityWork_ = solution_; rowActivityWork_ = solution_ + numberColumns_; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; // Cleanup for (iRow = 0; iRow < numberRows_; iRow++) { double value = rowActivityWork_[iRow] + sumFixed[iRow]; rowActivityWork_[iRow] = value; switch(getRowStatus(iRow)) { case basic: break; case atUpperBound: //rowActivityWork_[iRow]=rowUpperWork_[iRow]; break; case ClpSimplex::isFixed: case atLowerBound: //rowActivityWork_[iRow]=rowLowerWork_[iRow]; break; case isFree: break; // superbasic case superBasic: break; } } delete [] sumFixed; nonLinearCost_->checkInfeasibilities(); COIN_DETAIL_PRINT(printf("in original %d infeasibilities summing to %g\n", nonLinearCost_->numberInfeasibilities(), nonLinearCost_->sumInfeasibilities())); // Initialize weights primalColumnPivot_ = new ClpPrimalColumnSteepest(10); primalColumnPivot_->saveWeights(this, 2); #ifndef NDEBUG // Check status ClpSimplex * xxxx = this; int nBasic = 0; for (iColumn = 0; iColumn < xxxx->numberRows_ + xxxx->numberColumns_; iColumn++) if (xxxx->getStatus(iColumn) == basic) nBasic++; assert (nBasic == xxxx->numberRows_); for (iRow = 0; iRow < xxxx->numberRows_; iRow++) { int iPivot = xxxx->pivotVariable_[iRow]; assert (xxxx->getStatus(iPivot) == basic); } #endif } // Pass in Event handler (cloned and deleted at end) void ClpSimplex::passInEventHandler(const ClpEventHandler * eventHandler) { delete eventHandler_; eventHandler_ = eventHandler->clone(); eventHandler_->setSimplex(this); } #ifndef NDEBUG // For errors to make sure print to screen // only called in debug mode static void indexError(int index, std::string methodName) { std::cerr << "Illegal index " << index << " in ClpSimplex::" << methodName << std::endl; throw CoinError("Illegal index", methodName, "ClpSimplex"); } #endif // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal) //Get a row of the tableau (slack part in slack if not NULL) void ClpSimplex::getBInvARow(int row, double* z, double * slack) { #ifndef NDEBUG int n = numberRows(); if (row < 0 || row >= n) { indexError(row, "getBInvARow"); } #endif if (!rowArray_[0]) { printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n"); abort(); } CoinIndexedVector * rowArray0 = rowArray(0); CoinIndexedVector * rowArray1 = rowArray(1); CoinIndexedVector * columnArray0 = columnArray(0); CoinIndexedVector * columnArray1 = columnArray(1); rowArray0->clear(); rowArray1->clear(); columnArray0->clear(); columnArray1->clear(); // put +1 in row // But swap if pivot variable was slack as clp stores slack as -1.0 int pivot = pivotVariable_[row]; double value; // And if scaled then adjust if (!rowScale_) { if (pivot < numberColumns_) value = 1.0; else value = -1.0; } else { if (pivot < numberColumns_) value = columnScale_[pivot]; else value = -1.0 * inverseRowScale_[pivot-numberColumns_]; } rowArray1->insert(row, value); factorization_->updateColumnTranspose(rowArray0, rowArray1); // put row of tableau in rowArray1 and columnArray0 clpMatrix()->transposeTimes(this, 1.0, rowArray1, columnArray1, columnArray0); if (!rowScale_) { CoinMemcpyN(columnArray0->denseVector(), numberColumns_, z); } else { double * array = columnArray0->denseVector(); for (int i = 0; i < numberColumns_; i++) z[i] = array[i] * inverseColumnScale_[i]; } if (slack) { if (!rowScale_) { CoinMemcpyN(rowArray1->denseVector(), numberRows_, slack); } else { double * array = rowArray1->denseVector(); for (int i = 0; i < numberRows_; i++) slack[i] = array[i] * rowScale_[i]; } } // don't need to clear everything always, but doesn't cost rowArray0->clear(); rowArray1->clear(); columnArray0->clear(); columnArray1->clear(); } //Get a row of the basis inverse void ClpSimplex::getBInvRow(int row, double* z) { #ifndef NDEBUG int n = numberRows(); if (row < 0 || row >= n) { indexError(row, "getBInvRow"); } #endif if (!rowArray_[0]) { printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n"); abort(); } ClpFactorization * factorization = factorization_; CoinIndexedVector * rowArray0 = rowArray(0); CoinIndexedVector * rowArray1 = rowArray(1); rowArray0->clear(); rowArray1->clear(); // put +1 in row // But swap if pivot variable was slack as clp stores slack as -1.0 double value = (pivotVariable_[row] < numberColumns_) ? 1.0 : -1.0; // but scale if (rowScale_) { int pivot = pivotVariable_[row]; if (pivot < numberColumns_) value *= columnScale_[pivot]; else value /= rowScale_[pivot-numberColumns_]; } rowArray1->insert(row, value); factorization->updateColumnTranspose(rowArray0, rowArray1); if (!rowScale_) { CoinMemcpyN(rowArray1->denseVector(), numberRows_, z); } else { double * array = rowArray1->denseVector(); for (int i = 0; i < numberRows_; i++) { z[i] = array[i] * rowScale_[i]; } } rowArray1->clear(); } //Get a column of the tableau void ClpSimplex::getBInvACol(int col, double* vec) { if (!rowArray_[0]) { printf("ClpSimplexPrimal or ClpSimplexDual should have been called with correct startFinishOption\n"); abort(); } CoinIndexedVector * rowArray0 = rowArray(0); CoinIndexedVector * rowArray1 = rowArray(1); rowArray0->clear(); rowArray1->clear(); // get column of matrix #ifndef NDEBUG int n = numberColumns_ + numberRows_; if (col < 0 || col >= n) { indexError(col, "getBInvACol"); } #endif if (!rowScale_) { if (col < numberColumns_) { unpack(rowArray1, col); } else { rowArray1->insert(col - numberColumns_, 1.0); } } else { if (col < numberColumns_) { unpack(rowArray1, col); double multiplier = 1.0 * inverseColumnScale_[col]; int number = rowArray1->getNumElements(); int * index = rowArray1->getIndices(); double * array = rowArray1->denseVector(); for (int i = 0; i < number; i++) { int iRow = index[i]; // make sure not packed assert (array[iRow]); array[iRow] *= multiplier; } } else { rowArray1->insert(col - numberColumns_, rowScale_[col-numberColumns_]); } } factorization_->updateColumn(rowArray0, rowArray1, false); // But swap if pivot variable was slack as clp stores slack as -1.0 double * array = rowArray1->denseVector(); if (!rowScale_) { for (int i = 0; i < numberRows_; i++) { double multiplier = (pivotVariable_[i] < numberColumns_) ? 1.0 : -1.0; vec[i] = multiplier * array[i]; } } else { for (int i = 0; i < numberRows_; i++) { int pivot = pivotVariable_[i]; if (pivot < numberColumns_) vec[i] = array[i] * columnScale_[pivot]; else vec[i] = - array[i] / rowScale_[pivot-numberColumns_]; } } rowArray1->clear(); } //Get a column of the basis inverse void ClpSimplex::getBInvCol(int col, double* vec) { if (!rowArray_[0]) { printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n"); abort(); } CoinIndexedVector * rowArray0 = rowArray(0); CoinIndexedVector * rowArray1 = rowArray(1); rowArray0->clear(); rowArray1->clear(); #ifndef NDEBUG int n = numberRows(); if (col < 0 || col >= n) { indexError(col, "getBInvCol"); } #endif // put +1 in row // but scale double value; if (!rowScale_) { value = 1.0; } else { value = rowScale_[col]; } rowArray1->insert(col, value); factorization_->updateColumn(rowArray0, rowArray1, false); // But swap if pivot variable was slack as clp stores slack as -1.0 double * array = rowArray1->denseVector(); if (!rowScale_) { for (int i = 0; i < numberRows_; i++) { double multiplier = (pivotVariable_[i] < numberColumns_) ? 1.0 : -1.0; vec[i] = multiplier * array[i]; } } else { for (int i = 0; i < numberRows_; i++) { int pivot = pivotVariable_[i]; double value = array[i]; if (pivot < numberColumns_) vec[i] = value * columnScale_[pivot]; else vec[i] = - value / rowScale_[pivot-numberColumns_]; } } rowArray1->clear(); } /* Get basic indices (order of indices corresponds to the order of elements in a vector retured by getBInvACol() and getBInvCol()). */ void ClpSimplex::getBasics(int* index) { if (!rowArray_[0]) { printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n"); abort(); } CoinAssert (index); CoinMemcpyN(pivotVariable(), numberRows(), index); } /* Set an objective function coefficient */ void ClpSimplex::setObjectiveCoefficient( int elementIndex, double elementValue ) { #ifndef NDEBUG if (elementIndex < 0 || elementIndex >= numberColumns_) { indexError(elementIndex, "setObjectiveCoefficient"); } #endif if (objective()[elementIndex] != elementValue) { objective()[elementIndex] = elementValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~64; double direction = optimizationDirection_ * objectiveScale_; if (!rowScale_) { objectiveWork_[elementIndex] = direction * elementValue; } else { objectiveWork_[elementIndex] = direction * elementValue * columnScale_[elementIndex]; } } } } /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void ClpSimplex::setRowLower( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (rowLower_[elementIndex] != elementValue) { rowLower_[elementIndex] = elementValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~16; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { rowLowerWork_[elementIndex] = -COIN_DBL_MAX; } else if (!rowScale_) { rowLowerWork_[elementIndex] = elementValue * rhsScale_; } else { rowLowerWork_[elementIndex] = elementValue * rhsScale_ * rowScale_[elementIndex]; } } } } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void ClpSimplex::setRowUpper( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (rowUpper_[elementIndex] != elementValue) { rowUpper_[elementIndex] = elementValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~32; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { rowUpperWork_[elementIndex] = COIN_DBL_MAX; } else if (!rowScale_) { rowUpperWork_[elementIndex] = elementValue * rhsScale_; } else { rowUpperWork_[elementIndex] = elementValue * rhsScale_ * rowScale_[elementIndex]; } } } } /* Set a single row lower and upper bound */ void ClpSimplex::setRowBounds( int elementIndex, double lowerValue, double upperValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[elementIndex] != lowerValue) { rowLower_[elementIndex] = lowerValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~16; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { rowLowerWork_[elementIndex] = -COIN_DBL_MAX; } else if (!rowScale_) { rowLowerWork_[elementIndex] = lowerValue * rhsScale_; } else { rowLowerWork_[elementIndex] = lowerValue * rhsScale_ * rowScale_[elementIndex]; } } } if (rowUpper_[elementIndex] != upperValue) { rowUpper_[elementIndex] = upperValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~32; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { rowUpperWork_[elementIndex] = COIN_DBL_MAX; } else if (!rowScale_) { rowUpperWork_[elementIndex] = upperValue * rhsScale_; } else { rowUpperWork_[elementIndex] = upperValue * rhsScale_ * rowScale_[elementIndex]; } } } } void ClpSimplex::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #ifndef NDEBUG int n = numberRows_; #endif int numberChanged = 0; const int * saveFirst = indexFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; #ifndef NDEBUG if (iRow < 0 || iRow >= n) { indexError(iRow, "setRowSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[iRow] != lowerValue) { rowLower_[iRow] = lowerValue; whatsChanged_ &= ~16; numberChanged++; } if (rowUpper_[iRow] != upperValue) { rowUpper_[iRow] = upperValue; whatsChanged_ &= ~32; numberChanged++; } } if (numberChanged && (whatsChanged_ & 1) != 0) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; if (rowLower_[iRow] == -COIN_DBL_MAX) { rowLowerWork_[iRow] = -COIN_DBL_MAX; } else if (!rowScale_) { rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_; } else { rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_ * rowScale_[iRow]; } if (rowUpper_[iRow] == COIN_DBL_MAX) { rowUpperWork_[iRow] = COIN_DBL_MAX; } else if (!rowScale_) { rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_; } else { rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_ * rowScale_[iRow]; } } } } //----------------------------------------------------------------------------- /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void ClpSimplex::setColumnLower( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != elementValue) { columnLower_[elementIndex] = elementValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~128; double value; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { value = -COIN_DBL_MAX; } else if (!columnScale_) { value = elementValue * rhsScale_; } else { value = elementValue * rhsScale_ / columnScale_[elementIndex]; } lower_[elementIndex] = value; if (maximumRows_ >= 0) lower_[elementIndex+maximumRows_+maximumColumns_] = value; } } } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void ClpSimplex::setColumnUpper( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (columnUpper_[elementIndex] != elementValue) { columnUpper_[elementIndex] = elementValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~256; double value; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { value = COIN_DBL_MAX; } else if (!columnScale_) { value = elementValue * rhsScale_; } else { value = elementValue * rhsScale_ / columnScale_[elementIndex]; } //assert (columnUpperWork_==upper_); upper_[elementIndex] = value; if (maximumRows_ >= 0) upper_[elementIndex+maximumRows_+maximumColumns_] = value; } } } /* Set a single column lower and upper bound */ void ClpSimplex::setColumnBounds( int elementIndex, double lowerValue, double upperValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != lowerValue) { columnLower_[elementIndex] = lowerValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~128; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { lower_[elementIndex] = -COIN_DBL_MAX; } else if (!columnScale_) { lower_[elementIndex] = lowerValue * rhsScale_; } else { lower_[elementIndex] = lowerValue * rhsScale_ / columnScale_[elementIndex]; } } } if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (columnUpper_[elementIndex] != upperValue) { columnUpper_[elementIndex] = upperValue; if ((whatsChanged_ & 1) != 0) { // work arrays exist - update as well whatsChanged_ &= ~256; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { upper_[elementIndex] = COIN_DBL_MAX; } else if (!columnScale_) { upper_[elementIndex] = upperValue * rhsScale_; } else { upper_[elementIndex] = upperValue * rhsScale_ / columnScale_[elementIndex]; } } } } void ClpSimplex::setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #ifndef NDEBUG int n = numberColumns_; #endif int numberChanged = 0; const int * saveFirst = indexFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; #ifndef NDEBUG if (iColumn < 0 || iColumn >= n) { indexError(iColumn, "setColumnSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (columnLower_[iColumn] != lowerValue) { columnLower_[iColumn] = lowerValue; whatsChanged_ &= ~16; numberChanged++; } if (columnUpper_[iColumn] != upperValue) { columnUpper_[iColumn] = upperValue; whatsChanged_ &= ~32; numberChanged++; } } if (numberChanged && (whatsChanged_ & 1) != 0) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; if (columnLower_[iColumn] == -COIN_DBL_MAX) { lower_[iColumn] = -COIN_DBL_MAX; } else if (!columnScale_) { lower_[iColumn] = columnLower_[iColumn] * rhsScale_; } else { lower_[iColumn] = columnLower_[iColumn] * rhsScale_ / columnScale_[iColumn]; } if (columnUpper_[iColumn] == COIN_DBL_MAX) { upper_[iColumn] = COIN_DBL_MAX; } else if (!columnScale_) { upper_[iColumn] = columnUpper_[iColumn] * rhsScale_; } else { upper_[iColumn] = columnUpper_[iColumn] * rhsScale_ / columnScale_[iColumn]; } } } } /* Just check solution (for internal use) - sets sum of infeasibilities etc. */ void ClpSimplex::checkSolutionInternal() { double dualTolerance = dblParam_[ClpDualTolerance]; double primalTolerance = dblParam_[ClpPrimalTolerance]; double nonLinearOffset = 0.0; const double * objective = objective_->gradient(this, columnActivity_, nonLinearOffset, true); int iRow, iColumn; assert (!rowObjective_); objectiveValue_ = -nonLinearOffset; // now look at solution sumPrimalInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; double maxmin = optimizationDirection_; for (iRow = 0; iRow < numberRows_; iRow++) { double dualValue = dual_[iRow] * maxmin; double primalValue = rowActivity_[iRow]; double lower = rowLower_[iRow]; double upper = rowUpper_[iRow]; ClpSimplex::Status status = getRowStatus(iRow); if (status != basic) { if (lower == upper) { status = ClpSimplex::isFixed; } else if (primalValue > upper - primalTolerance) { status = ClpSimplex::atUpperBound; } else if (primalValue < lower + primalTolerance) { status = ClpSimplex::atLowerBound; } setRowStatus(iRow, status); } if (primalValue > upper + primalTolerance) { sumPrimalInfeasibilities_ += primalValue - upper - primalTolerance; numberPrimalInfeasibilities_ ++; } else if (primalValue < lower - primalTolerance) { sumPrimalInfeasibilities_ += lower - primalValue - primalTolerance; numberPrimalInfeasibilities_ ++; } else { switch(status) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: // dual should not be positive if (dualValue > dualTolerance) { sumDualInfeasibilities_ += dualValue - dualTolerance_; numberDualInfeasibilities_ ++; } break; case atLowerBound: // dual should not be negative if (dualValue < -dualTolerance) { sumDualInfeasibilities_ -= dualValue + dualTolerance_; numberDualInfeasibilities_ ++; } break; case superBasic: case isFree: if (primalValue < upper - primalTolerance) { // dual should not be negative if (dualValue < -dualTolerance) { sumDualInfeasibilities_ -= dualValue + dualTolerance_; numberDualInfeasibilities_ ++; } } if (primalValue > lower + primalTolerance) { // dual should not be positive if (dualValue > dualTolerance) { sumDualInfeasibilities_ += dualValue - dualTolerance_; numberDualInfeasibilities_ ++; } } break; } } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double dualValue = reducedCost_[iColumn] * maxmin; double primalValue = columnActivity_[iColumn]; objectiveValue_ += objective[iColumn] * primalValue; double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; ClpSimplex::Status status = getColumnStatus(iColumn); if (status != basic && lower == upper) { status = ClpSimplex::isFixed; setColumnStatus(iColumn, ClpSimplex::isFixed); } if (primalValue > upper + primalTolerance) { sumPrimalInfeasibilities_ += primalValue - upper - primalTolerance; numberPrimalInfeasibilities_ ++; } else if (primalValue < lower - primalTolerance) { sumPrimalInfeasibilities_ += lower - primalValue - primalTolerance; numberPrimalInfeasibilities_ ++; } else { switch(status) { case basic: // dual should be zero if (fabs(dualValue) > 10.0 * dualTolerance) { sumDualInfeasibilities_ += fabs(dualValue) - dualTolerance_; numberDualInfeasibilities_ ++; //if (fabs(dualValue) > 1000.0 * dualTolerance) //setColumnStatus(iColumn,superBasic); Maybe on a switch } break; case ClpSimplex::isFixed: break; case atUpperBound: // dual should not be positive if (dualValue > dualTolerance) { sumDualInfeasibilities_ += dualValue - dualTolerance_; numberDualInfeasibilities_ ++; } break; case atLowerBound: // dual should not be negative if (dualValue < -dualTolerance) { sumDualInfeasibilities_ -= dualValue + dualTolerance_; numberDualInfeasibilities_ ++; } break; case superBasic: case isFree: if (primalValue < upper - primalTolerance) { // dual should not be negative if (dualValue < -dualTolerance) { sumDualInfeasibilities_ -= dualValue + dualTolerance_; numberDualInfeasibilities_ ++; } } if (primalValue > lower + primalTolerance) { // dual should not be positive if (dualValue > dualTolerance) { sumDualInfeasibilities_ += dualValue - dualTolerance_; numberDualInfeasibilities_ ++; } } break; } } } objectiveValue_ += objective_->nonlinearOffset(); // But do direction objectiveValue_ *= optimizationDirection_; if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = -1; } /* When scaling is on it is possible that the scaled problem is feasible but the unscaled is not. Clp returns a secondary status code to that effect. This option allows for a cleanup. If you use it I would suggest 1. This only affects actions when scaled optimal 0 - no action 1 - clean up using dual if primal infeasibility 2 - clean up using dual if dual infeasibility 3 - clean up using dual if primal or dual infeasibility 11,12,13 - as 1,2,3 but use primal */ #ifdef COUNT_CLEANUPS static int n1 = 0; static int n2 = 0; static int n3 = 0; #endif int ClpSimplex::cleanup(int cleanupScaling) { #ifdef COUNT_CLEANUPS n1++; #endif int returnCode = 0; if (!problemStatus_ && cleanupScaling) { int check = cleanupScaling % 10; bool primal = (secondaryStatus_ == 2 || secondaryStatus_ == 4); bool dual = (secondaryStatus_ == 3 || secondaryStatus_ == 4); if (((check & 1) != 0 && primal) || (((check & 2) != 0) && dual)) { // need cleanup int saveScalingFlag = scalingFlag_; // say matrix changed whatsChanged_ |= 1; scaling(0); if (cleanupScaling < 10) { // dual returnCode = this->dual(); } else { // primal returnCode = this->primal(); } #ifdef COUNT_CLEANUPS n2++; n3 += numberIterations_; //printf("**cleanup took %d iterations\n",numberIterations_); #endif scaling(saveScalingFlag); } } return returnCode; } #ifdef COUNT_CLEANUPS void printHowMany() { printf("There were %d cleanups out of %d solves and %d iterations\n", n2, n1, n3); } #endif #ifndef SLIM_CLP #include "CoinWarmStartBasis.hpp" // Returns a basis (to be deleted by user) CoinWarmStartBasis * ClpSimplex::getBasis() const { int iRow, iColumn; CoinWarmStartBasis * basis = new CoinWarmStartBasis(); basis->setSize(numberColumns_, numberRows_); if (statusExists()) { // Flip slacks int lookupA[] = {0, 1, 3, 2, 0, 2}; for (iRow = 0; iRow < numberRows_; iRow++) { int iStatus = getRowStatus(iRow); iStatus = lookupA[iStatus]; basis->setArtifStatus(iRow, static_cast (iStatus)); } int lookupS[] = {0, 1, 2, 3, 0, 3}; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { int iStatus = getColumnStatus(iColumn); iStatus = lookupS[iStatus]; basis->setStructStatus(iColumn, static_cast (iStatus)); } } return basis; } #endif // Compute objective value from solution void ClpSimplex::computeObjectiveValue(bool useInternalArrays) { int iSequence; objectiveValue_ = 0.0; const double * obj = objective(); if (!useInternalArrays) { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = columnActivity_[iSequence]; objectiveValue_ += value * obj[iSequence]; } // But remember direction as we are using external objective objectiveValue_ *= optimizationDirection_; } else if (!columnScale_) { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = columnActivityWork_[iSequence]; objectiveValue_ += value * obj[iSequence]; } // But remember direction as we are using external objective objectiveValue_ *= optimizationDirection_; objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); } else { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double scaleFactor = columnScale_[iSequence]; double valueScaled = columnActivityWork_[iSequence]; objectiveValue_ += valueScaled * scaleFactor * obj[iSequence]; } // But remember direction as we are using external objective objectiveValue_ *= optimizationDirection_; objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); } } // Compute minimization objective value from internal solution double ClpSimplex::computeInternalObjectiveValue() { int iSequence; //double oldObj = objectiveValue_; double objectiveValue = 0.0; const double * obj = objective(); if (!columnScale_) { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = solution_[iSequence]; objectiveValue += value * obj[iSequence]; } } else { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = solution_[iSequence] * columnScale_[iSequence]; objectiveValue += value * obj[iSequence]; } } objectiveValue *= optimizationDirection_ / rhsScale_; objectiveValue -= dblParam_[ClpObjOffset]; return objectiveValue; } // Infeasibility/unbounded ray (NULL returned if none/wrong) double * ClpSimplex::infeasibilityRay(bool fullRay) const { double * array = NULL; if (problemStatus_ == 1 && ray_) { if (!fullRay) { array = ClpCopyOfArray(ray_, numberRows_); } else { array = new double [numberRows_+numberColumns_]; memcpy(array,ray_,numberRows_*sizeof(double)); memset(array+numberRows_,0,numberColumns_*sizeof(double)); transposeTimes(-1.0,array,array+numberRows_); } #ifdef PRINT_RAY_METHOD printf("Infeasibility ray obtained by algorithm %s - direction out %d\n",algorithm_>0 ? "primal" : "dual",directionOut_); #endif } return array; } // If user left factorization frequency then compute void ClpSimplex::defaultFactorizationFrequency() { if (factorizationFrequency() == 200) { // User did not touch preset const int cutoff1 = 10000; const int base = 75; const int freq0 = 50; int frequency; #ifndef ABC_INHERIT const int cutoff2 = 100000; const int freq1 = 200; const int freq2 = 400; const int maximum = 1000; 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; #else const int freq1 = 150; const int maximum = 10000; if (numberRows_ < cutoff1) frequency = base + numberRows_ / freq0; else frequency = base + cutoff1 / freq0 + (numberRows_ - cutoff1) / freq1; #endif setFactorizationFrequency(CoinMin(maximum, frequency)); } } // Gets clean and emptyish factorization ClpFactorization * ClpSimplex::getEmptyFactorization() { if ((specialOptions_ & 65536) == 0) { assert (!factorization_); factorization_ = new ClpFactorization(); } else if (!factorization_) { factorization_ = new ClpFactorization(); factorization_->setPersistenceFlag(1); } return factorization_; } // May delete or may make clean and emptyish factorization void ClpSimplex::setEmptyFactorization() { if (factorization_) { factorization_->cleanUp(); if ((specialOptions_ & 65536) == 0) { delete factorization_; factorization_ = NULL; } else if (factorization_) { factorization_->almostDestructor(); } } } /* Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ void ClpSimplex::setPersistenceFlag(int value) { if (value) { //specialOptions_|=65536; startPermanentArrays(); } else { specialOptions_ &= ~65536; } if (factorization_) factorization_->setPersistenceFlag(value); } // Move status and solution across void ClpSimplex::moveInfo(const ClpSimplex & rhs, bool justStatus) { objectiveValue_ = rhs.objectiveValue_; numberIterations_ = rhs. numberIterations_; problemStatus_ = rhs. problemStatus_; secondaryStatus_ = rhs. secondaryStatus_; if (numberRows_ == rhs.numberRows_ && numberColumns_ == rhs.numberColumns_ && !justStatus) { if (rhs.status_) { if (status_) CoinMemcpyN(rhs.status_, numberRows_ + numberColumns_, status_); else status_ = CoinCopyOfArray(rhs.status_, numberRows_ + numberColumns_); } else { delete [] status_; status_ = NULL; } CoinMemcpyN(rhs.columnActivity_, numberColumns_, columnActivity_); CoinMemcpyN(rhs.reducedCost_, numberColumns_, reducedCost_); CoinMemcpyN(rhs.rowActivity_, numberRows_, rowActivity_); CoinMemcpyN(rhs.dual_, numberRows_, dual_); } } // Save a copy of model with certain state - normally without cuts void ClpSimplex::makeBaseModel() { delete baseModel_; baseModel_ = new ClpSimplex(*this); } // Switch off base model void ClpSimplex::deleteBaseModel() { delete baseModel_; baseModel_ = NULL; } // Reset to base model void ClpSimplex::setToBaseModel(ClpSimplex * model) { if (!model) model = baseModel_; assert (model); int multiplier = ((model->specialOptions_ & 65536) != 0) ? 2 : 1; assert (multiplier == 2); if (multiplier == 2) { assert (model->maximumRows_ >= 0); if (maximumRows_ < 0) { specialOptions_ |= 65536; maximumRows_ = model->maximumRows_; maximumColumns_ = model->maximumColumns_; } } COIN_DETAIL_PRINT(printf("resetbase a %d rows, %d maximum rows\n", numberRows_, maximumRows_)); // temporary - later use maximumRows_ for rowUpper_ etc assert (numberRows_ >= model->numberRows_); abort(); } // Start or reset using maximumRows_ and Columns_ bool ClpSimplex::startPermanentArrays() { int maximumRows = maximumRows_; int maximumColumns = maximumColumns_; ClpModel::startPermanentArrays(); if (maximumRows != maximumRows_ || maximumColumns != maximumColumns_) { #if 0 maximumInternalRows_ = maximumRows_; maximumInternalColumns_ = maximumColumns_; int numberTotal2 = (maximumRows_ + maximumColumns_) * 2; delete [] cost_; cost_ = new double[numberTotal2]; delete [] lower_; delete [] upper_; lower_ = new double[numberTotal2]; upper_ = new double[numberTotal2]; delete [] dj_; dj_ = new double[numberTotal2]; delete [] solution_; solution_ = new double[numberTotal2]; assert (scalingFlag_ > 0); if (rowScale_ && rowScale_ != savedRowScale_) delete [] rowScale_; rowScale_ = NULL; // Do initial scaling delete [] savedRowScale_; savedRowScale_ = new double [4*maximumRows_]; delete [] savedColumnScale_; savedColumnScale_ = new double [4*maximumColumns_]; if (scalingFlag_ > 0) { rowScale_ = savedRowScale_; columnScale_ = savedColumnScale_; if (matrix_->scale(this)) { scalingFlag_ = -scalingFlag_; // not scaled after all assert (!rowScale_); } int numberRows2 = numberRows_ + numberExtraRows_; if (rowScale_) { CoinMemcpyN(rowScale_, 2 * numberRows2, savedRowScale_ + 2 * maximumRows_); CoinMemcpyN(columnScale_, 2 * numberColumns_, savedColumnScale_ + 2 * maximumColumns_); } else { abort(); CoinFillN(savedRowScale_ + 2 * maximumRows_, 2 * numberRows2, 1.0); CoinFillN(savedColumnScale_ + 2 * maximumColumns_, 2 * numberColumns_, 1.0); } } #else createRim(63); #endif return true; } else { return false; } } #include "ClpNode.hpp" //#define COIN_DEVELOP // Fathom - 1 if solution int ClpSimplex::fathom(void * stuff) { assert (stuff); ClpNodeStuff * info = reinterpret_cast (stuff); info->nNodes_ = 0; // say can declare optimal moreSpecialOptions_ |= 8; int saveMaxIterations = maximumIterations(); setMaximumIterations((((moreSpecialOptions_&2048)==0) ? 100 : 2000) + 5 * (numberRows_ + numberColumns_)); double saveObjLimit; getDblParam(ClpDualObjectiveLimit, saveObjLimit); if (perturbation_<100) { double limit = saveObjLimit * optimizationDirection_; setDblParam(ClpDualObjectiveLimit, (limit+1.0e-2+1.0e-7*fabs(limit))*optimizationDirection_); } #if 0 bool onOptimal = (numberColumns_==100); double optVal[133]; { memset(optVal, 0, sizeof(optVal)); #if 0 int intIndicesV[] = {61, 62, 65, 66, 67, 68, 69, 70}; double intSolnV[] = {4., 21., 4., 4., 6., 1., 25., 8.}; int vecLen = sizeof(intIndicesV) / sizeof(int); for (int i = 0; i < vecLen; i++) { optVal[intIndicesV[i]] = intSolnV[i]; } #else int intIndicesAt1[] = { 0, 18, 25, 36, 44, 59, 61, 77, 82, 93 }; int vecLen = sizeof(intIndicesAt1) / sizeof(int); for (int i = 0; i < vecLen; i++) { optVal[intIndicesAt1[i]] = 1; } #endif } if (numberColumns_ == 100) { const char * integerType = integerInformation(); for (int i = 0; i < 100; i++) { if (integerType[i]) { if (columnLower_[i] > optVal[i] || columnUpper_[i] < optVal[i]) { onOptimal = false; break; } } } if (onOptimal) { printf("On optimal path fathom\n"); } } #endif if (info->presolveType_) { // crunch down bool feasible = true; // Use dual region double * rhs = dual_; int * whichRow = new int[3*numberRows_]; int * whichColumn = new int[2*numberColumns_]; int nBound; bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true; ClpSimplex * small = static_cast (this)->crunch(rhs, whichRow, whichColumn, nBound, false, tightenBounds); if (small) { //double limit = 0.0; //getDblParam(ClpDualObjectiveLimit, limit); //printf("objlimit a %g",limit); //small->getDblParam(ClpDualObjectiveLimit, limit); //printf(" %g\n",limit); // pack down pseudocosts small->moreSpecialOptions_ = moreSpecialOptions_; if (info->upPseudo_) { const char * integerType2 = small->integerInformation(); int n = small->numberColumns(); int k = 0; int jColumn = 0; int j = 0; for (int i = 0; i < n; i++) { if (integerType2[i]) { int iColumn = whichColumn[i]; // find while (jColumn != iColumn) { if (integerType_[jColumn]) j++; jColumn++; } info->priority_[k] = info->priority_[j]; info->upPseudo_[k] = info->upPseudo_[j]; info->numberUp_[k] = info->numberUp_[j]; info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j]; info->downPseudo_[k] = info->downPseudo_[j]; info->numberDown_[k] = info->numberDown_[j]; info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j]; assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40); assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40); k++; } } } #if 0 small->dual(); if (small->problemStatus() == 0) { //problemStatus_ = 0; } else if (small->problemStatus() != 3) { feasible = false; } else { if (small->problemStatus_ == 3) { // may be problems printf("need coding from OsiClp for crunch\n"); abort(); } } #endif } else { feasible = false; } int returnCode = 0; if (feasible) { info->presolveType_ = 0; // save and move pseudo costs returnCode = small->fathom(stuff); // restore pseudocosts if (info->upPseudo_) { int n = small->numberColumns(); int * back = new int [numberColumns_]; int numberIntegers = 0; for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { back[i] = -10 - numberIntegers; numberIntegers++; } else { back[i] = -1; } } const char * integerType2 = small->integerInformation(); int numberIntegers2 = 0; for (int i = 0; i < n; i++) { int iColumn = whichColumn[i]; if (integerType2[i]) { int iBack = -back[iColumn]; assert (iBack >= 10); iBack -= 10; back[iColumn] = iBack; numberIntegers2++; } } int k = numberIntegers2; for (int i = numberColumns_ - 1; i >= 0; i--) { int iBack = back[i]; if (iBack <= -10) { // fixed integer numberIntegers--; info->numberUp_[numberIntegers] = -1; // say not updated } else if (iBack >= 0) { // not fixed integer numberIntegers--; k--; assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40); assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40); info->upPseudo_[numberIntegers] = info->upPseudo_[k]; info->numberUp_[numberIntegers] = info->numberUp_[k]; info->numberUpInfeasible_[numberIntegers] = info->numberUpInfeasible_[k]; info->downPseudo_[numberIntegers] = info->downPseudo_[k]; info->numberDown_[numberIntegers] = info->numberDown_[k]; info->numberDownInfeasible_[numberIntegers] = info->numberDownInfeasible_[k]; } } delete [] back; } if (returnCode) { bool fixBounds = (info->nNodes_ >= 0) ? true : false; //check this does everything static_cast (this)->afterCrunch(*small, whichRow, whichColumn, nBound); bool badSolution = false; for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { double value = columnActivity_[i]; double value2 = floor(value + 0.5); if (fabs(value - value2) >= 1.0e-4) { // Very odd - can't use badSolution = true; } columnActivity_[i] = value2; if (fixBounds) { columnLower_[i] = value2; columnUpper_[i] = value2; } } } if (badSolution) { info->nNodes_ = -1; returnCode = 0; } //setLogLevel(63); //double objectiveValue=doubleCheck(); //printf("Solution of %g\n",objectiveValue); } delete small; } delete [] whichRow; delete [] whichColumn; setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); return returnCode; } int returnCode = startFastDual2(info); if (returnCode) { stopFastDual2(info); setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); return returnCode; } // Get fake bounds correctly //(static_cast(this))->resetFakeBounds(1); gutsOfSolution ( NULL, NULL); double dummyChange; (static_cast(this))->changeBounds(3, NULL, dummyChange); int saveNumberFake = numberFake_; int status = fastDual2(info); #if 0 { int iPivot; double * array = rowArray_[3]->denseVector(); int i; for (iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = pivotVariable_[iPivot]; unpack(rowArray_[3], iSequence); factorization_->updateColumn(rowArray_[2], rowArray_[3]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; for (i = 0; i < numberRows_; i++) assert (fabs(array[i]) < 1.0e-4); rowArray_[3]->clear(); } } #endif CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50); if (status && problemStatus_ != 3) { // not finished - might be optimal checkPrimalSolution(rowActivityWork_, columnActivityWork_); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); //printf("objlimit b %g\n",limit); if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) { problemStatus_ = 0; } status = problemStatus_; } if (problemStatus_ != 0 && problemStatus_ != 1) { #ifdef COIN_DEVELOP printf("bad status %d on initial fast dual %d its\n", problemStatus_, numberIterations_); #endif info->nNodes_ = -1; setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); return 0; } int numberNodes = 1; int numberIterations = numberIterations_; #if defined(COIN_DEVELOP) || !defined(NO_FATHOM_PRINT) int printFrequency = 2000; #endif if (problemStatus_ == 1) { //printf("fathom infeasible on initial\n"); stopFastDual2(info); info->numberNodesExplored_ = 1; info->numberIterations_ = numberIterations; setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); return 0; } else if (problemStatus_ != 0) { stopFastDual2(info); info->numberNodesExplored_ = 1; info->numberIterations_ = numberIterations; setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); // say bad info->nNodes_ = -1; return 0; } if (!columnScale_) { CoinMemcpyN(solution_, numberColumns_, columnActivity_); } else { assert(columnActivity_); assert(columnScale_); assert(solution_); int j; for (j = 0; j < numberColumns_; j++) columnActivity_[j] = solution_[j] * columnScale_[j]; } double increment = info->integerIncrement_; int maxDepthSize = 10; int maxDepth = 0; int depth = 0; // Get fake bounds correctly (static_cast(this))->changeBounds(3, NULL, dummyChange); saveNumberFake = numberFake_; ClpNode ** nodes = new ClpNode * [maxDepthSize]; int numberTotal = numberRows_ + numberColumns_; double * saveLower = CoinCopyOfArray(columnLower_, numberColumns_); double * saveUpper = CoinCopyOfArray(columnUpper_, numberColumns_); double * saveLowerInternal = CoinCopyOfArray(lower_, numberTotal); double * saveUpperInternal = CoinCopyOfArray(upper_, numberTotal); double * bestLower = NULL; double * bestUpper = NULL; int * back = new int [numberColumns_]; int numberIntegers = 0; double sumChanges = 1.0e-5; int numberChanges = 1; for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) back[i] = numberIntegers++; else back[i] = -1; } unsigned char * bestStatus = NULL; double bestObjective; getDblParam(ClpDualObjectiveLimit, bestObjective); double saveBestObjective = bestObjective; bool backtrack = false; bool printing = handler_->logLevel() > 0; while (depth >= 0) { // If backtrack get to correct depth if (backtrack) { depth--; while (depth >= 0) { if (!nodes[depth]->fathomed()) { nodes[depth]->changeState(); break; } //if (printing) //printf("deleting node at depth %d\n",depth); //delete nodes[depth]; //nodes[depth]=NULL; depth--; } if (depth < 0) break; // apply // First if backtracking we need to restore factorization, bounds and weights CoinMemcpyN(saveLowerInternal, numberTotal, lower_); CoinMemcpyN(saveUpperInternal, numberTotal, upper_); CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); for (int i = 0; i < depth; i++) { nodes[i]->applyNode(this, 0); } nodes[depth]->applyNode(this, 1); int iColumn = nodes[depth]->sequence(); if (printing) printf("after backtracking - applying node at depth %d - variable %d (%g,%g)\n", depth, iColumn, columnLower_[iColumn], columnUpper_[iColumn]); depth++; } else { // just bounds if (depth > 0) { nodes[depth-1]->applyNode(this, 0); int iColumn = nodes[depth-1]->sequence(); if (printing) printf("No backtracking - applying node at depth-m %d - variable %d (%g,%g)\n", depth - 1, iColumn, columnLower_[iColumn], columnUpper_[iColumn]); } } // solve #if 0 { int iPivot; double * array = rowArray_[3]->denseVector(); int i; for (iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = pivotVariable_[iPivot]; unpack(rowArray_[3], iSequence); factorization_->updateColumn(rowArray_[2], rowArray_[3]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; for (i = 0; i < numberRows_; i++) assert (fabs(array[i]) < 1.0e-4); rowArray_[3]->clear(); } } #endif #ifdef COIN_DEVELOP static int zzzzzz=0; zzzzzz++; if ((zzzzzz%100000)==0) printf("%d fathom solves\n",zzzzzz); if (zzzzzz==-1) { printf("TROUBLE\n"); } #endif // Get fake bounds correctly (static_cast(this))->changeBounds(3, NULL, dummyChange); fastDual2(info); #if 0 { int iPivot; double * array = rowArray_[3]->denseVector(); int i; for (iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = pivotVariable_[iPivot]; unpack(rowArray_[3], iSequence); factorization_->updateColumn(rowArray_[2], rowArray_[3]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; for (i = 0; i < numberRows_; i++) assert (fabs(array[i]) < 1.0e-4); rowArray_[3]->clear(); } } #endif // give up if odd if (problemStatus_ > 1) { info->nNodes_ = -1; #ifdef COIN_DEVELOP printf("OUCH giving up on loop! %d %d %d %d - zzzzzz %d - max %d\n", numberNodes, numberIterations, problemStatus_, numberIterations_,zzzzzz,intParam_[0]); printf("xx %d\n", numberIterations*(numberRows_ + numberColumns_)); //abort(); #endif break; } numberNodes++; numberIterations += numberIterations_; if ((numberNodes % 1000) == 0) { #ifdef COIN_DEVELOP if ((numberNodes % printFrequency) == 0) { printf("Fathoming from node %d - %d nodes (%d iterations) - current depth %d\n", info->nodeCalled_,numberNodes, numberIterations, depth+info->startingDepth_); printFrequency *= 2; } #elif !defined(NO_FATHOM_PRINT) if ((numberNodes % printFrequency) == 0) { if ((moreSpecialOptions_&2048)!=0) info->handler_->message(CLP_FATHOM_STATUS, messages_) << info->nodeCalled_ << numberNodes << numberIterations << depth+info->startingDepth_ << CoinMessageEol; printFrequency *= 2; } #endif if ((numberIterations*(numberRows_ + numberColumns_) > 5.0e10 || numberNodes > 2.0e4) && (moreSpecialOptions_&4096)==0) { // give up info->nNodes_ = -1; #ifdef COIN_DEVELOP printf("OUCH giving up on nodes %d %d\n", numberNodes, numberIterations); printf("xx %d\n", numberIterations*(numberRows_ + numberColumns_)); //abort(); #endif break; } } if (problemStatus_ == 1 || (problemStatus_ == 0 && objectiveValue()*optimizationDirection_ > bestObjective)) { backtrack = true; if (printing) printf("infeasible at depth %d\n", depth); if (depth > 0) { int way = nodes[depth-1]->way(); int sequence = nodes[depth-1]->sequence(); #ifndef NDEBUG double branchingValue = nodes[depth-1]->branchingValue(); if (way > 0) assert (columnLower_[sequence] == ceil(branchingValue)); else assert (columnUpper_[sequence] == floor(branchingValue)); #endif sequence = back[sequence]; double change = bestObjective - nodes[depth-1]->objectiveValue(); if (change > 1.0e10) change = 10.0 * sumChanges / (1.0 + numberChanges); info->update(way, sequence, change, false); } } else if (problemStatus_ != 0) { abort(); } else { // Create node ClpNode * node; computeDuals(NULL); if (depth > 0) { int way = nodes[depth-1]->way(); int sequence = nodes[depth-1]->sequence(); #ifndef NDEBUG double branchingValue = nodes[depth-1]->branchingValue(); if (way > 0) assert (columnLower_[sequence] == ceil(branchingValue)); else assert (columnUpper_[sequence] == floor(branchingValue)); #endif sequence = back[sequence]; info->update(way, sequence, objectiveValue() - nodes[depth-1]->objectiveValue(), true); numberChanges++; sumChanges += objectiveValue() - nodes[depth-1]->objectiveValue(); } if (depth < maxDepth) { node = nodes[depth]; node->gutsOfConstructor(this, info, 1, depth); } else { node = new ClpNode(this, info, depth); if (depth == maxDepthSize) { maxDepthSize = 2 * maxDepthSize + 10; ClpNode ** temp = new ClpNode * [maxDepthSize]; for (int i = 0; i < depth; i++) temp[i] = nodes[i]; delete [] nodes; nodes = temp; } nodes[maxDepth++] = node; } #if 0 if (numberColumns_ == 100 && onOptimal) { const char * integerType = integerInformation(); bool localOptimal=true; for (int i = 0; i < 100; i++) { if (integerType[i]) { if (columnLower_[i] > optVal[i] || columnUpper_[i] < optVal[i]) { localOptimal = false; printf("bad %d %g %g %g\n", i, columnLower_[i], optVal[i], columnUpper_[i]); break; } } } if (localOptimal) { printf("still on optimal\n"); } assert (onOptimal); } #endif double objectiveValue=0.0; if (node->sequence() < 0) { objectiveValue = doubleCheck(); node->gutsOfConstructor(this, info, 1, depth); } if (node->sequence() < 0) { // solution //double objectiveValue = doubleCheck(); if (objectiveValue < bestObjective) { #ifdef COIN_DEVELOP printf("Fathoming from node %d - solution of %g after %d nodes at depth %d\n", info->nodeCalled_,objectiveValue, numberNodes, depth+info->startingDepth_); #elif !defined(NO_FATHOM_PRINT) if ((moreSpecialOptions_&2048)!=0) info->handler_->message(CLP_FATHOM_SOLUTION, messages_) << info->nodeCalled_ << objectiveValue << numberNodes << depth+info->startingDepth_ << CoinMessageEol; #endif // later then lower_ not columnLower_ (and total?) delete [] bestLower; bestLower = CoinCopyOfArray(columnLower_, numberColumns_); delete [] bestUpper; bestUpper = CoinCopyOfArray(columnUpper_, numberColumns_); delete [] bestStatus; bestStatus = CoinCopyOfArray(status_, numberTotal); bestObjective = objectiveValue - increment; if (perturbation_<100) bestObjective += 1.0e-2+1.0e-7*fabs(bestObjective); setDblParam(ClpDualObjectiveLimit, bestObjective * optimizationDirection_); } else { //#define CLP_INVESTIGATE #ifdef COIN_DEVELOP printf("why bad solution feasible\n"); #endif } //delete node; backtrack = true; } else { if (printing) printf("depth %d variable %d\n", depth, node->sequence()); depth++; backtrack = false; //nodes[depth++] = new ClpNode (this,info); } } } if (!info->nNodes_) assert (depth == -1); for (int i = 0; i < maxDepth; i++) delete nodes[i]; delete [] nodes; delete [] back; stopFastDual2(info); #ifndef NO_FATHOM_PRINT if ((moreSpecialOptions_&2048)!=0 && numberNodes >= 10000) info->handler_->message(CLP_FATHOM_FINISH, messages_) << info->nodeCalled_ << info->startingDepth_ << numberNodes << numberIterations << maxDepth+info->startingDepth_ << CoinMessageEol; #endif //printf("fathom finished after %d nodes\n",numberNodes); if (bestStatus) { CoinMemcpyN(bestLower, numberColumns_, columnLower_); CoinMemcpyN(bestUpper, numberColumns_, columnUpper_); CoinMemcpyN(bestStatus, numberTotal, status_); delete [] bestLower; delete [] bestUpper; delete [] bestStatus; setDblParam(ClpDualObjectiveLimit, saveBestObjective); saveObjLimit = saveBestObjective; int saveOptions = specialOptions_; specialOptions_ &= ~65536; dual(); specialOptions_ = saveOptions; info->numberNodesExplored_ = numberNodes; info->numberIterations_ = numberIterations; returnCode = 1; } else { info->numberNodesExplored_ = numberNodes; info->numberIterations_ = numberIterations; returnCode = 0; } if (info->nNodes_ < 0) { if (lower_) { CoinMemcpyN(saveLowerInternal, numberTotal, lower_); CoinMemcpyN(saveUpperInternal, numberTotal, upper_); numberFake_ = saveNumberFake; } CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } delete [] saveLower; delete [] saveUpper; delete [] saveLowerInternal; delete [] saveUpperInternal; setMaximumIterations(saveMaxIterations); setDblParam(ClpDualObjectiveLimit, saveObjLimit); return returnCode; } //#define CHECK_PATH #ifdef CHECK_PATH const double * debuggerSolution_Z = NULL; int numberColumns_Z = -1; int gotGoodNode_Z = -1; #endif /* Do up to N deep - returns -1 - no solution nNodes_ valid nodes >= if solution and that node gives solution ClpNode array is 2**N long. Values for N and array are in stuff (nNodes_ also in stuff) */ int ClpSimplex::fathomMany(void * stuff) { assert (stuff); ClpNodeStuff * info = reinterpret_cast (stuff); int nNodes = info->maximumNodes(); int putNode = info->maximumSpace(); int goodNodes = 0; info->nNodes_ = 0; ClpNode ** nodeInfo = info->nodeInfo_; assert (nodeInfo); // say can declare optimal moreSpecialOptions_ |= 8; double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); for (int j = 0; j < putNode; j++) { if (nodeInfo[j]) { nodeInfo[j]->setObjectiveValue(limit); if (info->large_) nodeInfo[j]->cleanUpForCrunch(); } } #ifdef CHECK_PATH // Note - if code working can get assert on startOptimal==2 (if finds) int startOptimal = 0; if (numberColumns_ == numberColumns_Z) { assert (debuggerSolution_Z); startOptimal = 1; for (int i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) { startOptimal = 0; break; } } if (startOptimal) { printf("starting on optimal\n"); } } else if (info->large_ && info->large_->numberColumns_ == numberColumns_Z) { assert (debuggerSolution_Z); startOptimal = 1; for (int i = 0; i < info->large_->numberColumns_; i++) { if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) { startOptimal = 0; break; } } if (startOptimal) { printf("starting on optimal (presolved) %d\n", numberColumns_); } } #endif int whichSolution = -1; if (info->presolveType_) { // crunch down bool feasible = true; // Use dual region double * rhs = dual_; int * whichRow = new int[3*numberRows_]; int * whichColumn = new int[2*numberColumns_]; int nBound; bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true; ClpSimplex * small = static_cast (this)->crunch(rhs, whichRow, whichColumn, nBound, false, tightenBounds); if (small) { info->large_ = this; info->whichRow_ = whichRow; info->whichColumn_ = whichColumn; info->nBound_ = nBound; //double limit = 0.0; //getDblParam(ClpDualObjectiveLimit, limit); //printf("objlimit a %g",limit); //small->getDblParam(ClpDualObjectiveLimit, limit); //printf(" %g\n",limit); // pack down pseudocosts if (info->upPseudo_) { const char * integerType2 = small->integerInformation(); int n = small->numberColumns(); int k = 0; int jColumn = 0; int j = 0; for (int i = 0; i < n; i++) { if (integerType2[i]) { int iColumn = whichColumn[i]; // find while (jColumn != iColumn) { if (integerType_[jColumn]) j++; jColumn++; } info->upPseudo_[k] = info->upPseudo_[j]; info->numberUp_[k] = info->numberUp_[j]; info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j]; info->downPseudo_[k] = info->downPseudo_[j]; info->numberDown_[k] = info->numberDown_[j]; info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j]; assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40); assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40); k++; } } } } else { feasible = false; } if (feasible) { info->presolveType_ = 0; // save and move pseudo costs whichSolution = small->fathomMany(stuff); // restore pseudocosts if (info->upPseudo_) { int n = small->numberColumns(); int * back = new int [numberColumns_]; int numberIntegers = 0; for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { back[i] = -10 - numberIntegers; numberIntegers++; } else { back[i] = -1; } } const char * integerType2 = small->integerInformation(); int numberIntegers2 = 0; for (int i = 0; i < n; i++) { int iColumn = whichColumn[i]; if (integerType2[i]) { int iBack = -back[iColumn]; assert (iBack >= 10); iBack -= 10; back[iColumn] = iBack; numberIntegers2++; } } int k = numberIntegers2; for (int i = numberColumns_ - 1; i >= 0; i--) { int iBack = back[i]; if (iBack <= -10) { // fixed integer numberIntegers--; info->numberUp_[numberIntegers] = -1; // say not updated } else if (iBack >= 0) { // not fixed integer numberIntegers--; k--; assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40); assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40); info->upPseudo_[numberIntegers] = info->upPseudo_[k]; info->numberUp_[numberIntegers] = info->numberUp_[k]; info->numberUpInfeasible_[numberIntegers] = info->numberUpInfeasible_[k]; info->downPseudo_[numberIntegers] = info->downPseudo_[k]; info->numberDown_[numberIntegers] = info->numberDown_[k]; info->numberDownInfeasible_[numberIntegers] = info->numberDownInfeasible_[k]; } } delete [] back; } delete small; } info->large_ = NULL; info->whichRow_ = NULL; info->whichColumn_ = NULL; delete [] whichRow; delete [] whichColumn; return whichSolution; } #ifndef DEBUG { int nBasic = 0; int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (getColumnStatus(i) == basic) nBasic++; } assert (nBasic == numberRows_); } #endif int returnCode = startFastDual2(info); if (returnCode) { stopFastDual2(info); abort(); return -1; } gutsOfSolution ( NULL, NULL); int status = fastDual2(info); CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50); if (status && problemStatus_ != 3) { // not finished - might be optimal checkPrimalSolution(rowActivityWork_, columnActivityWork_); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); //printf("objlimit b %g\n",limit); if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) { problemStatus_ = 0; } status = problemStatus_; } assert (problemStatus_ == 0 || problemStatus_ == 1); //(static_cast this)->dual(0,0); if (problemStatus_ == 10) { printf("Cleaning up with primal - need coding without createRim!\n"); abort(); } int numberNodes = 0; int numberIterations = numberIterations_; if (problemStatus_ == 1) { //printf("fathom infeasible on initial\n"); stopFastDual2(info); info->nNodes_ = 0; info->numberNodesExplored_ = 0; info->numberIterations_ = numberIterations; return -1; } else if (problemStatus_ != 0) { abort(); } if (!columnScale_) { CoinMemcpyN(solution_, numberColumns_, columnActivity_); } else { assert(columnActivity_); assert(columnScale_); assert(solution_); int j; for (j = 0; j < numberColumns_; j++) columnActivity_[j] = solution_[j] * columnScale_[j]; } double increment = info->integerIncrement_; int depth = 0; int numberTotal = numberRows_ + numberColumns_; double * saveLower = CoinCopyOfArray(columnLower_, numberColumns_); double * saveUpper = CoinCopyOfArray(columnUpper_, numberColumns_); double * saveLowerInternal = CoinCopyOfArray(lower_, numberTotal); double * saveUpperInternal = CoinCopyOfArray(upper_, numberTotal); //double * bestLower = NULL; //double * bestUpper = NULL; int * back = new int [numberColumns_]; int numberIntegers = 0; double sumChanges = 1.0e-5; int numberChanges = 1; for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) back[i] = numberIntegers++; else back[i] = -1; } //unsigned char * bestStatus = NULL; double bestObjective; getDblParam(ClpDualObjectiveLimit, bestObjective); double saveBestObjective = bestObjective; bool backtrack = false; bool printing = handler_->logLevel() > 0; #ifdef CHECK_PATH if (startOptimal) printing = true; #endif /* Use nodeInfo for storage depth 0 will be putNode-1, 1 putNode-2 etc */ int useDepth = putNode - 1; bool justDive = (info->solverOptions_ & 32) != 0; //printf("putNode %d nDepth %d\n"); while (depth >= 0) { bool stopAtOnce = false; // If backtrack get to correct depth if (backtrack) { depth--; useDepth++; while (depth >= 0) { if (!nodeInfo[useDepth]->fathomed()) { nodeInfo[useDepth]->changeState(); break; } //if (printing) //printf("deleting node at depth %d\n",depth); //delete nodes[useDepth]; //nodes[useDepth]=NULL; depth--; useDepth++; } if (depth < 0) break; // apply // First if backtracking we need to restore factorization, bounds and weights CoinMemcpyN(saveLowerInternal, numberTotal, lower_); CoinMemcpyN(saveUpperInternal, numberTotal, upper_); CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); for (int i = 0; i < depth; i++) { nodeInfo[putNode-1-i]->applyNode(this, 0); } nodeInfo[useDepth]->applyNode(this, 1); if (justDive) stopAtOnce = true; int iColumn = nodeInfo[useDepth]->sequence(); if (printing) printf("after backtracking - applying node at depth %d - variable %d (%g,%g)\n", depth, iColumn, columnLower_[iColumn], columnUpper_[iColumn]); depth++; useDepth--; } else { // just bounds if (depth > 0) { // Choose variable here!! nodeInfo[useDepth+1]->chooseVariable(this, info); nodeInfo[useDepth+1]->applyNode(this, 0); int iColumn = nodeInfo[useDepth+1]->sequence(); if (printing) printf("No backtracking - applying node at depth-m %d - variable %d (%g,%g)\n", depth - 1, iColumn, columnLower_[iColumn], columnUpper_[iColumn]); } } // solve double dummyChange; (static_cast(this))->changeBounds(3, NULL, dummyChange); //int saveNumberFake = numberFake_; fastDual2(info); numberNodes++; numberIterations += numberIterations_; if ((numberNodes % 1000) == 0 && printing) printf("After %d nodes (%d iterations) - best solution %g - current depth %d\n", numberNodes, numberIterations, bestObjective, depth); if (problemStatus_ == 1 || (problemStatus_ == 0 && objectiveValue()*optimizationDirection_ > bestObjective)) { backtrack = true; if (printing) printf("infeasible at depth %d\n", depth); #ifdef CHECK_PATH if (startOptimal && numberColumns_ == numberColumns_Z) { bool onOptimal = true; for (int i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) { onOptimal = false; break; } } if (onOptimal) { printf("INF on optimal fathom at depth %d\n", depth); abort(); } } else if (info->large_ && startOptimal && info->large_->numberColumns_ == numberColumns_Z) { bool onOptimal = true; for (int i = 0; i < info->large_->numberColumns_; i++) { if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) { onOptimal = false; break; } } if (onOptimal) { printf("INF on optimal (pre) fathom at depth %d\n", depth); writeMps("fathom_pre.mps"); abort(); } } #endif if (depth > 0) { int way = nodeInfo[useDepth+1]->way(); int sequence = nodeInfo[useDepth+1]->sequence(); #ifndef NDEBUG double branchingValue = nodeInfo[useDepth+1]->branchingValue(); if (way > 0) assert (columnLower_[sequence] == ceil(branchingValue)); else assert (columnUpper_[sequence] == floor(branchingValue)); #endif sequence = back[sequence]; double change = bestObjective - nodeInfo[useDepth+1]->objectiveValue(); if (change > 1.0e10) change = 10.0 * sumChanges / (1.0 + numberChanges); info->update(way, sequence, change, false); } } else if (problemStatus_ != 0) { abort(); } else { // Create node ClpNode * node; computeDuals(NULL); if (depth > 0) { int way = nodeInfo[useDepth+1]->way(); int sequence = nodeInfo[useDepth+1]->sequence(); #ifndef NDEBUG double branchingValue = nodeInfo[useDepth+1]->branchingValue(); if (way > 0) assert (columnLower_[sequence] == ceil(branchingValue)); else assert (columnUpper_[sequence] == floor(branchingValue)); #endif sequence = back[sequence]; info->update(way, sequence, objectiveValue() - nodeInfo[useDepth+1]->objectiveValue(), true); numberChanges++; sumChanges += objectiveValue() - nodeInfo[useDepth+1]->objectiveValue(); } #ifdef CHECK_PATH if (startOptimal && numberColumns_ == numberColumns_Z) { bool onOptimal = true; for (int i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) { onOptimal = false; break; } } if (onOptimal) { if (depth >= info->nDepth_) { printf("on optimal fathom at full depth %d %d %g\n", depth, goodNodes, objectiveValue()); gotGoodNode_Z = goodNodes; startOptimal = 2; } else { printf("on optimal fathom at depth %d\n", depth); } } } else if (info->large_ && startOptimal && info->large_->numberColumns_ == numberColumns_Z) { bool onOptimal = true; // Fix bounds in large for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { int iColumn = info->whichColumn_[i]; info->large_->columnUpper_[iColumn] = columnUpper_[i]; info->large_->columnLower_[iColumn] = columnLower_[i]; COIN_DETAIL_PRINT(printf("%d dj %g dual %g scale %g\n", iColumn, dj_[i], reducedCost_[i], columnScale_[i])); } } for (int i = 0; i < info->large_->numberColumns_; i++) { if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) { onOptimal = false; break; } } if (onOptimal) { if (depth >= info->nDepth_) { printf("on (pre) tentative optimal fathom at full depth %d %d %g\n", depth, goodNodes, objectiveValue()); for (int i = 0; i < info->large_->numberColumns_; i++) printf("fathomA %d %g %g\n", i, info->large_->columnLower_[i], info->large_->columnUpper_[i]); } else { printf("on (pre) optimal fathom at depth %d\n", depth); } } } #endif if (depth < info->nDepth_ && !stopAtOnce) { node = nodeInfo[useDepth]; if (node) { node->gutsOfConstructor(this, info, 1, depth); } else { node = new ClpNode(this, info, depth); nodeInfo[useDepth] = node; } } else { // save node = nodeInfo[goodNodes]; if (!node) { node = new ClpNode(this, info, depth); nodeInfo[goodNodes] = node; } if (!node->oddArraysExist()) node->createArrays(this); node->gutsOfConstructor(this, info, 2, depth); } if (node->sequence() < 0) { // solution double objectiveValue = doubleCheck(); if (printing) printf("Solution of %g after %d nodes at depth %d\n", objectiveValue, numberNodes, depth); if (objectiveValue < bestObjective && !problemStatus_) { // make sure node exists node = nodeInfo[goodNodes]; if (!node) { node = new ClpNode(this, info, depth); nodeInfo[goodNodes] = node; } if (info->large_) { //check this does everything // Fix bounds in large for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { int iColumn = info->whichColumn_[i]; info->large_->columnUpper_[iColumn] = columnUpper_[i]; info->large_->columnLower_[iColumn] = columnLower_[i]; } } static_cast (info->large_)->afterCrunch(*this, info->whichRow_, info->whichColumn_, info->nBound_); // do as for large if (!node->oddArraysExist()) node->createArrays(info->large_); node->gutsOfConstructor(info->large_, info, 2, depth); } else { if (!node->oddArraysExist()) node->createArrays(this); node->gutsOfConstructor(this, info, 2, depth); } whichSolution = goodNodes; goodNodes++; if (goodNodes >= nNodes) justDive = true; // clean up phase assert (node->sequence() < 0); bestObjective = objectiveValue - increment; setDblParam(ClpDualObjectiveLimit, bestObjective * optimizationDirection_); } else { #ifdef CLP_INVESTIGATE printf("why bad solution feasible\n"); abort(); #endif } backtrack = true; } else { //if (printing) //printf("depth %d variable %d\n",depth,node->sequence()); if (depth == info->nDepth_ || stopAtOnce) { if (info->large_) { //check this does everything // Fix bounds in large for (int i = 0; i < numberColumns_; i++) { if (integerType_[i]) { int iColumn = info->whichColumn_[i]; info->large_->columnUpper_[iColumn] = columnUpper_[i]; info->large_->columnLower_[iColumn] = columnLower_[i]; } } #ifdef CHECK_PATH if (startOptimal) for (int i = 0; i < info->large_->numberColumns_; i++) printf("fathomB %d %g %g %g\n", i, info->large_->columnLower_[i], info->large_->columnUpper_[i], node->dualSolution()[i]); #endif static_cast (info->large_)->afterCrunch(*this, info->whichRow_, info->whichColumn_, info->nBound_); #ifdef CHECK_PATH if (startOptimal) { bool onOptimal = true; for (int i = 0; i < info->large_->numberColumns_; i++) printf("fathomC %d %g %g\n", i, info->large_->columnLower_[i], info->large_->columnUpper_[i]); for (int i = 0; i < info->large_->numberColumns_; i++) { if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) { onOptimal = false; break; } } if (onOptimal) { printf("on (pre) optimal fathom at full depth %d %d %g\n", depth, goodNodes, info->large_->objectiveValue()); startOptimal = 2; gotGoodNode_Z = goodNodes; for (int i = 0; i < info->large_->numberColumns_; i++) printf("fathom %d %g %g\n", i, info->large_->columnLower_[i], info->large_->columnUpper_[i]); } } #endif // do as for large node->gutsOfConstructor(info->large_, info, 2, depth); } goodNodes++; if (goodNodes >= nNodes) justDive = true; // clean up phase backtrack = true; } else { depth++; useDepth--; backtrack = false; } } } } //printf("nNodes %d nDepth %d, useDepth %d goodNodes %d\n", // nNodes,info->nDepth_,useDepth,goodNodes); #ifdef CHECK_PATH if (startOptimal) { assert(startOptimal == 2); printf("got fathomed optimal at end %d\n", startOptimal); if (startOptimal != 2) abort(); } #endif assert (depth == -1); delete [] saveLower; delete [] saveUpper; delete [] saveLowerInternal; delete [] saveUpperInternal; delete [] back; //printf("fathom finished after %d nodes\n",numberNodes); if (whichSolution >= 0) { setDblParam(ClpDualObjectiveLimit, saveBestObjective); } stopFastDual2(info); info->nNodes_ = goodNodes; info->numberNodesExplored_ = numberNodes; info->numberIterations_ = numberIterations; return whichSolution; } // Double checks OK double ClpSimplex::doubleCheck() { #if 0 double * solution = CoinCopyOfArray(solution_, numberColumns_ + numberRows_); gutsOfSolution ( NULL, NULL); for (int i = 0; i < numberColumns_; i++) { if (fabs(solution[i] - solution_[i]) > 1.0e-7) printf("bada %d bad %g good %g\n", i, solution[i], solution_[i]); } //abort(); #endif // make sure clean whatsChanged_=0; dual(0, 7); #if 0 for (int i = 0; i < numberColumns_; i++) { if (fabs(solution[i] - solution_[i]) > 1.0e-7) printf("badb %d bad %g good %g\n", i, solution[i], solution_[i]); } dual(0, 1); for (int i = 0; i < numberColumns_; i++) { if (fabs(solution[i] - solution_[i]) > 1.0e-7) printf("badc %d bad %g good %g\n", i, solution[i], solution_[i]); } delete [] solution; #endif return objectiveValue() * optimizationDirection_; } // Start Fast dual int ClpSimplex::startFastDual2(ClpNodeStuff * info) { info->saveOptions_ = specialOptions_; assert ((info->solverOptions_ & 65536) == 0); info->solverOptions_ |= 65536; if ((specialOptions_ & 65536) == 0) { factorization_->setPersistenceFlag(2); } else { factorization_->setPersistenceFlag(2); startPermanentArrays(); } //assert (!lower_); // create modifiable copies of model rim and do optional scaling createRim(7 + 8 + 16 + 32, true, 0); #ifndef NDEBUG ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); assert (clpMatrix && (clpMatrix->flags() & 1) == 0); #endif // mark all as current whatsChanged_ = 0x3ffffff; // change newLower and newUpper if scaled // Do initial factorization // and set certain stuff // We can either set increasing rows so ...IsBasic gives pivot row // or we can just increment iBasic one by one // for now let ...iBasic give pivot row int factorizationStatus = internalFactorize(0); if (factorizationStatus < 0 || (factorizationStatus && factorizationStatus <= numberRows_)) { // some error #if 0 // we should either debug or ignore #ifdef CLP_INVESTIGATE //#ifndef NDEBUG printf("***** ClpDual strong branching factorization error - debug\n"); abort(); //#endif #endif return -2; #else dual(0, 7); createRim(7 + 8 + 16 + 32, true, 0); int factorizationStatus = internalFactorize(0); assert (factorizationStatus == 0); if (factorizationStatus) abort(); #endif } // Start of fast iterations factorization_->sparseThreshold(0); factorization_->goSparse(); assert (!info->saveCosts_); int numberTotal = numberRows_ + numberColumns_; double * save = new double [4*numberTotal]; CoinMemcpyN(cost_, numberTotal, save+3*numberTotal); if (perturbation_<100) { int saveIterations = numberIterations_; //int saveOptions = moreSpecialOptions_; int savePerturbation = perturbation_; numberIterations_ = 0; //moreSpecialOptions_ |= 128; bool allZero = true; for (int i=0;ilower_[i]) { allZero=false; break; } } } if (allZero) perturbation_ = 58; static_cast< ClpSimplexDual *>(this)->perturb(); numberIterations_ = saveIterations; //moreSpecialOptions_ = saveOptions; perturbation_ = savePerturbation; } info->saveCosts_ = save; CoinMemcpyN(cost_, numberTotal, save); return 0; } // Like Fast dual int ClpSimplex::fastDual2(ClpNodeStuff * info) { assert ((info->solverOptions_ & 65536) != 0); int numberTotal = numberRows_ + numberColumns_; assert (info->saveCosts_); double * save = info->saveCosts_; CoinMemcpyN(save, numberTotal, cost_); save += numberTotal; CoinMemcpyN(lower_, numberTotal, save); save += numberTotal; CoinMemcpyN(upper_, numberTotal, save); double dummyChange; (static_cast(this))->changeBounds(3, NULL, dummyChange); numberPrimalInfeasibilities_ = 1; sumPrimalInfeasibilities_ = 0.5; sumOfRelaxedDualInfeasibilities_ = 0.0; sumOfRelaxedPrimalInfeasibilities_ = 0.5; checkDualSolution(); //if (xxxxxx) //checkPrimalSolution(rowActivityWork_,columnActivityWork_); assert((specialOptions_ & 16384) == 0); specialOptions_ |= 524288; // say use solution ClpObjective * saveObjective = objective_; #ifndef NDEBUG //(static_cast(this))->resetFakeBounds(-1); #endif //int saveNumberFake = numberFake_; int status = static_cast (this)->fastDual(true); //numberFake_ = saveNumberFake; specialOptions_ &= ~524288; // say dont use solution CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50); if (status && problemStatus_ != 3) { // not finished - might be optimal checkPrimalSolution(rowActivityWork_, columnActivityWork_); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) { problemStatus_ = 0; } } if (problemStatus_ == 10) { // Say second call moreSpecialOptions_ |= 256; //printf("Cleaning up with primal\n"); //lastAlgorithm=1; int savePerturbation = perturbation_; int saveLog = handler_->logLevel(); //handler_->setLogLevel(63); perturbation_ = 100; bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // Allow for catastrophe int saveMax = intParam_[ClpMaxNumIteration]; if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_) intParam_[ClpMaxNumIteration] = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_; // check which algorithms allowed baseIteration_ = numberIterations_; status = static_cast (this)->primal(1, 7); baseIteration_ = 0; if (saveObjective != objective_) { // We changed objective to see if infeasible delete objective_; objective_ = saveObjective; if (!problemStatus_) { // carry on status = static_cast (this)->primal(1, 7); } } if (problemStatus_ == 3 && numberIterations_ < saveMax) { #ifdef COIN_DEVELOP if (handler_->logLevel() > 0) printf("looks like trouble - too many iterations in clean up - trying again\n"); #endif // flatten solution and try again int iColumn; for (iColumn = 0; iColumn < numberTotal; iColumn++) { if (getStatus(iColumn) != basic) { setStatus(iColumn, superBasic); // but put to bound if close if (fabs(solution_[iColumn] - lower_[iColumn]) <= primalTolerance_) { solution_[iColumn] = lower_[iColumn]; setStatus(iColumn, atLowerBound); } else if (fabs(solution_[iColumn] - upper_[iColumn]) <= primalTolerance_) { solution_[iColumn] = upper_[iColumn]; setStatus(iColumn, atUpperBound); } } } problemStatus_ = -1; intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_, saveMax); perturbation_ = savePerturbation; baseIteration_ = numberIterations_; status = static_cast (this)->primal(0); baseIteration_ = 0; computeObjectiveValue(); // can't rely on djs either memset(reducedCost_, 0, numberColumns_ * sizeof(double)); #ifdef COIN_DEVELOP if (problemStatus_ == 3 && numberIterations_ < saveMax && handler_->logLevel() > 0) printf("looks like real trouble - too many iterations in second clean up - giving up\n"); #endif } // Say not second call moreSpecialOptions_ &= ~256; intParam_[ClpMaxNumIteration] = saveMax; setInitialDenseFactorization(denseFactorization); perturbation_ = savePerturbation; if (problemStatus_ == 10) { if (!numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = 4; } handler_->setLogLevel(saveLog); // if done primal arrays may be rubbish save = info->saveCosts_ + numberTotal; CoinMemcpyN(save, numberTotal, lower_); save += numberTotal; CoinMemcpyN(save, numberTotal, upper_); } status = problemStatus_; if (!problemStatus_) { int j; // Move solution to external array if (!columnScale_) { CoinMemcpyN(solution_, numberColumns_, columnActivity_); } else { for (j = 0; j < numberColumns_; j++) columnActivity_[j] = solution_[j] * columnScale_[j]; } if ((info->solverOptions_ & 1) != 0) { // reduced costs if (!columnScale_) { CoinMemcpyN(dj_, numberColumns_, reducedCost_); } else { for (j = 0; j < numberColumns_; j++) reducedCost_[j] = dj_[j] * columnScale_[j+numberColumns_]; } } if ((info->solverOptions_ & 2) != 0) { // dual if (!rowScale_) { //CoinMemcpyN(dual_,numberRows_,dj_+numberColumns_); } else { for (j = 0; j < numberRows_; j++) dual_[j] = dj_[j+numberColumns_] * rowScale_[j]; } } if ((info->solverOptions_ & 4) != 0) { // row activity if (!rowScale_) { CoinMemcpyN(solution_ + numberColumns_, numberRows_, rowActivity_); } else { for (j = 0; j < numberRows_; j++) rowActivity_[j] = solution_[j+numberColumns_] * rowScale_[j+numberRows_]; } } } save = info->saveCosts_; CoinMemcpyN(save, numberTotal, cost_); #if 0 save += numberTotal; CoinMemcpyN(save, numberTotal, lower_); save += numberTotal; CoinMemcpyN(save, numberTotal, upper_); #endif return status; } // Stop Fast dual void ClpSimplex::stopFastDual2(ClpNodeStuff * info) { delete [] info->saveCosts_; info->saveCosts_ = NULL; specialOptions_ = info->saveOptions_; // try just factorization if ((specialOptions_ & 65536) == 0) factorization_->setPersistenceFlag(0); deleteRim(1); whatsChanged_ &= ~0xffff; assert ((info->solverOptions_ & 65536) != 0); info->solverOptions_ &= ~65536; } // Deals with crunch aspects ClpSimplex * ClpSimplex::fastCrunch(ClpNodeStuff * info, int mode) { ClpSimplex * small = NULL; if (mode == 0) { // before crunch // crunch down // Use dual region double * rhs = dual_; int * whichRow = new int[3*numberRows_]; int * whichColumn = new int[2*numberColumns_]; int nBound; bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true; small = static_cast (this)->crunch(rhs, whichRow, whichColumn, nBound, false, tightenBounds); if (small) { info->large_ = this; info->whichRow_ = whichRow; info->whichColumn_ = whichColumn; info->nBound_ = nBound; if (info->upPseudo_) { const char * integerType2 = small->integerInformation(); int n = small->numberColumns(); int k = 0; int jColumn = 0; int j = 0; for (int i = 0; i < n; i++) { if (integerType2[i]) { int iColumn = whichColumn[i]; // find while (jColumn != iColumn) { if (integerType_[jColumn]) j++; jColumn++; } info->upPseudo_[k] = info->upPseudo_[j]; info->numberUp_[k] = info->numberUp_[j]; info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j]; info->downPseudo_[k] = info->downPseudo_[j]; info->numberDown_[k] = info->numberDown_[j]; info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j]; assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40); assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40); k++; } } } } else { delete [] whichRow; delete [] whichColumn; } } else { // after crunch if (mode == 1) { // has solution ClpSimplex * other = info->large_; assert (other != this); static_cast (other)->afterCrunch(*this, info->whichRow_, info->whichColumn_, info->nBound_); for (int i = 0; i < other->numberColumns_; i++) { if (other->integerType_[i]) { double value = other->columnActivity_[i]; double value2 = floor(value + 0.5); assert (fabs(value - value2) < 1.0e-4); other->columnActivity_[i] = value2; other->columnLower_[i] = value2; other->columnUpper_[i] = value2; } } } delete [] info->whichRow_; delete [] info->whichColumn_; } return small; } // Resizes rim part of model void ClpSimplex::resize (int newNumberRows, int newNumberColumns) { ClpModel::resize(newNumberRows, newNumberColumns); delete [] perturbationArray_; perturbationArray_ = NULL; maximumPerturbationSize_=0; if (saveStatus_) { // delete arrays int saveOptions = specialOptions_; specialOptions_ = 0; gutsOfDelete(2); specialOptions_ = saveOptions; } } // Return true if the objective limit test can be relied upon bool ClpSimplex::isObjectiveLimitTestValid() const { if (problemStatus_ == 0) { return true; } else if (problemStatus_ == 1) { // ok if dual return (algorithm_ < 0); } else if (problemStatus_ == 2) { // ok if primal return (algorithm_ > 0); } else { return false; } } // Create C++ lines to get to current state void ClpSimplex::generateCpp( FILE * fp, bool defaultFactor) { ClpModel::generateCpp(fp); ClpSimplex defaultModel; ClpSimplex * other = &defaultModel; int iValue1, iValue2; double dValue1, dValue2; // Stuff that can't be done easily if (factorizationFrequency() == other->factorizationFrequency()) { if (defaultFactor) { fprintf(fp, "3 // For branchAndBound this may help\n"); fprintf(fp, "3 clpModel->defaultFactorizationFrequency();\n"); } else { // tell user about default fprintf(fp, "3 // For initialSolve you don't need below but ...\n"); fprintf(fp, "3 // clpModel->defaultFactorizationFrequency();\n"); } } iValue1 = this->factorizationFrequency(); iValue2 = other->factorizationFrequency(); fprintf(fp, "%d int save_factorizationFrequency = clpModel->factorizationFrequency();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setFactorizationFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->setFactorizationFrequency(save_factorizationFrequency);\n", iValue1 == iValue2 ? 7 : 6); dValue1 = this->dualBound(); dValue2 = other->dualBound(); fprintf(fp, "%d double save_dualBound = clpModel->dualBound();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setDualBound(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setDualBound(save_dualBound);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->infeasibilityCost(); dValue2 = other->infeasibilityCost(); fprintf(fp, "%d double save_infeasibilityCost = clpModel->infeasibilityCost();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setInfeasibilityCost(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setInfeasibilityCost(save_infeasibilityCost);\n", dValue1 == dValue2 ? 7 : 6); iValue1 = this->perturbation(); iValue2 = other->perturbation(); fprintf(fp, "%d int save_perturbation = clpModel->perturbation();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setPerturbation(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->setPerturbation(save_perturbation);\n", iValue1 == iValue2 ? 7 : 6); } // Copy across enabled stuff from one solver to another void ClpSimplex::copyEnabledStuff(const ClpSimplex * rhs) { solveType_=rhs->solveType_; if (rhs->solution_) { int numberTotal = numberRows_+numberColumns_; assert (!solution_); solution_ = CoinCopyOfArray(rhs->solution_,numberTotal); lower_ = CoinCopyOfArray(rhs->lower_,numberTotal); upper_ = CoinCopyOfArray(rhs->upper_,numberTotal); dj_ = CoinCopyOfArray(rhs->dj_,numberTotal); cost_ = CoinCopyOfArray(rhs->cost_,2*numberTotal); reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; columnActivityWork_ = solution_; rowActivityWork_ = solution_ + numberColumns_; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; } if (rhs->factorization_) { delete factorization_; factorization_ = new ClpFactorization(*rhs->factorization_); delete [] pivotVariable_; pivotVariable_ = CoinCopyOfArray(rhs->pivotVariable_,numberRows_); } for (int i = 0; i < 6; i++) { if (rhs->rowArray_[i]) rowArray_[i] = new CoinIndexedVector(*rhs->rowArray_[i]); if (rhs->columnArray_[i]) columnArray_[i] = new CoinIndexedVector(*rhs->columnArray_[i]); } if (rhs->nonLinearCost_) nonLinearCost_=new ClpNonLinearCost(*rhs->nonLinearCost_); if (rhs->dualRowPivot_) dualRowPivot_ = rhs->dualRowPivot_->clone(); if (rhs->primalColumnPivot_) primalColumnPivot_ = rhs->primalColumnPivot_->clone(); } Clp-1.15.10/src/ClpSimplexNonlinear.hpp0000644000076600007660000000762611510657452016322 0ustar coincoin/* $Id: ClpSimplexNonlinear.hpp 1665 2011-01-04 17:55:54Z 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). /* Authors John Forrest */ #ifndef ClpSimplexNonlinear_H #define ClpSimplexNonlinear_H class ClpNonlinearInfo; class ClpQuadraticObjective; class ClpConstraint; #include "ClpSimplexPrimal.hpp" /** This solves non-linear LPs using the primal simplex method It inherits from ClpSimplexPrimal. It has no data of its own and is never created - only cast from a ClpSimplexPrimal object at algorithm time. If needed create new class and pass around */ class ClpSimplexNonlinear : public ClpSimplexPrimal { public: /**@name Description of algorithm */ //@{ /** Primal algorithms for reduced gradient At present we have two algorithms: */ /// A reduced gradient method. int primal(); /** Primal algorithm for quadratic Using a semi-trust region approach as for pooling problem This is in because I have it lying around */ int primalSLP(int numberPasses, double deltaTolerance); /** Primal algorithm for nonlinear constraints Using a semi-trust region approach as for pooling problem This is in because I have it lying around */ int primalSLP(int numberConstraints, ClpConstraint ** constraints, int numberPasses, double deltaTolerance); /** Creates direction vector. note longArray is long enough for rows and columns. If numberNonBasic 0 then is updated otherwise mode is ignored and those are used. Norms are only for those > 1.0e3*dualTolerance If mode is nonzero then just largest dj */ void directionVector (CoinIndexedVector * longArray, CoinIndexedVector * spare1, CoinIndexedVector * spare2, int mode, double & normFlagged, double & normUnflagged, int & numberNonBasic); /// Main part. int whileIterating (int & pivotMode); /** longArray has direction pivotMode - 0 - use all dual infeasible variables 1 - largest dj while >= 10 trying startup phase Returns 0 - can do normal iteration (basis change) 1 - no basis change 2 - if wants singleton 3 - if time to re-factorize If sequenceIn_ >=0 then that will be incoming variable */ int pivotColumn(CoinIndexedVector * longArray, CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * spare, int & pivotMode, double & solutionError, double * array1); /** Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void statusOfProblemInPrimal(int & lastCleaned, int type, ClpSimplexProgress * progress, bool doFactorization, double & bestObjectiveWhenFlagged); /** Do last half of an iteration. Return codes Reasons to come out normal mode -1 normal -2 factorize now - good iteration -3 slight inaccuracy - refactorize - iteration done -4 inaccuracy - refactorize - no iteration -5 something flagged - go round again +2 looks unbounded +3 max iterations (iteration done) */ int pivotNonlinearResult(); //@} }; #endif Clp-1.15.10/src/ClpMatrixBase.hpp0000644000076600007660000005540711552534715015074 0ustar coincoin/* $Id: ClpMatrixBase.hpp 1722 2011-04-17 09:58:37Z 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 ClpMatrixBase_H #define ClpMatrixBase_H #include "CoinPragma.hpp" #include "CoinTypes.hpp" #include "CoinPackedMatrix.hpp" class CoinIndexedVector; class ClpSimplex; class ClpModel; /** Abstract base class for Clp Matrices Since this class is abstract, no object of this type can be created. If a derived class provides all methods then all Clp algorithms should work. Some can be very inefficient e.g. getElements etc is only used for tightening bounds for dual and the copies are deleted. Many methods can just be dummy i.e. abort(); if not all features are being used. So if column generation was being done then it makes no sense to do steepest edge so there would be no point providing subsetTransposeTimes. */ class ClpMatrixBase { public: /**@name Virtual methods that the derived classes must provide */ //@{ /// Return a complete CoinPackedMatrix virtual CoinPackedMatrix * getPackedMatrix() const = 0; /** Whether the packed matrix is column major ordered or not. */ virtual bool isColOrdered() const = 0; /** Number of entries in the packed matrix. */ virtual CoinBigIndex getNumElements() const = 0; /** Number of columns. */ virtual int getNumCols() const = 0; /** Number of rows. */ virtual int getNumRows() const = 0; /** A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const double * getElements() const = 0; /** A vector containing the minor indices of the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const int * getIndices() const = 0; virtual const CoinBigIndex * getVectorStarts() const = 0; /** The lengths of the major-dimension vectors. */ virtual const int * getVectorLengths() const = 0 ; /** The length of a single major-dimension vector. */ virtual int getVectorLength(int index) const ; /** Delete the columns whose indices are listed in indDel. */ virtual void deleteCols(const int numDel, const int * indDel) = 0; /** Delete the rows whose indices are listed in indDel. */ virtual void deleteRows(const int numDel, const int * indDel) = 0; #ifndef CLP_NO_VECTOR /// Append Columns virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); /// Append Rows virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); #endif /** Modify one element of packed matrix. An element may be added. This works for either ordering If the new element is zero it will be deleted unless keepZero true */ virtual void modifyCoefficient(int row, int column, double newElement, bool keepZero = false); /** Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ virtual int appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther = -1); /** Returns a new matrix in reverse order without gaps Is allowed to return NULL if doesn't want to have row copy */ virtual ClpMatrixBase * reverseOrderedCopy() const { return NULL; } /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis(const int * whichColumn, int & numberColumnBasic) = 0; /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element) = 0; /** Creates scales for column copy (rowCopy in model may be modified) default does not allow scaling returns non-zero if no scaling done */ virtual int scale(ClpModel * , const ClpSimplex * = NULL) const { return 1; } /** Scales rowCopy if column copy scaled Only called if scales already exist */ virtual void scaleRowCopy(ClpModel * ) const { } /// Returns true if can create row copy virtual bool canGetRowCopy() const { return true; } /** Realy really scales column copy Only called if scales already exist. Up to user to delete */ inline virtual ClpMatrixBase * scaledColumnCopy(ClpModel * ) const { return this->clone(); } /** Checks if all elements are in valid range. Can just return true if you are not paranoid. For Clp I will probably expect no zeros. Code can modify matrix to get rid of small elements. check bits (can be turned off to save time) : 1 - check if matrix has gaps 2 - check if zero elements 4 - check and compress duplicates 8 - report on large and small */ virtual bool allElementsInRange(ClpModel * , double , double , int = 15) { return true; } /** Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ virtual void setDimensions(int numrows, int numcols); /** Returns largest and smallest elements of both signs. Largest refers to largest absolute value. If returns zeros then can't tell anything */ virtual void rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const = 0; /** Unpacks a column into an CoinIndexedvector ** in packed format Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const = 0; /** Purely for column generation and similar ideas. Allows matrix and any bounds or costs to be updated (sensibly). Returns non-zero if any changes. */ virtual int refresh(ClpSimplex * ) { return 0; } // Really scale matrix virtual void reallyScale(const double * rowScale, const double * columnScale); /** Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector Default returns vector of ones */ virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const = 0; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const = 0; /// Allow any parts of a created CoinPackedMatrix to be deleted virtual void releasePackedMatrix() const = 0; /// Says whether it can do partial pricing virtual bool canDoPartialPricing() const; /// Returns number of hidden rows e.g. gub virtual int hiddenRows() const; /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /** expands an updated column to allow for extra rows which the main solver does not know about and returns number added. This will normally be a no-op - it is in for GUB but may get extended to general non-overlapping and embedded networks. mode 0 - extend mode 1 - delete etc */ virtual int extendUpdated(ClpSimplex * model, CoinIndexedVector * update, int mode); /** utility primal function for dealing with dynamic constraints mode=0 - Set up before "update" and "times" for primal solution using extended rows mode=1 - Cleanup primal solution after "times" using extended rows. mode=2 - Check (or report on) primal infeasibilities */ virtual void primalExpanded(ClpSimplex * model, int mode); /** utility dual function for dealing with dynamic constraints mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended updates array (and may use other if dual values pass) mode=1 - Update dual solution after "transposeTimes" using extended rows. mode=2 - Compute all djs and compute key dual infeasibilities mode=3 - Report on key dual infeasibilities mode=4 - Modify before updateTranspose in partial pricing */ virtual void dualExpanded(ClpSimplex * model, CoinIndexedVector * array, double * other, int mode); /** general utility function for dealing with dynamic constraints mode=0 - Create list of non-key basics in pivotVariable_ using number as numberBasic in and out mode=1 - Set all key variables as basic mode=2 - return number extra rows needed, number gives maximum number basic mode=3 - before replaceColumn mode=4 - return 1 if can do primal, 2 if dual, 3 if both mode=5 - save any status stuff (when in good state) mode=6 - restore status stuff mode=7 - flag given variable (normally sequenceIn) mode=8 - unflag all variables mode=9 - synchronize costs and bounds mode=10 - return 1 if there may be changing bounds on variable (column generation) mode=11 - make sure set is clean (used when a variable rejected - but not flagged) mode=12 - after factorize but before permute stuff mode=13 - at end of simplex to delete stuff */ virtual int generalExpanded(ClpSimplex * model, int mode, int & number); /** update information for a pivot (and effective rhs) */ virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); /** Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ virtual void createVariable(ClpSimplex * model, int & bestSequence); /** Just for debug if odd type matrix. Returns number of primal infeasibilities. */ virtual int checkFeasible(ClpSimplex * model, double & sum) const ; /// Returns reduced cost of a variable double reducedCost(ClpSimplex * model, int sequence) const; /// Correct sequence in and out to give true value (if both -1 maybe do whole matrix) virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; //@} //--------------------------------------------------------------------------- /**@name Matrix times vector methods They can be faster if scalar is +- 1 Also for simplex I am not using basic/non-basic split */ //@{ /** Return y + A * x * scalar in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const = 0; /** And for scaling - default aborts for when scaling not supported (unless pointers NULL when as normal) */ virtual void times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ virtual void transposeTimes(double scalar, const double * x, double * y) const = 0; /** And for scaling - default aborts for when scaling not supported (unless pointers NULL when as normal) */ virtual void transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale, double * spare = NULL) const; #if COIN_LONG_WORK // For long double versions (aborts if not supported) virtual void times(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const ; virtual void transposeTimes(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const ; #endif /** Return x * scalar *A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const = 0; /** Return x *A in z but just for indices in y. This is only needed for primal steepest edge. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const = 0; /** Returns true if can combine transposeTimes and subsetTransposeTimes and if it would be faster */ virtual bool canCombine(const ClpSimplex * , const CoinIndexedVector * ) const { return false; } /// Updates two arrays for steepest and does devex weights (need not be coded) virtual void transposeTimes2(const ClpSimplex * model, const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * spare, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); /// Updates second array for steepest and does devex weights (need not be coded) virtual void subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); /** Return x *A in z but just for number indices in y. Default cheats with fake CoinIndexedVector and then calls subsetTransposeTimes */ virtual void listTransposeTimes(const ClpSimplex * model, double * x, int * y, int number, double * z) const; //@} //@{ ///@name Other /// Clone virtual ClpMatrixBase * clone() const = 0; /** Subset clone (without gaps). Duplicates are allowed and order is as given. Derived classes need not provide this as it may not always make sense */ virtual ClpMatrixBase * subsetClone ( int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const; /// Gets rid of any mutable by products virtual void backToBasics() {} /** Returns type. The types which code may need to know about are: 1 - ClpPackedMatrix 11 - ClpNetworkMatrix 12 - ClpPlusMinusOneMatrix */ inline int type() const { return type_; } /// Sets type void setType(int newtype) { type_ = newtype; } /// Sets up an effective RHS void useEffectiveRhs(ClpSimplex * model); /** Returns effective RHS offset if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, bool check = false); /// If rhsOffset used this is iteration last refreshed inline int lastRefresh() const { return lastRefresh_; } /// If rhsOffset used this is refresh frequency (0==off) inline int refreshFrequency() const { return refreshFrequency_; } inline void setRefreshFrequency(int value) { refreshFrequency_ = value; } /// whether to skip dual checks most of time inline bool skipDualCheck() const { return skipDualCheck_; } inline void setSkipDualCheck(bool yes) { skipDualCheck_ = yes; } /** Partial pricing tuning parameter - minimum number of "objects" to scan. e.g. number of Gub sets but could be number of variables */ inline int minimumObjectsScan() const { return minimumObjectsScan_; } inline void setMinimumObjectsScan(int value) { minimumObjectsScan_ = value; } /// Partial pricing tuning parameter - minimum number of negative reduced costs to get inline int minimumGoodReducedCosts() const { return minimumGoodReducedCosts_; } inline void setMinimumGoodReducedCosts(int value) { minimumGoodReducedCosts_ = value; } /// Current start of search space in matrix (as fraction) inline double startFraction() const { return startFraction_; } inline void setStartFraction(double value) { startFraction_ = value; } /// Current end of search space in matrix (as fraction) inline double endFraction() const { return endFraction_; } inline void setEndFraction(double value) { endFraction_ = value; } /// Current best reduced cost inline double savedBestDj() const { return savedBestDj_; } inline void setSavedBestDj(double value) { savedBestDj_ = value; } /// Initial number of negative reduced costs wanted inline int originalWanted() const { return originalWanted_; } inline void setOriginalWanted(int value) { originalWanted_ = value; } /// Current number of negative reduced costs which we still need inline int currentWanted() const { return currentWanted_; } inline void setCurrentWanted(int value) { currentWanted_ = value; } /// Current best sequence inline int savedBestSequence() const { return savedBestSequence_; } inline void setSavedBestSequence(int value) { savedBestSequence_ = value; } //@} protected: /**@name Constructors, destructor
NOTE: All constructors are protected. There's no need to expose them, after all, this is an abstract class. */ //@{ /** Default constructor. */ ClpMatrixBase(); /** Destructor (has to be public) */ public: virtual ~ClpMatrixBase(); protected: // Copy ClpMatrixBase(const ClpMatrixBase&); // Assignment ClpMatrixBase& operator=(const ClpMatrixBase&); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /** Effective RHS offset if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive */ double * rhsOffset_; /// Current start of search space in matrix (as fraction) double startFraction_; /// Current end of search space in matrix (as fraction) double endFraction_; /// Best reduced cost so far double savedBestDj_; /// Initial number of negative reduced costs wanted int originalWanted_; /// Current number of negative reduced costs which we still need int currentWanted_; /// Saved best sequence in pricing int savedBestSequence_; /// type (may be useful) int type_; /// If rhsOffset used this is iteration last refreshed int lastRefresh_; /// If rhsOffset used this is refresh frequency (0==off) int refreshFrequency_; /// Partial pricing tuning parameter - minimum number of "objects" to scan int minimumObjectsScan_; /// Partial pricing tuning parameter - minimum number of negative reduced costs to get int minimumGoodReducedCosts_; /// True sequence in (i.e. from larger problem) int trueSequenceIn_; /// True sequence out (i.e. from larger problem) int trueSequenceOut_; /// whether to skip dual checks most of time bool skipDualCheck_; //@} }; // bias for free variables #define FREE_BIAS 1.0e1 // Acceptance criteria for free variables #define FREE_ACCEPT 1.0e2 #endif Clp-1.15.10/src/ClpPredictorCorrector.hpp0000644000076600007660000000625211510657452016643 0ustar coincoin/* $Id: ClpPredictorCorrector.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). /* Authors John Forrest */ #ifndef ClpPredictorCorrector_H #define ClpPredictorCorrector_H #include "ClpInterior.hpp" /** This solves LPs using the predictor-corrector method due to Mehrotra. It also uses multiple centrality corrections as in Gondzio. See; S. Mehrotra, "On the implementation of a primal-dual interior point method", SIAM Journal on optimization, 2 (1992) J. Gondzio, "Multiple centraility corrections in a primal-dual method for linear programming", Computational Optimization and Applications",6 (1996) It is rather basic as Interior point is not my speciality It inherits from ClpInterior. It has no data of its own and is never created - only cast from a ClpInterior object at algorithm time. It can also solve QPs */ class ClpPredictorCorrector : public ClpInterior { public: /**@name Description of algorithm */ //@{ /** Primal Dual Predictor Corrector algorithm Method Big TODO */ int solve(); //@} /**@name Functions used in algorithm */ //@{ /// findStepLength. //phase - 0 predictor // 1 corrector // 2 primal dual CoinWorkDouble findStepLength( int phase); /// findDirectionVector. CoinWorkDouble findDirectionVector(const int phase); /// createSolution. Creates solution from scratch (- code if no memory) int createSolution(); /// complementarityGap. Computes gap //phase 0=as is , 1 = after predictor , 2 after corrector CoinWorkDouble complementarityGap(int & numberComplementarityPairs, int & numberComplementarityItems, const int phase); /// setupForSolve. //phase 0=affine , 1 = corrector , 2 = primal-dual void setupForSolve(const int phase); /** Does solve. region1 is for deltaX (columns+rows), region2 for deltaPi (rows) */ void solveSystem(CoinWorkDouble * region1, CoinWorkDouble * region2, const CoinWorkDouble * region1In, const CoinWorkDouble * region2In, const CoinWorkDouble * saveRegion1, const CoinWorkDouble * saveRegion2, bool gentleRefine); /// sees if looks plausible change in complementarity bool checkGoodMove(const bool doCorrector, CoinWorkDouble & bestNextGap, bool allowIncreasingGap); ///: checks for one step size bool checkGoodMove2(CoinWorkDouble move, CoinWorkDouble & bestNextGap, bool allowIncreasingGap); /// updateSolution. Updates solution at end of iteration //returns number fixed int updateSolution(CoinWorkDouble nextGap); /// Save info on products of affine deltaT*deltaW and deltaS*deltaZ CoinWorkDouble affineProduct(); ///See exactly what would happen given current deltas void debugMove(int phase, CoinWorkDouble primalStep, CoinWorkDouble dualStep); //@} }; #endif Clp-1.15.10/src/ClpMain.cpp0000644000076600007660000066237012253625014013707 0ustar coincoin/* $Id: ClpMain.cpp 2009 2013-12-16 16:27:56Z 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 "CoinPragma.hpp" #include #include #include #include #include #include #include int boundary_sort = 1000; int boundary_sort2 = 1000; int boundary_sort3 = 10000; #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinSort.hpp" // History since 1.0 at end #include "ClpConfig.h" #include "CoinMpsIO.hpp" #include "CoinFileIO.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 #include "AbcCommon.hpp" #include "ClpFactorization.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" #include "CbcOrClpParam.hpp" #include "CoinSignal.hpp" #include "CoinWarmStartBasis.hpp" #ifdef ABC_INHERIT #include "AbcSimplex.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcDualRowSteepest.hpp" #include "AbcDualRowDantzig.hpp" #endif //#define COIN_HAS_ASL #ifdef COIN_HAS_ASL #include "Clp_ampl.h" #endif #ifdef DMALLOC #include "dmalloc.h" #endif #if defined(COIN_HAS_WSMP) || defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(TAUCS_BARRIER) || defined(COIN_HAS_MUMPS) #define FOREIGN_BARRIER #endif static double totalTime = 0.0; static bool maskMatches(const int * starts, char ** masks, std::string & check); #ifndef ABC_INHERIT static ClpSimplex * currentModel = NULL; #else static AbcSimplex * currentModel = NULL; #endif extern "C" { static void #if defined(_MSC_VER) __cdecl #endif // _MSC_VER signal_handler(int /*whichSignal*/) { if (currentModel != NULL) currentModel->setMaximumIterations(0); // stop at next iterations return; } } //############################################################################# #ifdef NDEBUG #undef NDEBUG #endif #ifndef ABC_INHERIT int mainTest (int argc, const char *argv[], int algorithm, ClpSimplex empty, ClpSolve solveOptions, int switchOff, bool doVector); #else int mainTest (int argc, const char *argv[], int algorithm, AbcSimplex empty, ClpSolve solveOptions, int switchOff, bool doVector); #endif static void statistics(ClpSimplex * originalModel, ClpSimplex * model); static void generateCode(const char * fileName, int type); // Returns next valid field int CbcOrClpRead_mode = 1; FILE * CbcOrClpReadCommand = stdin; extern int CbcOrClpEnvironmentIndex; #ifdef CLP_USER_DRIVEN1 /* Returns true if variable sequenceOut can leave basis when model->sequenceIn() enters. This function may be entered several times for each sequenceOut. The first time realAlpha will be positive if going to lower bound and negative if going to upper bound (scaled bounds in lower,upper) - then will be zero. currentValue is distance to bound. currentTheta is current theta. alpha is fabs(pivot element). Variable will change theta if currentValue - currentTheta*alpha < 0.0 */ bool userChoiceValid1(const ClpSimplex * model, int sequenceOut, double currentValue, double currentTheta, double alpha, double realAlpha) { return true; } /* This returns true if chosen in/out pair valid. The main thing to check would be variable flipping bounds may be OK. This would be signaled by reasonable theta_ and valueOut_. If you return false sequenceIn_ will be flagged as ineligible. */ bool userChoiceValid2(const ClpSimplex * model) { return true; } /* If a good pivot then you may wish to unflag some variables. */ void userChoiceWasGood(ClpSimplex * model) { } #endif //#define CILK_TEST #ifdef CILK_TEST static void cilkTest(); #endif int #if defined(_MSC_VER) __cdecl #endif // _MSC_VER main (int argc, const char *argv[]) { #ifdef CILK_TEST cilkTest(); #endif // next {} is just to make sure all memory should be freed - for debug { double time1 = CoinCpuTime(), time2; // Set up all non-standard stuff //int numberModels=1; #ifndef ABC_INHERIT ClpSimplex * models = new ClpSimplex[1]; #else AbcSimplex * models = new AbcSimplex[1]; #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 doCrash = 0; int doVector = 0; int doSprint = -1; // set reasonable defaults #ifdef ABC_INHERIT #define DEFAULT_PRESOLVE_PASSES 20 #else #define DEFAULT_PRESOLVE_PASSES 5 #endif int preSolve = DEFAULT_PRESOLVE_PASSES; bool preSolveFile = false; models->setPerturbation(50); models->messageHandler()->setPrefix(false); 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 = ".\\"; # ifdef COIN_MSVS // Visual Studio builds are deeper dirSample = "..\\..\\..\\..\\Data\\Sample\\"; dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\"; dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\"; # else dirSample = "..\\..\\Data\\Sample\\"; dirNetlib = "..\\..\\Data\\Netlib\\"; dirMiplib = "..\\..\\Data\\miplib3\\"; # endif } std::string defaultDirectory = directory; std::string importFile = ""; std::string exportFile = "default.mps"; std::string importBasisFile = ""; int basisHasValues = 0; int substitution = 3; int dualize = 3; // dualize if looks promising std::string exportBasisFile = "default.bas"; std::string saveFile = "default.prob"; std::string restoreFile = "default.prob"; std::string solutionFile = "stdout"; std::string solutionSaveFile = "solution.file"; std::string printMask = ""; CbcOrClpParam parameters[CBCMAXPARAMETERS]; int numberParameters ; establishParams(numberParameters, parameters) ; parameters[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters, parameters)].setStringValue(importBasisFile); parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters, parameters)].setStringValue(exportBasisFile); 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(models->dualBound()); parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters, parameters)].setDoubleValue(models->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_INT_SOLVERLOGLEVEL, numberParameters, parameters)].setIntValue(models->logLevel()); parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters, parameters)].setIntValue(models->factorizationFrequency()); parameters[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters, parameters)].setIntValue(models->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(models->perturbation()); parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters, parameters)].setDoubleValue(models->primalTolerance()); parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters, parameters)].setDoubleValue(models->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(models->maximumSeconds()); parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, 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(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].setDoubleValue(1.0e-8); int verbose = 0; // total number of commands read int numberGoodCommands = 0; bool * goodModels = new bool[1]; goodModels[0] = false; #ifdef COIN_HAS_ASL ampl_info info; int usingAmpl=0; CoinMessageHandler * generalMessageHandler = models->messageHandler(); generalMessageHandler->setPrefix(false); CoinMessages generalMessages = models->messages(); char generalPrint[10000]; { bool noPrinting_=false; memset(&info, 0, sizeof(info)); if (argc > 2 && !strcmp(argv[2], "-AMPL")) { usingAmpl = 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); 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_) { models->messageHandler()->setLogLevel(0); setCbcOrClpPrinting(false); } if (!noPrinting_) printf("%d rows, %d columns and %d elements\n", info.numberRows, info.numberColumns, info.numberElements); models->loadProblem(info.numberColumns, info.numberRows, info.starts, info.rows, info.elements, info.columnLower, info.columnUpper, info.objective, info.rowLower, info.rowUpper); // If we had a solution use it if (info.primalSolution) { models->setColSolution(info.primalSolution); } // status if (info.rowStatus) { unsigned char * statusArray = models->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]); } freeArrays1(&info); // modify objective if necessary models->setOptimizationDirection(info.direction); models->setObjectiveOffset(info.offset); if (info.offset) { sprintf(generalPrint, "Ampl objective offset is %g", info.offset); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } goodModels[0] = true; // change argc etc argc = info.numberArguments; argv = const_cast(info.arguments); } } #endif // Hidden stuff for barrier int choleskyType = 0; int gamma = 0; parameters[whichParam(CLP_PARAM_STR_BARRIERSCALE, numberParameters, parameters)].setCurrentOption(2); int scaleBarrier = 2; int doKKT = 0; int crossover = 2; // do crossover unless quadratic int iModel = 0; //models[0].scaling(1); //models[0].setDualBound(1.0e6); //models[0].setDualTolerance(1.0e-7); //ClpDualRowSteepest steep; //models[0].setDualRowPivotAlgorithm(steep); #ifdef ABC_INHERIT models[0].setDualTolerance(1.0e-6); models[0].setPrimalTolerance(1.0e-6); #endif //ClpPrimalColumnSteepest steepP; //models[0].setPrimalColumnPivotAlgorithm(steepP); std::string field; std::cout << "Coin LP version " << CLP_VERSION << ", build " << __DATE__ << std::endl; // Print command line if (argc > 1) { printf("command line - "); for (int i = 0; i < argc; i++) printf("%s ", argv[i]); printf("\n"); } while (1) { // next command field = CoinReadGetCommand(argc, argv); // exit if null or similar if (!field.length()) { if (numberGoodCommands == 1 && goodModels[0]) { // we just had file name - do dual or primal field = "either"; } else if (!numberGoodCommands) { // let's give the sucker a hint std::cout << "Clp 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 int 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; } } ClpSimplex * thisModel=models+iModel; if (iParam < numberParameters && !numberQuery) { // found CbcOrClpParam found = parameters[iParam]; CbcOrClpParameterType type = found.type(); int valid; numberGoodCommands++; if (type == CBC_PARAM_GENERALQUERY) { 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; int maxAcross = 10; 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 && usingAmpl) verbose += 4; #endif if (verbose) maxAcross = 1; int limits[] = {1, 101, 201, 301, 401}; std::vector types; types.push_back("Double parameters:"); types.push_back("Int parameters:"); types.push_back("Keyword parameters:"); types.push_back("Actions or string parameters:"); int iType; for (iType = 0; iType < 4; 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]) { 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) { // 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, 101, 201, 301, 401}; std::vector types; types.push_back("Double parameters:"); types.push_back("Int parameters:"); types.push_back("Keyword parameters and others:"); types.push_back("Actions:"); int iType; for (iType = 0; iType < 4; iType++) { int across = 0; std::cout << types[iType] << std::endl; 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) { parameters[iParam].setDoubleParameter(thisModel, value); } 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 (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_VERBOSE) verbose = value; parameters[iParam].setIntParameter(thisModel, value); } 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 { parameters[iParam].setCurrentOption(action); // for now hard wired switch (type) { case CLP_PARAM_STR_DIRECTION: if (action == 0) { models[iModel].setOptimizationDirection(1); #ifdef ABC_INHERIT thisModel->setOptimizationDirection(1); #endif } else if (action == 1) { models[iModel].setOptimizationDirection(-1); #ifdef ABC_INHERIT thisModel->setOptimizationDirection(-1); #endif } else { models[iModel].setOptimizationDirection(0); #ifdef ABC_INHERIT thisModel->setOptimizationDirection(0); #endif } break; case CLP_PARAM_STR_DUALPIVOT: if (action == 0) { ClpDualRowSteepest steep(3); thisModel->setDualRowPivotAlgorithm(steep); #ifdef ABC_INHERIT AbcDualRowSteepest steep2(3); models[iModel].setDualRowPivotAlgorithm(steep2); #endif } else if (action == 1) { //ClpDualRowDantzig dantzig; ClpDualRowDantzig dantzig; thisModel->setDualRowPivotAlgorithm(dantzig); #ifdef ABC_INHERIT AbcDualRowDantzig dantzig2; models[iModel].setDualRowPivotAlgorithm(dantzig2); #endif } else if (action == 2) { // partial steep ClpDualRowSteepest steep(2); thisModel->setDualRowPivotAlgorithm(steep); #ifdef ABC_INHERIT AbcDualRowSteepest steep2(2); models[iModel].setDualRowPivotAlgorithm(steep2); #endif } else { ClpDualRowSteepest steep; thisModel->setDualRowPivotAlgorithm(steep); #ifdef ABC_INHERIT AbcDualRowSteepest steep2; models[iModel].setDualRowPivotAlgorithm(steep2); #endif } break; case CLP_PARAM_STR_PRIMALPIVOT: if (action == 0) { ClpPrimalColumnSteepest steep(3); thisModel->setPrimalColumnPivotAlgorithm(steep); } else if (action == 1) { ClpPrimalColumnSteepest steep(0); thisModel->setPrimalColumnPivotAlgorithm(steep); } else if (action == 2) { ClpPrimalColumnDantzig dantzig; thisModel->setPrimalColumnPivotAlgorithm(dantzig); } else if (action == 3) { ClpPrimalColumnSteepest steep(4); thisModel->setPrimalColumnPivotAlgorithm(steep); } else if (action == 4) { ClpPrimalColumnSteepest steep(1); thisModel->setPrimalColumnPivotAlgorithm(steep); } else if (action == 5) { ClpPrimalColumnSteepest steep(2); thisModel->setPrimalColumnPivotAlgorithm(steep); } else if (action == 6) { ClpPrimalColumnSteepest steep(10); thisModel->setPrimalColumnPivotAlgorithm(steep); } break; case CLP_PARAM_STR_SCALING: thisModel->scaling(action); break; case CLP_PARAM_STR_AUTOSCALE: thisModel->setAutomaticScaling(action != 0); break; case CLP_PARAM_STR_SPARSEFACTOR: thisModel->setSparseFactorization((1 - action) != 0); break; case CLP_PARAM_STR_BIASLU: thisModel->factorization()->setBiasLU(action); break; case CLP_PARAM_STR_PERTURBATION: if (action == 0) thisModel->setPerturbation(50); else thisModel->setPerturbation(100); break; case CLP_PARAM_STR_ERRORSALLOWED: allowImportErrors = action; break; case CLP_PARAM_STR_ABCWANTED: models[iModel].setAbcState(action); break; case CLP_PARAM_STR_INTPRINT: printMode = action; break; case CLP_PARAM_STR_KEEPNAMES: keepImportNames = 1 - action; break; case CLP_PARAM_STR_PRESOLVE: if (action == 0) preSolve = DEFAULT_PRESOLVE_PASSES; else if (action == 1) preSolve = 0; else if (action == 2) preSolve = 10; else preSolveFile = true; break; case CLP_PARAM_STR_PFI: thisModel->factorization()->setForrestTomlin(action == 0); break; case CLP_PARAM_STR_FACTORIZATION: models[iModel].factorization()->forceOtherFactorization(action); #ifdef ABC_INHERIT thisModel->factorization()->forceOtherFactorization(action); #endif break; case CLP_PARAM_STR_CRASH: doCrash = action; break; case CLP_PARAM_STR_VECTOR: doVector = action; break; case CLP_PARAM_STR_MESSAGES: models[iModel].messageHandler()->setPrefix(action != 0); #ifdef ABC_INHERIT thisModel->messageHandler()->setPrefix(action != 0); #endif 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; default: //abort(); break; } } } else { // action if (type == CLP_PARAM_ACTION_EXIT) { #ifdef COIN_HAS_ASL if (usingAmpl) { 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_EITHERSIMPLEX: case CLP_PARAM_ACTION_BARRIER: // synonym for dual case CBC_PARAM_ACTION_BAB: if (goodModels[iModel]) { if (type==CLP_PARAM_ACTION_EITHERSIMPLEX|| type==CBC_PARAM_ACTION_BAB) models[iModel].setMoreSpecialOptions(16384| models[iModel].moreSpecialOptions()); double objScale = parameters[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters, parameters)].doubleValue(); if (objScale != 1.0) { int iColumn; int numberColumns = models[iModel].numberColumns(); double * dualColumnSolution = models[iModel].dualColumnSolution(); ClpObjective * obj = models[iModel].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 = models[iModel].numberRows(); double * dualRowSolution = models[iModel].dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) dualRowSolution[iRow] *= objScale; models[iModel].setObjectiveOffset(objScale * models[iModel].objectiveOffset()); } ClpSolve::SolveType method; ClpSolve::PresolveType presolveType; ClpSolve solveOptions; #ifndef ABC_INHERIT ClpSimplex * model2 = models + iModel; #else AbcSimplex * model2 = models + iModel; if (type==CLP_PARAM_ACTION_EITHERSIMPLEX|| type==CBC_PARAM_ACTION_BAB) solveOptions.setSpecialOption(3,0); // allow +-1 #endif if (dualize==4) { solveOptions.setSpecialOption(4, 77); dualize=0; } if (dualize) { bool tryIt = true; double fractionColumn = 1.0; double fractionRow = 1.0; if (dualize == 3) { dualize = 1; int numberColumns = model2->numberColumns(); int numberRows = model2->numberRows(); #ifndef ABC_INHERIT if (numberRows < 50000 || 5 * numberColumns > numberRows) { #else if (numberRows < 500 || 4 * numberColumns > numberRows) { #endif tryIt = false; } else { fractionColumn = 0.1; fractionRow = 0.3; } } if (tryIt) { ClpSimplex * thisModel=model2; thisModel = static_cast (thisModel)->dualOfModel(fractionRow, fractionColumn); if (thisModel) { printf("Dual of model has %d rows and %d columns\n", thisModel->numberRows(), thisModel->numberColumns()); thisModel->setOptimizationDirection(1.0); #ifndef ABC_INHERIT model2=thisModel; #else int abcState=model2->abcState(); model2=new AbcSimplex(*thisModel); model2->setAbcState(abcState); delete thisModel; #endif } else { thisModel = models + iModel; dualize = 0; } } else { dualize = 0; } } if (preSolveFile) presolveOptions |= 0x40000000; solveOptions.setPresolveActions(presolveOptions); solveOptions.setSubstitution(substitution); if (preSolve != DEFAULT_PRESOLVE_PASSES && preSolve) { presolveType = ClpSolve::presolveNumber; if (preSolve < 0) { preSolve = - preSolve; if (preSolve <= 100) { presolveType = ClpSolve::presolveNumber; printf("Doing %d presolve passes - picking up non-costed slacks\n", preSolve); solveOptions.setDoSingletonColumn(true); } else { preSolve -= 100; presolveType = ClpSolve::presolveNumberCost; printf("Doing %d presolve passes - picking up costed slacks\n", preSolve); } } } else if (preSolve) { presolveType = ClpSolve::presolveOn; } else { presolveType = ClpSolve::presolveOff; } solveOptions.setPresolveType(presolveType, preSolve); if (type == CLP_PARAM_ACTION_DUALSIMPLEX || type == CBC_PARAM_ACTION_BAB) { method = ClpSolve::useDual; } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) { method = ClpSolve::usePrimalorSprint; } else if (type == CLP_PARAM_ACTION_EITHERSIMPLEX) { method = ClpSolve::automatic; } else { method = ClpSolve::useBarrier; #ifdef ABC_INHERIT if (doIdiot > 0) solveOptions.setSpecialOption(1, 2, doIdiot); // dense threshold #endif if (crossover == 1) { method = ClpSolve::useBarrierNoCross; } else if (crossover == 2) { ClpObjective * obj = models[iModel].objectiveAsObject(); if (obj->type() > 1) { method = ClpSolve::useBarrierNoCross; presolveType = ClpSolve::presolveOff; solveOptions.setPresolveType(presolveType, preSolve); } } } solveOptions.setSolveType(method); solveOptions.setSpecialOption(5, printOptions & 1); if (doVector) { ClpMatrixBase * matrix = models[iModel].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) { if ((scaleBarrier & 1) != 0) barrierOptions |= 8; barrierOptions |= 2048 * (scaleBarrier >> 1); } if (doKKT) barrierOptions |= 16; if (gamma) barrierOptions |= 32 * gamma; if (crossover == 3) barrierOptions |= 256; // try presolve in crossover solveOptions.setSpecialOption(4, barrierOptions); } int status; if (cppValue >= 0) { // generate code FILE * fp = fopen("user_driver.cpp", "w"); if (fp) { // generate enough to do solveOptions model2->generateCpp(fp); solveOptions.generateCpp(fp); fclose(fp); // now call generate code generateCode("user_driver.cpp", cppValue); } else { std::cout << "Unable to open file user_driver.cpp" << std::endl; } } #ifdef CLP_MULTIPLE_FACTORIZATIONS int denseCode = parameters[whichParam(CBC_PARAM_INT_DENSE, numberParameters, parameters)].intValue(); if (denseCode!=-1) model2->factorization()->setGoDenseThreshold(denseCode); int smallCode = parameters[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters, parameters)].intValue(); if (smallCode!=-1) model2->factorization()->setGoSmallThreshold(smallCode); model2->factorization()->goDenseOrSmall(model2->numberRows()); #endif try { status = model2->initialSolve(solveOptions); #ifndef NDEBUG // if infeasible check ray if (model2->status()==1) { ClpSimplex * simplex = model2; if(simplex->ray()) { // make sure we use non-scaled versions ClpPackedMatrix * saveMatrix = simplex->swapScaledMatrix(NULL); double * saveScale = simplex->swapRowScale(NULL); // 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; // get ray as user would double * ray = simplex->infeasibilityRay(); // get farkas row memset(farkas,0,(2*numberColumns+numberRows)*sizeof(double)); simplex->transposeTimes(-1.0,ray,farkas); // 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; if (fabs(effectiveRhs[i])>1.0e10) printf("Large rhs row %d %g\n", i,effectiveRhs[i]); } simplex->times(-1.0,bound,effectiveRhs); double bSum=0.0; for (int i=0;i1.0e10) printf("Large rhs row %d %g after\n", i,effectiveRhs[i]); } if (numberBad||bSum>1.0e-6) { printf("Bad infeasibility ray %g - %d bad\n", bSum,numberBad); } else { //printf("Good ray - infeasibility %g\n", // -bSum); } delete [] ray; delete [] farkas; simplex->swapRowScale(saveScale); simplex->swapScaledMatrix(saveMatrix); } else { //printf("No dual ray\n"); } } #endif } catch (CoinError e) { e.print(); status = -1; } if (dualize) { ClpSimplex * thisModel=models+iModel; int returnCode = static_cast (thisModel)->restoreFromDual(model2); if (model2->status() == 3) returnCode = 0; delete model2; if (returnCode && dualize != 2) { currentModel = models + iModel; // register signal handler signal(SIGINT, signal_handler); thisModel->primal(1); currentModel = NULL; } // switch off (user can switch back on) parameters[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters, parameters)].setIntValue(dualize); } if (status >= 0) basisHasValues = 1; } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_STATISTICS: if (goodModels[iModel]) { // If presolve on look at presolved bool deleteModel2 = false; ClpSimplex * model2 = models + iModel; 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(models[iModel], presolveTolerance, true, preSolve); if (model2) { printf("Statistics for presolved model\n"); deleteModel2 = true; } else { printf("Presolved model looks infeasible - will use unpresolved\n"); model2 = models + iModel; } } else { printf("Statistics for unpresolved model\n"); model2 = models + iModel; } statistics(models + iModel, model2); if (deleteModel2) delete model2; } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_TIGHTEN: if (goodModels[iModel]) { int numberInfeasibilities = models[iModel].tightenPrimalBounds(); if (numberInfeasibilities) std::cout << "** Analysis indicates model infeasible" << std::endl; } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_PLUSMINUS: if (goodModels[iModel]) { ClpMatrixBase * saveMatrix = models[iModel].clpMatrix(); ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(saveMatrix); if (clpMatrix) { ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); if (newMatrix->getIndices()) { models[iModel].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 { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_NETWORK: if (goodModels[iModel]) { ClpMatrixBase * saveMatrix = models[iModel].clpMatrix(); ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(saveMatrix); if (clpMatrix) { ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix())); if (newMatrix->getIndices()) { models[iModel].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 { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_IMPORT: { // 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 == "-") { // stdin canOpen = true; fileName = "-"; } 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 (percent < length && percent > 0) { 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; if (!gmpl) status = models[iModel].readMps(fileName.c_str(), keepImportNames != 0, allowImportErrors != 0); else if (gmpl > 0) status = models[iModel].readGMPL(fileName.c_str(), (gmpl == 2) ? gmplData.c_str() : NULL, keepImportNames != 0); else #ifdef KILL_ZERO_READLP status = models[iModel].readLp(fileName.c_str(), models[iModel].getSmallElementValue()); #else status = models[iModel].readLp(fileName.c_str(), 1.0e-12); #endif if (!status || (status > 0 && allowImportErrors)) { goodModels[iModel] = true; // sets to all slack (not necessary?) thisModel->createStatus(); 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_EXPORT: if (goodModels[iModel]) { double objScale = parameters[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters, parameters)].doubleValue(); if (objScale != 1.0) { int iColumn; int numberColumns = models[iModel].numberColumns(); double * dualColumnSolution = models[iModel].dualColumnSolution(); ClpObjective * obj = models[iModel].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 = models[iModel].numberRows(); double * dualRowSolution = models[iModel].dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) dualRowSolution[iRow] *= objScale; models[iModel].setObjectiveOffset(objScale * models[iModel].objectiveOffset()); } // 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 = models + iModel; if (dualize && dualize < 3) { model2 = static_cast (model2)->dualOfModel(); printf("Dual of model has %d rows and %d columns\n", model2->numberRows(), model2->numberColumns()); model2->setOptimizationDirection(1.0); preSolve = 0; // as picks up from model } 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(models[iModel], presolveTolerance, true, preSolve, false, false); 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 = models + iModel; } } else { printf("Saving model on %s\n", fileName.c_str()); } #if 0 // 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()); #ifdef STRIPBLANKS char * xx = rowNames[iRow]; int i; int length = strlen(xx); int n = 0; for (i = 0; i < length; i++) { if (xx[i] != ' ') xx[n++] = xx[i]; } xx[n] = '\0'; #endif } columnNames = new char * [numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnNames[iColumn] = CoinStrdup(model2->columnName(iColumn).c_str()); #ifdef STRIPBLANKS char * xx = columnNames[iColumn]; int i; int length = strlen(xx); int n = 0; for (i = 0; i < length; i++) { if (xx[i] != ' ') xx[n++] = xx[i]; } xx[n] = '\0'; #endif } } CoinMpsIO writer; writer.setMpsData(*model2->matrix(), COIN_DBL_MAX, model2->getColLower(), model2->getColUpper(), model2->getObjCoefficients(), (const char*) 0 /*integrality*/, model2->getRowLower(), model2->getRowUpper(), columnNames, rowNames); // Pass in array saying if each variable integer writer.copyInIntegerInformation(model2->integerInformation()); writer.setObjectiveOffset(model2->objectiveOffset()); writer.writeMps(fileName.c_str(), 0, 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 model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1)); #endif if (deleteModel2) delete model2; time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_BASISIN: if (goodModels[iModel]) { // 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) { int values = thisModel->readBasis(fileName.c_str()); if (values == 0) basisHasValues = -1; else basisHasValues = 1; } } else { std::cout << "** Current model not valid" << std::endl; } 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 (goodModels[iModel]) { // 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 = models + iModel; model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2); time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_PARAMETRICS: if (goodModels[iModel]) { // 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; } ClpSimplex * model2 = models + iModel; static_cast (model2)->parametrics(fileName.c_str()); time2 = CoinCpuTime(); totalTime += time2 - time1; time1 = time2; } else { std::cout << "** Current model not valid" << std::endl; } 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 = models + iModel; if (preSolve) { ClpPresolve pinfo; double presolveTolerance = parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].doubleValue(); model2 = pinfo.presolvedModel(models[iModel], 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 = models + iModel; } } else { printf("Saving model on %s\n", fileName.c_str()); } status = model2->saveModel(fileName.c_str()); if (deleteModel2) delete model2; if (!status) { goodModels[iModel] = 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 = models[iModel].restoreModel(fileName.c_str()); if (!status) { goodModels[iModel] = 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: models[iModel].setOptimizationDirection(-1); #ifdef ABC_INHERIT thisModel->setOptimizationDirection(-1); #endif break; case CLP_PARAM_ACTION_MINIMIZE: models[iModel].setOptimizationDirection(1); #ifdef ABC_INHERIT thisModel->setOptimizationDirection(1); #endif break; case CLP_PARAM_ACTION_ALLSLACK: thisModel->allSlackBasis(true); #ifdef ABC_INHERIT models[iModel].allSlackBasis(); #endif break; case CLP_PARAM_ACTION_REVERSE: if (goodModels[iModel]) { int iColumn; int numberColumns = models[iModel].numberColumns(); double * dualColumnSolution = models[iModel].dualColumnSolution(); ClpObjective * obj = models[iModel].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 = models[iModel].numberRows(); double * dualRowSolution = models[iModel].dualRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) { dualRowSolution[iRow] = -dualRowSolution[iRow]; } models[iModel].setObjectiveOffset(-models[iModel].objectiveOffset()); } 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: { // create fields for unitTest const char * fields[4]; int nFields = 4; fields[0] = "fake main from unitTest"; std::string mpsfield = "-dirSample="; mpsfield += dirSample.c_str(); fields[1] = mpsfield.c_str(); std::string netfield = "-dirNetlib="; netfield += dirNetlib.c_str(); fields[2] = netfield.c_str(); fields[3] = "-netlib"; int algorithm; if (type == CLP_PARAM_ACTION_NETLIB_DUAL) { std::cerr << "Doing netlib with dual algorithm" << std::endl; algorithm = 0; models[iModel].setMoreSpecialOptions(models[iModel].moreSpecialOptions()|32768); } else if (type == CLP_PARAM_ACTION_NETLIB_BARRIER) { std::cerr << "Doing netlib with barrier algorithm" << std::endl; algorithm = 2; } else if (type == CLP_PARAM_ACTION_NETLIB_EITHER) { std::cerr << "Doing netlib with dual or primal algorithm" << std::endl; algorithm = 3; } else if (type == CLP_PARAM_ACTION_NETLIB_TUNE) { std::cerr << "Doing netlib with best algorithm!" << std::endl; algorithm = 5; // uncomment next to get active tuning // algorithm=6; } else { std::cerr << "Doing netlib with primal algorithm" << std::endl; algorithm = 1; } //int specialOptions = models[iModel].specialOptions(); models[iModel].setSpecialOptions(0); ClpSolve solveOptions; ClpSolve::PresolveType presolveType; if (preSolve) presolveType = ClpSolve::presolveOn; else presolveType = ClpSolve::presolveOff; solveOptions.setPresolveType(presolveType, 5); if (doSprint >= 0 || doIdiot >= 0) { if (doSprint > 0) { // sprint overrides idiot solveOptions.setSpecialOption(1, 3, doSprint); // sprint } else if (doIdiot > 0) { solveOptions.setSpecialOption(1, 2, doIdiot); // idiot } else { 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 FACTORIZATION_STATISTICS { extern int loSizeX; extern int hiSizeX; for (int i=0;i0) loSizeX=size; } if (!strcmp(argv[i],"-hisize")) { int size=atoi(argv[i+1]); if (size>loSizeX) hiSizeX=size; } } if (loSizeX!=-1||hiSizeX!=1000000) printf("Solving problems %d<= and <%d\n",loSizeX,hiSizeX); } #endif // for moment then back to models[iModel] #ifndef ABC_INHERIT int specialOptions = models[iModel].specialOptions(); mainTest(nFields, fields, algorithm, *thisModel, solveOptions, specialOptions, doVector != 0); #else //if (!processTune) { //specialOptions=0; //models->setSpecialOptions(models->specialOptions()&~65536); // } mainTest(nFields, fields, algorithm, *models, solveOptions, 0, doVector != 0); #endif } break; case CLP_PARAM_ACTION_UNITTEST: { // create fields for unitTest const char * fields[2]; int nFields = 2; fields[0] = "fake main from unitTest"; std::string dirfield = "-dirSample="; dirfield += dirSample.c_str(); fields[1] = dirfield.c_str(); int specialOptions = models[iModel].specialOptions(); models[iModel].setSpecialOptions(0); int algorithm = -1; if (models[iModel].numberRows()) algorithm = 7; ClpSolve solveOptions; ClpSolve::PresolveType presolveType; if (preSolve) presolveType = ClpSolve::presolveOn; else presolveType = ClpSolve::presolveOff; solveOptions.setPresolveType(presolveType, 5); #ifndef ABC_INHERIT mainTest(nFields, fields, algorithm, *thisModel, solveOptions, specialOptions, doVector != 0); #else mainTest(nFields, fields, algorithm, *models, solveOptions, specialOptions, doVector != 0); #endif } break; case CLP_PARAM_ACTION_FAKEBOUND: if (goodModels[iModel]) { // 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 = models[iModel].numberRows(); double * rowLower = models[iModel].rowLower(); double * rowUpper = models[iModel].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 = models[iModel].numberColumns(); double * columnLower = models[iModel].columnLower(); double * columnUpper = models[iModel].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 (goodModels[iModel]) { ClpSimplex newModel(models[iModel], models[iModel].scalingFlag()); printf("model really really scaled\n"); models[iModel] = newModel; } break; case CLP_PARAM_ACTION_USERCLP: // Replace the sample code by whatever you want if (goodModels[iModel]) { ClpSimplex * thisModel = &models[iModel]; printf("Dummy user code - model has %d rows and %d columns\n", thisModel->numberRows(), thisModel->numberColumns()); } break; case CLP_PARAM_ACTION_HELP: std::cout << "Coin LP version " << CLP_VERSION << ", build " << __DATE__ << std::endl; std::cout << "Non default values:-" << std::endl; std::cout << "Perturbation " << models[0].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_SOLUTION: case CLP_PARAM_ACTION_GMPL_SOLUTION: if (goodModels[iModel]) { // 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; fprintf(fp, "\n"); } else if (field == "stderr") { // stderr fp = stderr; fprintf(fp, "\n"); } 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; } if (!append) fp = fopen(fileName.c_str(), "w"); else fp = fopen(fileName.c_str(), "a"); } if (fp) { // See if Glpk if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) { int numberRows = models[iModel].getNumRows(); int numberColumns = models[iModel].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 = models[iModel].status(); int iStat2 = GLP_UNDEF; if (iStat == 0) { // optimal 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) { iStat2 = GLP_FEAS; } double objValue = models[iModel].getObjValue() * models[iModel].getObjSense(); fprintf(fp,"%d 2 %g\n",iStat2,objValue); if (numberGlpkRows > numberRows) { // objective as row fprintf(fp,"4 %g 1.0\n",objValue); } int lookup[6]= {4,1,3,2,4,5}; const double * primalRowSolution = models[iModel].primalRowSolution(); const double * dualRowSolution = models[iModel].dualRowSolution(); for (int i=0;iupper-1.0e-6) { numberAtUpper++; } else { numberBetween++; largestAway=CoinMax(largestAway, CoinMin(primal-lower,upper-primal)); } } printf("For rows %d at lower, %d between, %d at upper - lowest %g, highest %g most away %g - highest dual %g lowest %g\n", numberAtLower,numberBetween,numberAtUpper, lowestPrimal,highestPrimal,largestAway, lowestDual,highestDual); int numberColumns = models[iModel].numberColumns(); double * dualColumnSolution = models[iModel].dualColumnSolution(); double * primalColumnSolution = models[iModel].primalColumnSolution(); double * columnLower = models[iModel].columnLower(); double * columnUpper = models[iModel].columnUpper(); highestPrimal=-COIN_DBL_MAX; lowestPrimal=COIN_DBL_MAX; highestDual=-COIN_DBL_MAX; lowestDual=COIN_DBL_MAX; largestAway=0.0;; numberAtLower=0; numberAtUpper=0; numberBetween=0; for (int iColumn=0;iColumnupper-1.0e-6) { numberAtUpper++; } else { numberBetween++; largestAway=CoinMax(largestAway, CoinMin(primal-lower,upper-primal)); } } printf("For columns %d at lower, %d between, %d at upper - lowest %g, highest %g most away %g - highest dual %g lowest %g\n", numberAtLower,numberBetween,numberAtUpper, lowestPrimal,highestPrimal,largestAway, lowestDual,highestDual); break; } // make fancy later on int iRow; int numberRows = models[iModel].numberRows(); int lengthName = models[iModel].lengthNames(); // 0 if no names int lengthPrint = CoinMax(lengthName, 8); // in general I don't want to pass around massive // amounts of data but seems simpler here std::vector rowNames = *(models[iModel].rowNames()); std::vector columnNames = *(models[iModel].columnNames()); double * dualRowSolution = models[iModel].dualRowSolution(); double * primalRowSolution = models[iModel].primalRowSolution(); double * rowLower = models[iModel].rowLower(); double * rowUpper = models[iModel].rowUpper(); double primalTolerance = models[iModel].primalTolerance(); 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 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 (size_t 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 (size_t i = 0; i <= lengthName - length; i++) { char * maskOut = newMasks[nEntries]; CoinMemcpyN(oldMask, static_cast(nBefore), maskOut); for (size_t k = 0; k < i; k++) maskOut[k+nBefore] = '?'; CoinMemcpyN(ast + 1, static_cast(nAfter), maskOut + nBefore + i); 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) { int numberColumns = models[iModel].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 (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: models[iModel].primalRanging(numberRows, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); break; // objective ranging case 8: models[iModel].dualRanging(number, which, valueIncrease, sequenceIncrease, valueDecrease, sequenceDecrease); break; } for (int i = 0; i < number; i++) { int iWhich = which[i]; fprintf(fp, "%d,", (iWhich 2) { 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 < static_cast(lengthPrint); i++) fprintf(fp, " "); } fprintf(fp, " %15.8g %15.8g\n", primalRowSolution[iRow], dualRowSolution[iRow]); } } } int iColumn; int numberColumns = models[iModel].numberColumns(); double * dualColumnSolution = models[iModel].dualColumnSolution(); double * primalColumnSolution = models[iModel].primalColumnSolution(); double * columnLower = models[iModel].columnLower(); double * columnUpper = models[iModel].columnUpper(); 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; } if (doMask && !maskMatches(maskStarts, masks, columnNames[iColumn])) type = 0; if (type) { 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 < static_cast(lengthPrint); i++) fprintf(fp, " "); } fprintf(fp, " %15.8g %15.8g\n", primalColumnSolution[iColumn], dualColumnSolution[iColumn]); } } 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 { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_SAVESOL: if (goodModels[iModel]) { // 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(models + iModel, fileName); } else { std::cout << "** Current model not valid" << std::endl; } break; case CLP_PARAM_ACTION_ENVIRONMENT: CbcOrClpEnvironmentIndex = 0; 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; } } } } delete [] models; delete [] goodModels; } #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 // By now all memory should be freed #ifdef DMALLOC dmalloc_log_unfreed(); dmalloc_shutdown(); #endif return 0; } 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; } void sortOnOther(int * column, const CoinBigIndex * rowStart, int * order, int * other, int nRow, int nInRow, int where) { if (nRow < 2 || where >= nInRow) return; // do initial sort int kRow; int iRow; for ( kRow = 0; kRow < nRow; kRow++) { iRow = order[kRow]; other[kRow] = column[rowStart[iRow] + where]; } CoinSort_2(other, other + nRow, order); int first = 0; iRow = order[0]; int firstC = column[rowStart[iRow] + where]; kRow = 1; while (kRow < nRow) { int lastC = 9999999;; for (; kRow < nRow + 1; kRow++) { if (kRow < nRow) { iRow = order[kRow]; lastC = column[rowStart[iRow] + where]; } else { lastC = 9999999; } if (lastC > firstC) break; } // sort sortOnOther(column, rowStart, order + first, other, kRow - first, nInRow, where + 1); firstC = lastC; first = kRow; } } 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 (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) numberBinary++; } } } printf("Original problem has %d integers (%d of which binary)\n", numberIntegers,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(); if (model->integerInformation()) { const char * integerInformation = model->integerInformation(); int numberIntegers = 0; int numberBinary = 0; double * obj = new double [numberColumns]; int * which = new int [numberColumns]; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn]) { if (integerInformation[iColumn]) { numberIntegers++; if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1) numberBinary++; } } } if(numberColumns != originalModel->numberColumns()) printf("Presolved problem has %d integers (%d of which binary)\n", numberIntegers,numberBinary); for (int ifInt=0;ifInt<2;ifInt++) { for (int ifAbs=0;ifAbs<2;ifAbs++) { int numberSort=0; int numberZero=0; int numberDifferentObj=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn]) { if (!ifInt||integerInformation[iColumn]) { obj[numberSort]=(ifAbs) ? fabs(objective[iColumn]) : objective[iColumn]; which[numberSort++]=iColumn; if (!objective[iColumn]) numberZero++; } } } 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++; printf("==== "); if (ifInt) printf("for integers "); if (!ifAbs) printf("%d zero objective ",numberZero); else printf("absolute objective values "); printf("%d different\n",numberDifferentObj); bool saveModel=false; int target=model->logLevel(); if (target>10000) { if (ifInt&&!ifAbs) saveModel=true; target-=10000; } if (target<=100) target=12; else target-=100; if (numberDifferentObj1.0e-12) { printf("%d variables have objective of %g\n", jColumn-iLast,last); iLast=jColumn; last=obj[jColumn]; } } printf("%d variables have objective of %g\n", numberSort-iLast,last); if (saveModel) { int spaceNeeded=numberSort+numberDifferentObj; int * columnAdd = new int[spaceNeeded+numberDifferentObj+1]; double * elementAdd = new double[spaceNeeded]; int * rowAdd = new int[2*numberDifferentObj+1]; int * newIsInteger = rowAdd+numberDifferentObj+1; double * objectiveNew = new double[3*numberDifferentObj]; double * lowerNew = objectiveNew+numberDifferentObj; double * upperNew = lowerNew+numberDifferentObj; memset(columnAdd+spaceNeeded,0, (numberDifferentObj+1)*sizeof(int)); ClpSimplex tempModel=*model; int iLast=0; double last=obj[0]; numberDifferentObj=0; int numberElements=0; rowAdd[0]=0; double * objective = tempModel.objective(); 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) { bool allInteger=integerInformation!=NULL; int iColumn=which[iLast]; objectiveNew[numberDifferentObj]=objective[iColumn]; double lower=0.0; double upper=0.0; for (int kColumn=iLast;kColumnproblemName(); if (ifInt) tempName += "_int"; if (ifAbs) tempName += "_abs"; tempName += ".mps"; tempModel.writeMps(tempName.c_str()); } } } } delete [] which; delete [] obj; printf("===== end objective counts\n"); } 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"); //#define SYM #ifndef SYM if (model->logLevel() < 2) return ; #endif 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"); if (model->logLevel() == 63 #ifdef SYM || true #endif ) { // get column copy CoinPackedMatrix columnCopy = *matrix; const int * columnLength = columnCopy.getVectorLengths(); number = new int[numberRows+1]; memset(number, 0, (numberRows + 1)*sizeof(int)); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; number[length]++; } k = 0; for (iRow = 1; iRow <= numberRows; iRow++) { if (number[iRow]) { k++; } } int * row = columnCopy.getMutableIndices(); const CoinBigIndex * columnStart = columnCopy.getVectorStarts(); double * element = columnCopy.getMutableElements(); int * order = new int[numberColumns]; int * other = new int[numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; order[iColumn] = iColumn; other[iColumn] = length; CoinBigIndex start = columnStart[iColumn]; CoinSort_2(row + start, row + start + length, element + start); } CoinSort_2(other, other + numberColumns, order); int jColumn = number[0] + number[1]; for (iRow = 2; iRow <= numberRows; iRow++) { if (number[iRow]) { printf("XX %d columns have %d entries\n", number[iRow], iRow); int kColumn = jColumn + number[iRow]; sortOnOther(row, columnStart, order + jColumn, other, number[iRow], iRow, 0); // Now print etc if (iRow < 500000) { for (int lColumn = jColumn; lColumn < kColumn; lColumn++) { iColumn = order[lColumn]; CoinBigIndex start = columnStart[iColumn]; if (model->logLevel() == 63) { printf("column %d %g <= ", iColumn, columnLower[iColumn]); for (CoinBigIndex i = start; i < start + iRow; i++) printf("( %d, %g) ", row[i], element[i]); printf("<= %g\n", columnUpper[iColumn]); } } } jColumn = kColumn; } } delete [] order; delete [] other; delete [] number; } // get row copy CoinPackedMatrix rowCopy = *matrix; rowCopy.reverseOrdering(); const int * rowLength = rowCopy.getVectorLengths(); number = new int[numberColumns+1]; memset(number, 0, (numberColumns + 1)*sizeof(int)); if (model->logLevel() > 3) { // get column copy CoinPackedMatrix columnCopy = *matrix; const int * columnLength = columnCopy.getVectorLengths(); const int * row = columnCopy.getIndices(); const CoinBigIndex * columnStart = columnCopy.getVectorStarts(); const double * element = columnCopy.getElements(); const double * elementByRow = rowCopy.getElements(); const int * rowStart = rowCopy.getVectorStarts(); const int * column = rowCopy.getIndices(); int nPossibleZeroCost=0; int nPossibleNonzeroCost=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; if (columnLower[iColumn]<-1.0e30&&columnUpper[iColumn]>1.0e30) { if (length==1) { printf("Singleton free %d - cost %g\n",iColumn,objective[iColumn]); } else if (length==2) { int iRow0=row[columnStart[iColumn]]; int iRow1=row[columnStart[iColumn]+1]; double element0=element[columnStart[iColumn]]; double element1=element[columnStart[iColumn]+1]; int n0=rowLength[iRow0]; int n1=rowLength[iRow1]; printf("Doubleton free %d - cost %g - %g in %srow with %d entries and %g in %srow with %d entries\n", iColumn,objective[iColumn],element0,(rowLower[iRow0]==rowUpper[iRow0]) ? "==" : "",n0, element1,(rowLower[iRow1]==rowUpper[iRow1]) ? "==" : "",n1); } } if (length==1) { int iRow=row[columnStart[iColumn]]; double value=COIN_DBL_MAX; for (int i=rowStart[iRow];ilogLevel() > 4) printf("Singleton %d with no objective in row with %d elements - rhs %g,%g\n",iColumn,rowLength[iRow],rowLower[iRow],rowUpper[iRow]); nPossibleZeroCost++; } else if (value!=-COIN_DBL_MAX) { if (model->logLevel() > 4) printf("Singleton %d with objective in row with %d equal elements - rhs %g,%g\n",iColumn,rowLength[iRow],rowLower[iRow],rowUpper[iRow]); nPossibleNonzeroCost++; } } } if (nPossibleZeroCost||nPossibleNonzeroCost) printf("%d singletons with zero cost, %d with valid cost\n", nPossibleZeroCost,nPossibleNonzeroCost); // look for DW int * blockStart = new int [2*(numberRows+numberColumns)+1+numberRows]; int * columnBlock = blockStart+numberRows; int * nextColumn = columnBlock+numberColumns; int * blockCount = nextColumn+numberColumns; int * blockEls = blockCount+numberRows+1; int direction[2]={-1,1}; int bestBreak=-1; double bestValue=0.0; int iPass=0; int halfway=(numberRows+1)/2; int firstMaster=-1; int lastMaster=-2; while (iPass<2) { int increment=direction[iPass]; int start= increment>0 ? 0 : numberRows-1; int stop=increment>0 ? numberRows : -1; int numberBlocks=0; int thisBestBreak=-1; double thisBestValue=COIN_DBL_MAX; int numberRowsDone=0; int numberMarkedColumns=0; int maximumBlockSize=0; for (int i=0;i=0) { // column marked if (iBlock<0) { // put row in that block iBlock=whichColumnBlock; } else if (iBlock!=whichColumnBlock) { // merge blockCount[iBlock]+=blockCount[whichColumnBlock]; blockCount[whichColumnBlock]=0; int jColumn=blockStart[whichColumnBlock]; while (jColumn>=0) { columnBlock[jColumn]=iBlock; iColumn=jColumn; jColumn=nextColumn[jColumn]; } nextColumn[iColumn]=blockStart[iBlock]; blockStart[iBlock]=blockStart[whichColumnBlock]; blockStart[whichColumnBlock]=-1; } } } int n=numberMarkedColumns; if (iBlock<0) { //new block if (rowLength[iRow]) { numberBlocks++; iBlock=numberBlocks; int jColumn=column[rowStart[iRow]]; columnBlock[jColumn]=iBlock; blockStart[iBlock]=jColumn; numberMarkedColumns++; for (CoinBigIndex j=rowStart[iRow]+1;j maximumBlockSize&&numberRowsDone>halfway) { thisBestBreak=iRow; thisBestValue=static_cast(maximumBlockSize)/ static_cast(numberRowsDone); } } if (thisBestBreak==stop) thisBestValue=COIN_DBL_MAX; iPass++; if (iPass==1) { bestBreak=thisBestBreak; bestValue=thisBestValue; } else { if (bestValue=0) { blockCount[iBlock]++; blockEls[iBlock]+=rowLength[iRow]; } else { if (iBlock==-2) numberMaster++; else numberEmpty++; } } int numberEmptyColumns=0; int numberMasterColumns=0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { int iBlock=columnBlock[iColumn]; if (iBlock>=0) { nextColumn[iBlock]++; } else { if (columnLength[iColumn]) numberMasterColumns++; else numberEmptyColumns++; } } int largestRows=0; int largestColumns=0; for (int i=0;ilargestRows+largestColumns) { largestRows=blockCount[i]; largestColumns=nextColumn[i]; } } bool useful=true; if (numberMaster>halfway||largestRows*3>numberRows) useful=false; printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n", useful ? "**Useful" : "NoGood", numberBlocks,largestRows,largestColumns,numberMaster,numberEmpty,numberRows, numberMasterColumns,numberEmptyColumns,numberColumns); for (int i=0;ilogLevel() == 17) { int * whichRows=new int[numberRows+numberColumns]; int * whichColumns=whichRows+numberRows; char name[20]; for (int iBlock=0;iBlock= 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; } } } } if (model->logLevel() == 63 #ifdef SYM || true #endif ) { int * column = rowCopy.getMutableIndices(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); double * element = rowCopy.getMutableElements(); int * order = new int[numberRows]; int * other = new int[numberRows]; for (iRow = 0; iRow < numberRows; iRow++) { int length = rowLength[iRow]; order[iRow] = iRow; other[iRow] = length; CoinBigIndex start = rowStart[iRow]; CoinSort_2(column + start, column + start + length, element + start); } CoinSort_2(other, other + numberRows, order); int jRow = number[0] + number[1]; double * weight = new double[numberRows]; double * randomColumn = new double[numberColumns+1]; double * randomRow = new double [numberRows+1]; int * sortRow = new int [numberRows]; int * possibleRow = new int [numberRows]; int * backRow = new int [numberRows]; int * stackRow = new int [numberRows]; int * sortColumn = new int [numberColumns]; int * possibleColumn = new int [numberColumns]; int * backColumn = new int [numberColumns]; int * backColumn2 = new int [numberColumns]; int * mapRow = new int [numberRows]; int * mapColumn = new int [numberColumns]; int * stackColumn = new int [numberColumns]; double randomLower = CoinDrand48(); double randomUpper = CoinDrand48(); double randomInteger = CoinDrand48(); int * startAdd = new int[numberRows+1]; int * columnAdd = new int [2*numberElements]; double * elementAdd = new double[2*numberElements]; int nAddRows = 0; startAdd[0] = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { randomColumn[iColumn] = CoinDrand48(); backColumn2[iColumn] = -1; } for (iColumn = 2; iColumn <= numberColumns; iColumn++) { if (number[iColumn]) { printf("XX %d rows have %d entries\n", number[iColumn], iColumn); int kRow = jRow + number[iColumn]; sortOnOther(column, rowStart, order + jRow, other, number[iColumn], iColumn, 0); // Now print etc if (iColumn < 500000) { int nLook = 0; for (int lRow = jRow; lRow < kRow; lRow++) { iRow = order[lRow]; CoinBigIndex start = rowStart[iRow]; if (model->logLevel() == 63) { printf("row %d %g <= ", iRow, rowLower[iRow]); for (CoinBigIndex i = start; i < start + iColumn; i++) printf("( %d, %g) ", column[i], element[i]); printf("<= %g\n", rowUpper[iRow]); } int first = column[start]; double sum = 0.0; for (CoinBigIndex i = start; i < start + iColumn; i++) { int jColumn = column[i]; double value = element[i]; jColumn -= first; assert (jColumn >= 0); sum += value * randomColumn[jColumn]; } if (rowLower[iRow] > -1.0e30 && rowLower[iRow]) sum += rowLower[iRow] * randomLower; else if (!rowLower[iRow]) sum += 1.234567e-7 * randomLower; if (rowUpper[iRow] < 1.0e30 && rowUpper[iRow]) sum += rowUpper[iRow] * randomUpper; else if (!rowUpper[iRow]) sum += 1.234567e-7 * randomUpper; sortRow[nLook] = iRow; randomRow[nLook++] = sum; // best way is to number unique elements and bounds and use if (fabs(sum) > 1.0e4) sum *= 1.0e-6; weight[iRow] = sum; } assert (nLook <= numberRows); CoinSort_2(randomRow, randomRow + nLook, sortRow); randomRow[nLook] = COIN_DBL_MAX; double last = -COIN_DBL_MAX; int iLast = -1; for (int iLook = 0; iLook < nLook + 1; iLook++) { if (randomRow[iLook] > last) { if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { //printf("%d rows possible?\n",n); } } iLast = iLook; last = randomRow[iLook]; } } } jRow = kRow; } } CoinPackedMatrix columnCopy = *matrix; const int * columnLength = columnCopy.getVectorLengths(); const int * row = columnCopy.getIndices(); const CoinBigIndex * columnStart = columnCopy.getVectorStarts(); const double * elementByColumn = columnCopy.getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; CoinBigIndex start = columnStart[iColumn]; double sum = objective[iColumn]; if (columnLower[iColumn] > -1.0e30 && columnLower[iColumn]) sum += columnLower[iColumn] * randomLower; else if (!columnLower[iColumn]) sum += 1.234567e-7 * randomLower; if (columnUpper[iColumn] < 1.0e30 && columnUpper[iColumn]) sum += columnUpper[iColumn] * randomUpper; else if (!columnUpper[iColumn]) sum += 1.234567e-7 * randomUpper; if (model->isInteger(iColumn)) sum += 9.87654321e-6 * randomInteger; for (CoinBigIndex i = start; i < start + length; i++) { int iRow = row[i]; sum += elementByColumn[i] * weight[iRow]; } sortColumn[iColumn] = iColumn; randomColumn[iColumn] = sum; } { CoinSort_2(randomColumn, randomColumn + numberColumns, sortColumn); for (iColumn = 0; iColumn < numberColumns; iColumn++) { int i = sortColumn[iColumn]; backColumn[i] = iColumn; } randomColumn[numberColumns] = COIN_DBL_MAX; double last = -COIN_DBL_MAX; int iLast = -1; for (int iLook = 0; iLook < numberColumns + 1; iLook++) { if (randomColumn[iLook] > last) { if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { //printf("%d columns possible?\n",n); } for (int i = iLast; i < iLook; i++) { possibleColumn[sortColumn[i]] = n; } } iLast = iLook; last = randomColumn[iLook]; } } for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex start = rowStart[iRow]; double sum = 0.0; int length = rowLength[iRow]; for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; double value = element[i]; jColumn = backColumn[jColumn]; sum += value * randomColumn[jColumn]; //if (iColumn==23089||iRow==23729) //printf("row %d cola %d colb %d value %g rand %g sum %g\n", // iRow,jColumn,column[i],value,randomColumn[jColumn],sum); } sortRow[iRow] = iRow; randomRow[iRow] = weight[iRow]; randomRow[iRow] = sum; } CoinSort_2(randomRow, randomRow + numberRows, sortRow); for (iRow = 0; iRow < numberRows; iRow++) { int i = sortRow[iRow]; backRow[i] = iRow; } randomRow[numberRows] = COIN_DBL_MAX; last = -COIN_DBL_MAX; iLast = -1; // Do backward indices from order for (iRow = 0; iRow < numberRows; iRow++) { other[order[iRow]] = iRow; } for (int iLook = 0; iLook < numberRows + 1; iLook++) { if (randomRow[iLook] > last) { if (iLast >= 0) { int n = iLook - iLast; if (n > 1) { //printf("%d rows possible?\n",n); // Within group sort as for original "order" for (int i = iLast; i < iLook; i++) { int jRow = sortRow[i]; order[i] = other[jRow]; } CoinSort_2(order + iLast, order + iLook, sortRow + iLast); } for (int i = iLast; i < iLook; i++) { possibleRow[sortRow[i]] = n; } } iLast = iLook; last = randomRow[iLook]; } } // Temp out for (int iLook = 0; iLook < numberRows - 1000000; iLook++) { iRow = sortRow[iLook]; CoinBigIndex start = rowStart[iRow]; int length = rowLength[iRow]; int numberPossible = possibleRow[iRow]; for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; if (possibleColumn[jColumn] != numberPossible) numberPossible = -1; } int n = numberPossible; if (numberPossible > 1) { //printf("pppppossible %d\n",numberPossible); for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) { int jRow = sortRow[jLook]; CoinBigIndex start2 = rowStart[jRow]; assert (numberPossible == possibleRow[jRow]); assert(length == rowLength[jRow]); for (CoinBigIndex i = start2; i < start2 + length; i++) { int jColumn = column[i]; if (possibleColumn[jColumn] != numberPossible) numberPossible = -1; } } if (numberPossible < 2) { // switch off for (int jLook = iLook; jLook < iLook + n; jLook++) possibleRow[sortRow[jLook]] = -1; } // skip rest iLook += n - 1; } else { possibleRow[iRow] = -1; } } for (int iLook = 0; iLook < numberRows; iLook++) { iRow = sortRow[iLook]; int numberPossible = possibleRow[iRow]; // Only if any integers int numberIntegers = 0; CoinBigIndex start = rowStart[iRow]; int length = rowLength[iRow]; for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; if (model->isInteger(jColumn)) numberIntegers++; } if (numberPossible > 1 && !numberIntegers) { //printf("possible %d - but no integers\n",numberPossible); } if (numberPossible > 1 && (numberIntegers || false)) { // printf("possible %d - %d integers\n", numberPossible, numberIntegers); int lastLook = iLook; int nMapRow = -1; for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) { // stop if too many failures if (jLook > iLook + 10 && nMapRow < 0) break; // Create identity mapping int i; for (i = 0; i < numberRows; i++) mapRow[i] = i; for (i = 0; i < numberColumns; i++) mapColumn[i] = i; int offset = jLook - iLook; int nStackC = 0; // build up row and column mapping int nStackR = 1; stackRow[0] = iLook; bool good = true; while (nStackR) { nStackR--; int look1 = stackRow[nStackR]; int look2 = look1 + offset; assert (randomRow[look1] == randomRow[look2]); int row1 = sortRow[look1]; int row2 = sortRow[look2]; assert (mapRow[row1] == row1); assert (mapRow[row2] == row2); mapRow[row1] = row2; mapRow[row2] = row1; CoinBigIndex start1 = rowStart[row1]; CoinBigIndex offset2 = rowStart[row2] - start1; int length = rowLength[row1]; assert( length == rowLength[row2]); for (CoinBigIndex i = start1; i < start1 + length; i++) { int jColumn1 = column[i]; int jColumn2 = column[i+offset2]; if (randomColumn[backColumn[jColumn1]] != randomColumn[backColumn[jColumn2]]) { good = false; break; } if (mapColumn[jColumn1] == jColumn1) { // not touched assert (mapColumn[jColumn2] == jColumn2); if (jColumn1 != jColumn2) { // Put on stack mapColumn[jColumn1] = jColumn2; mapColumn[jColumn2] = jColumn1; stackColumn[nStackC++] = jColumn1; } } else { if (mapColumn[jColumn1] != jColumn2 || mapColumn[jColumn2] != jColumn1) { // bad good = false; printf("bad col\n"); break; } } } if (!good) break; while (nStackC) { nStackC--; int iColumn = stackColumn[nStackC]; int iColumn2 = mapColumn[iColumn]; assert (iColumn != iColumn2); int length = columnLength[iColumn]; assert (length == columnLength[iColumn2]); CoinBigIndex start = columnStart[iColumn]; CoinBigIndex offset2 = columnStart[iColumn2] - start; for (CoinBigIndex i = start; i < start + length; i++) { int iRow = row[i]; int iRow2 = row[i+offset2]; if (mapRow[iRow] == iRow) { // First (but be careful) if (iRow != iRow2) { //mapRow[iRow]=iRow2; //mapRow[iRow2]=iRow; int iBack = backRow[iRow]; int iBack2 = backRow[iRow2]; if (randomRow[iBack] == randomRow[iBack2] && iBack2 - iBack == offset) { stackRow[nStackR++] = iBack; } else { //printf("randomRow diff - weights %g %g\n", // weight[iRow],weight[iRow2]); // bad good = false; break; } } } else { if (mapRow[iRow] != iRow2 || mapRow[iRow2] != iRow) { // bad good = false; printf("bad row\n"); break; } } } if (!good) break; } } // then check OK if (good) { for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex start = rowStart[iRow]; int length = rowLength[iRow]; if (mapRow[iRow] == iRow) { for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; backColumn2[jColumn] = i - start; } for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; if (mapColumn[jColumn] != jColumn) { int jColumn2 = mapColumn[jColumn]; CoinBigIndex i2 = backColumn2[jColumn2]; if (i2 < 0) { good = false; } else if (element[i] != element[i2+start]) { good = false; } } } for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; backColumn2[jColumn] = -1; } } else { int row2 = mapRow[iRow]; assert (iRow = mapRow[row2]); if (rowLower[iRow] != rowLower[row2] || rowLower[row2] != rowLower[iRow]) good = false; CoinBigIndex offset2 = rowStart[row2] - start; for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; double value = element[i]; int jColumn2 = column[i+offset2]; double value2 = element[i+offset2]; if (value != value2 || mapColumn[jColumn] != jColumn2 || mapColumn[jColumn2] != jColumn) good = false; } } } if (good) { // check rim for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (mapColumn[iColumn] != iColumn) { int iColumn2 = mapColumn[iColumn]; if (objective[iColumn] != objective[iColumn2]) good = false; if (columnLower[iColumn] != columnLower[iColumn2]) good = false; if (columnUpper[iColumn] != columnUpper[iColumn2]) good = false; if (model->isInteger(iColumn) != model->isInteger(iColumn2)) good = false; } } } if (good) { // temp if (nMapRow < 0) { //const double * solution = model->primalColumnSolution(); // find mapped int nMapColumn = 0; for (int i = 0; i < numberColumns; i++) { if (mapColumn[i] > i) nMapColumn++; } nMapRow = 0; int kRow = -1; for (int i = 0; i < numberRows; i++) { if (mapRow[i] > i) { nMapRow++; kRow = i; } } printf("%d columns, %d rows\n", nMapColumn, nMapRow); if (nMapRow == 1) { CoinBigIndex start = rowStart[kRow]; int length = rowLength[kRow]; printf("%g <= ", rowLower[kRow]); for (CoinBigIndex i = start; i < start + length; i++) { int jColumn = column[i]; if (mapColumn[jColumn] != jColumn) printf("* "); printf("%d,%g ", jColumn, element[i]); } printf("<= %g\n", rowUpper[kRow]); } } // temp int row1 = sortRow[lastLook]; int row2 = sortRow[jLook]; lastLook = jLook; CoinBigIndex start1 = rowStart[row1]; CoinBigIndex offset2 = rowStart[row2] - start1; int length = rowLength[row1]; assert( length == rowLength[row2]); CoinBigIndex put = startAdd[nAddRows]; double multiplier = length < 11 ? 2.0 : 1.125; double value = 1.0; for (CoinBigIndex i = start1; i < start1 + length; i++) { int jColumn1 = column[i]; int jColumn2 = column[i+offset2]; columnAdd[put] = jColumn1; elementAdd[put++] = value; columnAdd[put] = jColumn2; elementAdd[put++] = -value; value *= multiplier; } nAddRows++; startAdd[nAddRows] = put; } else { printf("ouch - did not check out as good\n"); } } } // skip rest iLook += numberPossible - 1; } } } if (nAddRows) { double * lower = new double [nAddRows]; double * upper = new double[nAddRows]; int i; //const double * solution = model->primalColumnSolution(); for (i = 0; i < nAddRows; i++) { lower[i] = 0.0; upper[i] = COIN_DBL_MAX; } printf("Adding %d rows with %d elements\n", nAddRows, startAdd[nAddRows]); //ClpSimplex newModel(*model); //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd); //newModel.writeMps("modified.mps"); delete [] lower; delete [] upper; } delete [] startAdd; delete [] columnAdd; delete [] elementAdd; delete [] order; delete [] other; delete [] randomColumn; delete [] weight; delete [] randomRow; delete [] sortRow; delete [] backRow; delete [] possibleRow; delete [] sortColumn; delete [] backColumn; delete [] backColumn2; delete [] possibleColumn; delete [] mapRow; delete [] mapColumn; delete [] stackRow; delete [] stackColumn; } 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 (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(const char * fileName, int type) { FILE * fp = fopen(fileName, "r"); assert (fp); int numberLines = 0; #define MAXLINES 500 #define MAXONELINE 200 char line[MAXLINES][MAXONELINE]; while (fgets(line[numberLines], MAXONELINE, fp)) { assert (numberLines < MAXLINES); clean(line[numberLines]); numberLines++; } fclose(fp); // add in actual solve strcpy(line[numberLines], "5 clpModel->initialSolve(clpSolve);"); numberLines++; fp = fopen(fileName, "w"); assert (fp); char apo = '"'; char backslash = '\\'; fprintf(fp, "#include %cClpSimplex.hpp%c\n", apo, apo); fprintf(fp, "#include %cClpSolve.hpp%c\n", apo, apo); fprintf(fp, "\nint main (int argc, const char *argv[])\n{\n"); fprintf(fp, " ClpSimplex model;\n"); fprintf(fp, " int status=1;\n"); fprintf(fp, " if (argc<2)\n"); fprintf(fp, " fprintf(stderr,%cPlease give file name%cn%c);\n", apo, backslash, apo); fprintf(fp, " else\n"); fprintf(fp, " status=model.readMps(argv[1],true);\n"); fprintf(fp, " if (status) {\n"); fprintf(fp, " fprintf(stderr,%cBad readMps %%s%cn%c,argv[1]);\n", apo, backslash, apo); fprintf(fp, " exit(1);\n"); fprintf(fp, " }\n\n"); fprintf(fp, " // Now do requested saves and modifications\n"); fprintf(fp, " ClpSimplex * clpModel = & model;\n"); int wanted[9]; memset(wanted, 0, sizeof(wanted)); wanted[0] = wanted[3] = wanted[5] = wanted[8] = 1; if (type > 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", "Add to model" }; 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) fprintf(fp, "\n // %s\n\n", header[iType].c_str()); n++; fprintf(fp, "%s\n", line[iLine] + 1); } } } fprintf(fp, "\n // Now you would use solution etc etc\n\n"); fprintf(fp, " return 0;\n}\n"); fclose(fp); printf("C++ file written to %s\n", fileName); } /* Version 1.00.00 October 13 2004. 1.00.01 October 18. Added basis handling helped/prodded by Thorsten Koch. Also modifications to make faster with sbb (I hope I haven't broken anything). 1.00.02 March 21 2005. Redid ClpNonLinearCost to save memory also redid createRim to try and improve cache characteristics. 1.00.03 April 8 2005. Added Volume algorithm as crash and made code more robust on testing. Also added "either" and "tune" algorithm. 1.01.01 April 12 2005. Decided to go to different numbering. Backups will be last 2 digits while middle 2 are for improvements. Still take a long time to get to 2.00.01 1.01.02 May 4 2005. Will be putting in many changes - so saving stable version 1.02.01 May 6 2005. Lots of changes to try and make faster and more stable in branch and cut. 1.02.02 May 19 2005. Stuff for strong branching and some improvements to simplex 1.03.01 May 24 2006. Lots done but I can't remember what! 1.03.03 June 13 2006. For clean up after dual perturbation 1.04.01 June 26 2007. Lots of changes but I got lazy 1.05.00 June 27 2007. This is trunk so when gets to stable will be 1.5 1.11.00 November 5 2009 (Guy Fawkes) - OSL factorization and better ordering */ #ifdef CILK_TEST // -*- C++ -*- /* * cilk-for.cilk * * Copyright (c) 2007-2008 Cilk Arts, Inc. 55 Cambridge Street, * Burlington, MA 01803. Patents pending. All rights reserved. You may * freely use the sample code to guide development of your own works, * provided that you reproduce this notice in any works you make that * use the sample code. This sample code is provided "AS IS" without * warranty of any kind, either express or implied, including but not * limited to any implied warranty of non-infringement, merchantability * or fitness for a particular purpose. In no event shall Cilk Arts, * Inc. be liable for any direct, indirect, special, or consequential * damages, or any other damages whatsoever, for any use of or reliance * on this sample code, including, without limitation, any lost * opportunity, lost profits, business interruption, loss of programs or * data, even if expressly advised of or otherwise aware of the * possibility of such damages, whether in an action of contract, * negligence, tort, or otherwise. * * This file demonstrates a Cilk++ for loop */ #include //#include #include #include #include // cilk_for granularity. #define CILK_FOR_GRAINSIZE 128 double dowork(double i) { // Waste time: int j; double k = i; for (j = 0; j < 50000; ++j) { k += k / ((j + 1) * (k + 1)); } return k; } static void doSomeWork(double * a,int low, int high) { if (high-low>300) { int mid=(high+low)>>1; cilk_spawn doSomeWork(a,low,mid); doSomeWork(a,mid,high); cilk_sync; } else { for(int i = low; i < high; ++i) { a[i] = dowork(a[i]); } } } void cilkTest() { unsigned int n = 10000; //cilk::cilkview cv; double* a = new double[n]; for(unsigned int i = 0; i < n; i++) { // Populate A a[i] = (double) ((i * i) % 1024 + 512) / 512; } std::cout << "Iterating over " << n << " integers" << std::endl; //cv.start(); #if 1 //#pragma cilk_grainsize=CILK_FOR_GRAINSIZE cilk_for(unsigned int i = 0; i < n; ++i) { a[i] = dowork(a[i]); } #else doSomeWork(a,0,n); #endif int * which =new int[n]; unsigned int n2=n>>1; for (int i=0;i maximumIndex(-1,0.0); cilk_for(unsigned int i = 0; i < n2; ++i) { int iWhich=which[i]; maximumIndex.calc_max(iWhich,a[iWhich]); } int bestIndex=maximumIndex.get_index(); int bestIndex2=-1; double largest=0.0; cilk_for(unsigned int i = 0; i < n2; ++i) { int iWhich=which[i]; if (a[iWhich]>largest) { bestIndex2=iWhich; largest=a[iWhich]; } } assert (bestIndex==bestIndex2); //cv.stop(); //cv.dump("cilk-for-results", false); //std::cout << cv.accumulated_milliseconds() / 1000.f << " seconds" << std::endl; exit(0); } #endif Clp-1.15.10/src/AbcPrimalColumnDantzig.hpp0000644000076600007660000000371512101105055016700 0ustar coincoin/* $Id: AbcPrimalColumnDantzig.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcPrimalColumnDantzig_H #define AbcPrimalColumnDantzig_H #include "AbcPrimalColumnPivot.hpp" //############################################################################# /** Primal Column Pivot Dantzig Algorithm Class This is simplest choice - choose largest infeasibility */ class AbcPrimalColumnDantzig : public AbcPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none. Lumbers over all columns - slow The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row Can just do full price if you really want to be slow */ virtual int pivotColumn(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1); /// Just sets model virtual void saveWeights(AbcSimplex * model, int) { model_ = model; } //@} ///@name Constructors and destructors //@{ /// Default Constructor AbcPrimalColumnDantzig(); /// Copy constructor AbcPrimalColumnDantzig(const AbcPrimalColumnDantzig &); /// Assignment operator AbcPrimalColumnDantzig & operator=(const AbcPrimalColumnDantzig& rhs); /// Destructor virtual ~AbcPrimalColumnDantzig (); /// Clone virtual AbcPrimalColumnPivot * clone(bool copyData = true) const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data //@} }; #endif Clp-1.15.10/src/CoinAbcFactorization1.cpp0000644000076600007660000000101712101105055016447 0ustar coincoin/* $Id: CoinAbcFactorization1.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization1.cpp" #endif Clp-1.15.10/src/ClpNetworkBasis.cpp0000644000076600007660000012412411571121105015416 0ustar coincoin/* $Id: ClpNetworkBasis.cpp 1732 2011-05-31 08:09:41Z forrest $ */ // 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). #include "CoinPragma.hpp" #include "ClpNetworkBasis.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpMatrixBase.hpp" #include "CoinIndexedVector.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNetworkBasis::ClpNetworkBasis () { #ifndef COIN_FAST_CODE slackValue_ = -1.0; #endif numberRows_ = 0; numberColumns_ = 0; parent_ = NULL; descendant_ = NULL; pivot_ = NULL; rightSibling_ = NULL; leftSibling_ = NULL; sign_ = NULL; stack_ = NULL; permute_ = NULL; permuteBack_ = NULL; stack2_ = NULL; depth_ = NULL; mark_ = NULL; model_ = NULL; } // Constructor from CoinFactorization ClpNetworkBasis::ClpNetworkBasis(const ClpSimplex * model, int numberRows, const CoinFactorizationDouble * pivotRegion, const int * permuteBack, const CoinBigIndex * startColumn, const int * numberInColumn, const int * indexRow, const CoinFactorizationDouble * /*element*/) { #ifndef COIN_FAST_CODE slackValue_ = -1.0; #endif numberRows_ = numberRows; numberColumns_ = numberRows; parent_ = new int [ numberRows_+1]; descendant_ = new int [ numberRows_+1]; pivot_ = new int [ numberRows_+1]; rightSibling_ = new int [ numberRows_+1]; leftSibling_ = new int [ numberRows_+1]; sign_ = new double [ numberRows_+1]; stack_ = new int [ numberRows_+1]; stack2_ = new int[numberRows_+1]; depth_ = new int[numberRows_+1]; mark_ = new char[numberRows_+1]; permute_ = new int [numberRows_ + 1]; permuteBack_ = new int [numberRows_ + 1]; int i; for (i = 0; i < numberRows_ + 1; i++) { parent_[i] = -1; descendant_[i] = -1; pivot_[i] = -1; rightSibling_[i] = -1; leftSibling_[i] = -1; sign_[i] = -1.0; stack_[i] = -1; permute_[i] = i; permuteBack_[i] = i; stack2_[i] = -1; depth_[i] = -1; mark_[i] = 0; } mark_[numberRows_] = 1; // pivotColumnBack gives order of pivoting into basis // so pivotColumnback[0] is first slack in basis and // it pivots on row permuteBack[0] // a known root is given by permuteBack[numberRows_-1] for (i = 0; i < numberRows_; i++) { int iPivot = permuteBack[i]; double sign; if (pivotRegion[i] > 0.0) sign = 1.0; else sign = -1.0; int other; if (numberInColumn[i] > 0) { int iRow = indexRow[startColumn[i]]; other = permuteBack[iRow]; //assert (parent_[other]!=-1); } else { other = numberRows_; } sign_[iPivot] = sign; int iParent = other; parent_[iPivot] = other; if (descendant_[iParent] >= 0) { // we have a sibling int iRight = descendant_[iParent]; rightSibling_[iPivot] = iRight; leftSibling_[iRight] = iPivot; } else { rightSibling_[iPivot] = -1; } descendant_[iParent] = iPivot; leftSibling_[iPivot] = -1; } // do depth int nStack = 1; stack_[0] = descendant_[numberRows_]; depth_[numberRows_] = -1; // root while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { depth_[iNext] = nStack; int iRight = rightSibling_[iNext]; stack_[nStack++] = iRight; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } model_ = model; check(); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNetworkBasis::ClpNetworkBasis (const ClpNetworkBasis & rhs) { #ifndef COIN_FAST_CODE slackValue_ = rhs.slackValue_; #endif numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; if (rhs.parent_) { parent_ = new int [numberRows_+1]; CoinMemcpyN(rhs.parent_, (numberRows_ + 1), parent_); } else { parent_ = NULL; } if (rhs.descendant_) { descendant_ = new int [numberRows_+1]; CoinMemcpyN(rhs.descendant_, (numberRows_ + 1), descendant_); } else { descendant_ = NULL; } if (rhs.pivot_) { pivot_ = new int [numberRows_+1]; CoinMemcpyN(rhs.pivot_, (numberRows_ + 1), pivot_); } else { pivot_ = NULL; } if (rhs.rightSibling_) { rightSibling_ = new int [numberRows_+1]; CoinMemcpyN(rhs.rightSibling_, (numberRows_ + 1), rightSibling_); } else { rightSibling_ = NULL; } if (rhs.leftSibling_) { leftSibling_ = new int [numberRows_+1]; CoinMemcpyN(rhs.leftSibling_, (numberRows_ + 1), leftSibling_); } else { leftSibling_ = NULL; } if (rhs.sign_) { sign_ = new double [numberRows_+1]; CoinMemcpyN(rhs.sign_, (numberRows_ + 1), sign_); } else { sign_ = NULL; } if (rhs.stack_) { stack_ = new int [numberRows_+1]; CoinMemcpyN(rhs.stack_, (numberRows_ + 1), stack_); } else { stack_ = NULL; } if (rhs.permute_) { permute_ = new int [numberRows_+1]; CoinMemcpyN(rhs.permute_, (numberRows_ + 1), permute_); } else { permute_ = NULL; } if (rhs.permuteBack_) { permuteBack_ = new int [numberRows_+1]; CoinMemcpyN(rhs.permuteBack_, (numberRows_ + 1), permuteBack_); } else { permuteBack_ = NULL; } if (rhs.stack2_) { stack2_ = new int [numberRows_+1]; CoinMemcpyN(rhs.stack2_, (numberRows_ + 1), stack2_); } else { stack2_ = NULL; } if (rhs.depth_) { depth_ = new int [numberRows_+1]; CoinMemcpyN(rhs.depth_, (numberRows_ + 1), depth_); } else { depth_ = NULL; } if (rhs.mark_) { mark_ = new char [numberRows_+1]; CoinMemcpyN(rhs.mark_, (numberRows_ + 1), mark_); } else { mark_ = NULL; } model_ = rhs.model_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNetworkBasis::~ClpNetworkBasis () { delete [] parent_; delete [] descendant_; delete [] pivot_; delete [] rightSibling_; delete [] leftSibling_; delete [] sign_; delete [] stack_; delete [] permute_; delete [] permuteBack_; delete [] stack2_; delete [] depth_; delete [] mark_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNetworkBasis & ClpNetworkBasis::operator=(const ClpNetworkBasis& rhs) { if (this != &rhs) { delete [] parent_; delete [] descendant_; delete [] pivot_; delete [] rightSibling_; delete [] leftSibling_; delete [] sign_; delete [] stack_; delete [] permute_; delete [] permuteBack_; delete [] stack2_; delete [] depth_; delete [] mark_; #ifndef COIN_FAST_CODE slackValue_ = rhs.slackValue_; #endif numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; if (rhs.parent_) { parent_ = new int [numberRows_+1]; CoinMemcpyN(rhs.parent_, (numberRows_ + 1), parent_); } else { parent_ = NULL; } if (rhs.descendant_) { descendant_ = new int [numberRows_+1]; CoinMemcpyN(rhs.descendant_, (numberRows_ + 1), descendant_); } else { descendant_ = NULL; } if (rhs.pivot_) { pivot_ = new int [numberRows_+1]; CoinMemcpyN(rhs.pivot_, (numberRows_ + 1), pivot_); } else { pivot_ = NULL; } if (rhs.rightSibling_) { rightSibling_ = new int [numberRows_+1]; CoinMemcpyN(rhs.rightSibling_, (numberRows_ + 1), rightSibling_); } else { rightSibling_ = NULL; } if (rhs.leftSibling_) { leftSibling_ = new int [numberRows_+1]; CoinMemcpyN(rhs.leftSibling_, (numberRows_ + 1), leftSibling_); } else { leftSibling_ = NULL; } if (rhs.sign_) { sign_ = new double [numberRows_+1]; CoinMemcpyN(rhs.sign_, (numberRows_ + 1), sign_); } else { sign_ = NULL; } if (rhs.stack_) { stack_ = new int [numberRows_+1]; CoinMemcpyN(rhs.stack_, (numberRows_ + 1), stack_); } else { stack_ = NULL; } if (rhs.permute_) { permute_ = new int [numberRows_+1]; CoinMemcpyN(rhs.permute_, (numberRows_ + 1), permute_); } else { permute_ = NULL; } if (rhs.permuteBack_) { permuteBack_ = new int [numberRows_+1]; CoinMemcpyN(rhs.permuteBack_, (numberRows_ + 1), permuteBack_); } else { permuteBack_ = NULL; } if (rhs.stack2_) { stack2_ = new int [numberRows_+1]; CoinMemcpyN(rhs.stack2_, (numberRows_ + 1), stack2_); } else { stack2_ = NULL; } if (rhs.depth_) { depth_ = new int [numberRows_+1]; CoinMemcpyN(rhs.depth_, (numberRows_ + 1), depth_); } else { depth_ = NULL; } if (rhs.mark_) { mark_ = new char [numberRows_+1]; CoinMemcpyN(rhs.mark_, (numberRows_ + 1), mark_); } else { mark_ = NULL; } } return *this; } // checks looks okay void ClpNetworkBasis::check() { // check depth int nStack = 1; stack_[0] = descendant_[numberRows_]; depth_[numberRows_] = -1; // root while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { //assert (depth_[iNext]==nStack); depth_[iNext] = nStack; int iRight = rightSibling_[iNext]; stack_[nStack++] = iRight; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } } // prints void ClpNetworkBasis::print() { int i; printf(" parent descendant left right sign depth\n"); for (i = 0; i < numberRows_ + 1; i++) printf("%4d %7d %8d %7d %7d %5g %7d\n", i, parent_[i], descendant_[i], leftSibling_[i], rightSibling_[i], sign_[i], depth_[i]); } /* Replaces one Column to basis, returns 0=OK */ int ClpNetworkBasis::replaceColumn ( CoinIndexedVector * regionSparse, int pivotRow) { // When things have settled down then redo this to make more elegant // I am sure lots of loops can be combined // regionSparse is empty assert (!regionSparse->getNumElements()); model_->unpack(regionSparse, model_->sequenceIn()); // arc given by pivotRow is leaving basis //int kParent = parent_[pivotRow]; // arc coming in has these two nodes int * indices = regionSparse->getIndices(); int iRow0 = indices[0]; int iRow1; if (regionSparse->getNumElements() == 2) iRow1 = indices[1]; else iRow1 = numberRows_; double sign = -regionSparse->denseVector()[iRow0]; regionSparse->clear(); // and outgoing model_->unpack(regionSparse, model_->pivotVariable()[pivotRow]); int jRow0 = indices[0]; int jRow1; if (regionSparse->getNumElements() == 2) jRow1 = indices[1]; else jRow1 = numberRows_; regionSparse->clear(); // get correct pivotRow //#define FULL_DEBUG #ifdef FULL_DEBUG printf ("irow %d %d, jrow %d %d\n", iRow0, iRow1, jRow0, jRow1); #endif if (parent_[jRow0] == jRow1) { int newPivot = jRow0; if (newPivot != pivotRow) { #ifdef FULL_DEBUG printf("pivot row of %d permuted to %d\n", pivotRow, newPivot); #endif pivotRow = newPivot; } } else { //assert (parent_[jRow1]==jRow0); int newPivot = jRow1; if (newPivot != pivotRow) { #ifdef FULL_DEBUG printf("pivot row of %d permuted to %d\n", pivotRow, newPivot); #endif pivotRow = newPivot; } } bool extraPrint = (model_->numberIterations() > -3) && (model_->logLevel() > 10); if (extraPrint) print(); #ifdef FULL_DEBUG printf("In %d (region= %g, stored %g) %d (%g) pivoting on %d (%g)\n", iRow1, sign, sign_[iRow1], iRow0, sign_[iRow0] , pivotRow, sign_[pivotRow]); #endif // see which path outgoing pivot is on int kRow = -1; int jRow = iRow1; while (jRow != numberRows_) { if (jRow == pivotRow) { kRow = iRow1; break; } else { jRow = parent_[jRow]; } } if (kRow < 0) { jRow = iRow0; while (jRow != numberRows_) { if (jRow == pivotRow) { kRow = iRow0; break; } else { jRow = parent_[jRow]; } } } //assert (kRow>=0); if (iRow0 == kRow) { iRow0 = iRow1; iRow1 = kRow; sign = -sign; } // pivot row is on path from iRow1 back to root // get stack of nodes to change // Also get precursors for cleaning order int nStack = 1; stack_[0] = iRow0; while (kRow != pivotRow) { stack_[nStack++] = kRow; if (sign * sign_[kRow] < 0.0) { sign_[kRow] = -sign_[kRow]; } else { sign = -sign; } kRow = parent_[kRow]; //sign *= sign_[kRow]; } stack_[nStack++] = pivotRow; if (sign * sign_[pivotRow] < 0.0) { sign_[pivotRow] = -sign_[pivotRow]; } else { sign = -sign; } int iParent = parent_[pivotRow]; while (nStack > 1) { int iLeft; int iRight; kRow = stack_[--nStack]; int newParent = stack_[nStack-1]; #ifdef FULL_DEBUG printf("row %d, old parent %d, new parent %d, pivotrow %d\n", kRow, iParent, newParent, pivotRow); #endif int i1 = permuteBack_[pivotRow]; int i2 = permuteBack_[kRow]; permuteBack_[pivotRow] = i2; permuteBack_[kRow] = i1; // do Btran permutation permute_[i1] = kRow; permute_[i2] = pivotRow; pivotRow = kRow; // Take out of old parent iLeft = leftSibling_[kRow]; iRight = rightSibling_[kRow]; if (iLeft < 0) { // take out of tree if (iRight >= 0) { leftSibling_[iRight] = iLeft; descendant_[iParent] = iRight; } else { #ifdef FULL_DEBUG printf("Saying %d (old parent of %d) has no descendants\n", iParent, kRow); #endif descendant_[iParent] = -1; } } else { // take out of tree rightSibling_[iLeft] = iRight; if (iRight >= 0) leftSibling_[iRight] = iLeft; } leftSibling_[kRow] = -1; rightSibling_[kRow] = -1; // now insert new one // make this descendant of that if (descendant_[newParent] >= 0) { // we will have a sibling int jRight = descendant_[newParent]; rightSibling_[kRow] = jRight; leftSibling_[jRight] = kRow; } else { rightSibling_[kRow] = -1; } descendant_[newParent] = kRow; leftSibling_[kRow] = -1; parent_[kRow] = newParent; iParent = kRow; } // now redo all depths from stack_[1] // This must be possible to combine - but later { int iPivot = stack_[1]; int iDepth = depth_[parent_[iPivot]]; //depth of parent iDepth ++; //correct for this one int nStack = 1; stack_[0] = iPivot; while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { // add stack level depth_[iNext] = nStack + iDepth; stack_[nStack++] = rightSibling_[iNext]; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } } if (extraPrint) print(); //check(); return 0; } /* Updates one column (FTRAN) from region2 */ double ClpNetworkBasis::updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, int pivotRow) { regionSparse->clear ( ); double *region = regionSparse->denseVector ( ); double *region2 = regionSparse2->denseVector ( ); int *regionIndex2 = regionSparse2->getIndices ( ); int numberNonZero = regionSparse2->getNumElements ( ); int *regionIndex = regionSparse->getIndices ( ); int i; bool doTwo = (numberNonZero == 2); int i0 = -1; int i1 = -1; if (doTwo) { i0 = regionIndex2[0]; i1 = regionIndex2[1]; } double returnValue = 0.0; bool packed = regionSparse2->packedMode(); if (packed) { if (doTwo && region2[0]*region2[1] < 0.0) { region[i0] = region2[0]; region2[0] = 0.0; region[i1] = region2[1]; region2[1] = 0.0; int iDepth0 = depth_[i0]; int iDepth1 = depth_[i1]; if (iDepth1 > iDepth0) { int temp = i0; i0 = i1; i1 = temp; temp = iDepth0; iDepth0 = iDepth1; iDepth1 = temp; } numberNonZero = 0; if (pivotRow < 0) { while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; region2[numberNonZero] = pivotValue * sign_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; region2[numberNonZero] = pivotValue * sign_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; region2[numberNonZero] = pivotValue1 * sign_[i1]; regionIndex2[numberNonZero++] = iBack1; int otherRow1 = parent_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } else { while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; double value = pivotValue * sign_[i0]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; double value = pivotValue * sign_[i0]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; value = pivotValue1 * sign_[i1]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack1; if (iBack1 == pivotRow) returnValue = value; int otherRow1 = parent_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } } else { // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero; i++) { int j = regionIndex2[i]; double value = region2[i]; region2[i] = 0.0; region[j] = value; regionIndex[i] = j; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } numberNonZero = 0; if (pivotRow < 0) { for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; region2[numberNonZero] = pivotValue * sign_[iPivot]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } else { for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; double value = pivotValue * sign_[iPivot]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } } } else { if (doTwo && region2[i0]*region2[i1] < 0.0) { // If just +- 1 then could go backwards on depth until join region[i0] = region2[i0]; region2[i0] = 0.0; region[i1] = region2[i1]; region2[i1] = 0.0; int iDepth0 = depth_[i0]; int iDepth1 = depth_[i1]; if (iDepth1 > iDepth0) { int temp = i0; i0 = i1; i1 = temp; temp = iDepth0; iDepth0 = iDepth1; iDepth1 = temp; } numberNonZero = 0; while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region2[iBack] = pivotValue * sign_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region2[iBack] = pivotValue * sign_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; regionIndex2[numberNonZero++] = iBack1; int otherRow1 = parent_[i1]; region2[iBack1] = pivotValue1 * sign_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } else { // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero; i++) { int j = regionIndex2[i]; double value = region2[j]; region2[j] = 0.0; region[j] = value; regionIndex[i] = j; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } numberNonZero = 0; for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[iPivot]; region2[iBack] = pivotValue * sign_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } if (pivotRow >= 0) returnValue = region2[pivotRow]; } region[numberRows_] = 0.0; regionSparse2->setNumElements(numberNonZero); #ifdef FULL_DEBUG { int i; for (i = 0; i < numberRows_; i++) { assert(!mark_[i]); assert (stack2_[i] == -1); } } #endif return returnValue; } /* Updates one column (FTRAN) to/from array ** For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. rhs) */ int ClpNetworkBasis::updateColumn ( CoinIndexedVector * regionSparse, double region2[] ) const { regionSparse->clear ( ); double *region = regionSparse->denseVector ( ); int numberNonZero = 0; int *regionIndex = regionSparse->getIndices ( ); int i; // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; for (i = 0; i < numberRows_; i++) { double value = region2[i]; if (value) { region2[i] = 0.0; region[i] = value; regionIndex[numberNonZero++] = i; int j = i; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } } numberNonZero = 0; for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; numberNonZero++; int otherRow = parent_[iPivot]; region2[iBack] = pivotValue * sign_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } region[numberRows_] = 0.0; return numberNonZero; } /* Updates one column transpose (BTRAN) For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. dense objective) returns number of nonzeros */ int ClpNetworkBasis::updateColumnTranspose ( CoinIndexedVector * regionSparse, double region2[] ) const { // permute in after copying // so will end up in right place double *region = regionSparse->denseVector ( ); int *regionIndex = regionSparse->getIndices ( ); int i; int numberNonZero = 0; CoinMemcpyN(region2, numberRows_, region); for (i = 0; i < numberRows_; i++) { double value = region[i]; if (value) { int k = permute_[i]; region[i] = 0.0; region2[k] = value; regionIndex[numberNonZero++] = k; mark_[k] = 1; } } // copy back // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; for (i = 0; i < numberNonZero; i++) { int j = regionIndex[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth) ; greatestDepth = CoinMax(iDepth, greatestDepth) ; int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero = 0; region2[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region2[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region2[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region2[iPivot] = pivotValue; if (pivotValue) numberNonZero++; iPivot = stack_[iPivot]; } } return numberNonZero; } /* Updates one column (BTRAN) from region2 */ int ClpNetworkBasis::updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const { // permute in - presume small number so copy back // so will end up in right place regionSparse->clear ( ); double *region = regionSparse->denseVector ( ); double *region2 = regionSparse2->denseVector ( ); int *regionIndex2 = regionSparse2->getIndices ( ); int numberNonZero2 = regionSparse2->getNumElements ( ); int *regionIndex = regionSparse->getIndices ( ); int i; int numberNonZero = 0; bool packed = regionSparse2->packedMode(); if (packed) { for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; int j = permute_[k]; double value = region2[i]; region2[i] = 0.0; region[j] = value; mark_[j] = 1; regionIndex[numberNonZero++] = j; } // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero2; i++) { int j = regionIndex[i]; regionIndex2[i] = j; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth) ; greatestDepth = CoinMax(iDepth, greatestDepth) ; int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } for (; i < numberNonZero; i++) { int j = regionIndex2[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth) ; greatestDepth = CoinMax(iDepth, greatestDepth) ; int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero2 = 0; region[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region[iPivot] = pivotValue; if (pivotValue) { region2[numberNonZero2] = pivotValue; regionIndex2[numberNonZero2++] = iPivot; } iPivot = stack_[iPivot]; } } // zero out for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; region[k] = 0.0; } } else { for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; int j = permute_[k]; double value = region2[k]; region2[k] = 0.0; region[j] = value; mark_[j] = 1; regionIndex[numberNonZero++] = j; } // copy back // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero2; i++) { int j = regionIndex[i]; double value = region[j]; region[j] = 0.0; region2[j] = value; regionIndex2[i] = j; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth) ; greatestDepth = CoinMax(iDepth, greatestDepth) ; int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } for (; i < numberNonZero; i++) { int j = regionIndex2[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth) ; greatestDepth = CoinMax(iDepth, greatestDepth) ; int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero2 = 0; region2[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region2[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region2[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region2[iPivot] = pivotValue; if (pivotValue) regionIndex2[numberNonZero2++] = iPivot; iPivot = stack_[iPivot]; } } } regionSparse2->setNumElements(numberNonZero2); #ifdef FULL_DEBUG { int i; for (i = 0; i < numberRows_; i++) { assert(!mark_[i]); assert (stack2_[i] == -1); } } #endif return numberNonZero2; } Clp-1.15.10/src/ClpPresolve.hpp0000644000076600007660000002460612130015370014611 0ustar coincoin/* $Id: ClpPresolve.hpp 1928 2013-04-06 12:54: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 ClpPresolve_H #define ClpPresolve_H #include "ClpSimplex.hpp" class CoinPresolveAction; #include "CoinPresolveMatrix.hpp" /** This is the Clp interface to CoinPresolve */ class ClpPresolve { public: /**@name Main Constructor, destructor */ //@{ /// Default constructor ClpPresolve(); /// Virtual destructor virtual ~ClpPresolve(); //@} /**@name presolve - presolves a model, transforming the model * and saving information in the ClpPresolve object needed for postsolving. * This underlying (protected) method is virtual; the idea is that in the future, * one could override this method to customize how the various * presolve techniques are applied. This version of presolve returns a pointer to a new presolved model. NULL if infeasible or unbounded. This should be paired with postsolve below. The advantage of going back to original model is that it will be exactly as it was i.e. 0.0 will not become 1.0e-19. If keepIntegers is true then bounds may be tightened in original. Bounds will be moved by up to feasibilityTolerance to try and stay feasible. Names will be dropped in presolved model if asked */ ClpSimplex * presolvedModel(ClpSimplex & si, double feasibilityTolerance = 0.0, bool keepIntegers = true, int numberPasses = 5, bool dropNames = false, bool doRowObjective = false, const char * prohibitedRows=NULL, const char * prohibitedColumns=NULL); #ifndef CLP_NO_STD /** This version saves data in a file. The passed in model is updated to be presolved model. Returns non-zero if infeasible*/ int presolvedModelToFile(ClpSimplex &si, std::string fileName, double feasibilityTolerance = 0.0, bool keepIntegers = true, int numberPasses = 5, bool dropNames = false, bool doRowObjective = false); #endif /** Return pointer to presolved model, Up to user to destroy */ ClpSimplex * model() const; /// Return pointer to original model ClpSimplex * originalModel() const; /// Set pointer to original model void setOriginalModel(ClpSimplex * model); /// return pointer to original columns const int * originalColumns() const; /// return pointer to original rows const int * originalRows() const; /** "Magic" number. If this is non-zero then any elements with this value may change and so presolve is very limited in what can be done to the row and column. This is for non-linear problems. */ inline void setNonLinearValue(double value) { nonLinearValue_ = value; } inline double nonLinearValue() const { return nonLinearValue_; } /// Whether we want to do dual part of presolve inline bool doDual() const { return (presolveActions_ & 1) == 0; } inline void setDoDual(bool doDual) { if (doDual) presolveActions_ &= ~1; else presolveActions_ |= 1; } /// Whether we want to do singleton part of presolve inline bool doSingleton() const { return (presolveActions_ & 2) == 0; } inline void setDoSingleton(bool doSingleton) { if (doSingleton) presolveActions_ &= ~2; else presolveActions_ |= 2; } /// Whether we want to do doubleton part of presolve inline bool doDoubleton() const { return (presolveActions_ & 4) == 0; } inline void setDoDoubleton(bool doDoubleton) { if (doDoubleton) presolveActions_ &= ~4; else presolveActions_ |= 4; } /// Whether we want to do tripleton part of presolve inline bool doTripleton() const { return (presolveActions_ & 8) == 0; } inline void setDoTripleton(bool doTripleton) { if (doTripleton) presolveActions_ &= ~8; else presolveActions_ |= 8; } /// Whether we want to do tighten part of presolve inline bool doTighten() const { return (presolveActions_ & 16) == 0; } inline void setDoTighten(bool doTighten) { if (doTighten) presolveActions_ &= ~16; else presolveActions_ |= 16; } /// Whether we want to do forcing part of presolve inline bool doForcing() const { return (presolveActions_ & 32) == 0; } inline void setDoForcing(bool doForcing) { if (doForcing) presolveActions_ &= ~32; else presolveActions_ |= 32; } /// Whether we want to do impliedfree part of presolve inline bool doImpliedFree() const { return (presolveActions_ & 64) == 0; } inline void setDoImpliedFree(bool doImpliedfree) { if (doImpliedfree) presolveActions_ &= ~64; else presolveActions_ |= 64; } /// Whether we want to do dupcol part of presolve inline bool doDupcol() const { return (presolveActions_ & 128) == 0; } inline void setDoDupcol(bool doDupcol) { if (doDupcol) presolveActions_ &= ~128; else presolveActions_ |= 128; } /// Whether we want to do duprow part of presolve inline bool doDuprow() const { return (presolveActions_ & 256) == 0; } inline void setDoDuprow(bool doDuprow) { if (doDuprow) presolveActions_ &= ~256; else presolveActions_ |= 256; } /// Whether we want to do singleton column part of presolve inline bool doSingletonColumn() const { return (presolveActions_ & 512) == 0; } inline void setDoSingletonColumn(bool doSingleton) { if (doSingleton) presolveActions_ &= ~512; else presolveActions_ |= 512; } /// Whether we want to do gubrow part of presolve inline bool doGubrow() const { return (presolveActions_ & 1024) == 0; } inline void setDoGubrow(bool doGubrow) { if (doGubrow) presolveActions_ &= ~1024; else presolveActions_ |= 1024; } /// Whether we want to do twoxtwo part of presolve inline bool doTwoxTwo() const { return (presolveActions_ & 2048) != 0; } inline void setDoTwoxtwo(bool doTwoxTwo) { if (!doTwoxTwo) presolveActions_ &= ~2048; else presolveActions_ |= 2048; } /// Set whole group inline int presolveActions() const { return presolveActions_ & 0xffff; } inline void setPresolveActions(int action) { presolveActions_ = (presolveActions_ & 0xffff0000) | (action & 0xffff); } /// Substitution level inline void setSubstitution(int value) { substitution_ = value; } /// Asks for statistics inline void statistics() { presolveActions_ |= 0x80000000; } /// Return presolve status (0,1,2) int presolveStatus() const; /**@name postsolve - postsolve the problem. If the problem has not been solved to optimality, there are no guarantees. If you are using an algorithm like simplex that has a concept of "basic" rows/cols, then set updateStatus Note that if you modified the original problem after presolving, then you must ``undo'' these modifications before calling postsolve. This version updates original*/ virtual void postsolve(bool updateStatus = true); /// Gets rid of presolve actions (e.g.when infeasible) void destroyPresolve(); /**@name private or protected data */ private: /// Original model - must not be destroyed before postsolve ClpSimplex * originalModel_; /// ClpPresolved model - up to user to destroy by deleteClpPresolvedModel ClpSimplex * presolvedModel_; /** "Magic" number. If this is non-zero then any elements with this value may change and so presolve is very limited in what can be done to the row and column. This is for non-linear problems. One could also allow for cases where sign of coefficient is known. */ double nonLinearValue_; /// Original column numbers int * originalColumn_; /// Original row numbers int * originalRow_; /// Row objective double * rowObjective_; /// The list of transformations applied. const CoinPresolveAction *paction_; /// The postsolved problem will expand back to its former size /// as postsolve transformations are applied. /// It is efficient to allocate data structures for the final size /// of the problem rather than expand them as needed. /// These fields give the size of the original problem. int ncols_; int nrows_; CoinBigIndex nelems_; /// Number of major passes int numberPasses_; /// Substitution level int substitution_; #ifndef CLP_NO_STD /// Name of saved model file std::string saveFile_; #endif /** Whether we want to skip dual part of presolve etc. 512 bit allows duplicate column processing on integer columns and dual stuff on integers */ int presolveActions_; protected: /// If you want to apply the individual presolve routines differently, /// or perhaps add your own to the mix, /// define a derived class and override this method virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); /// Postsolving is pretty generic; just apply the transformations /// in reverse order. /// You will probably only be interested in overriding this method /// if you want to add code to test for consistency /// while debugging new presolve techniques. virtual void postsolve(CoinPostsolveMatrix &prob); /** This is main part of Presolve */ virtual ClpSimplex * gutsOfPresolvedModel(ClpSimplex * originalModel, double feasibilityTolerance, bool keepIntegers, int numberPasses, bool dropNames, bool doRowObjective, const char * prohibitedRows=NULL, const char * prohibitedColumns=NULL); }; #endif Clp-1.15.10/src/ClpSimplexPrimal.cpp0000644000076600007660000051445012252354371015610 0ustar coincoin/* $Id: ClpSimplexPrimal.cpp 2006 2013-12-12 15:40: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). /* Notes on implementation of primal simplex algorithm. When primal feasible(A): If dual feasible, we are optimal. Otherwise choose an infeasible basic variable to enter basis from a bound (B). We now need to find an outgoing variable which will leave problem primal feasible so we get the column of the tableau corresponding to the incoming variable (with the correct sign depending if variable will go up or down). We now perform a ratio test to determine which outgoing variable will preserve primal feasibility (C). If no variable found then problem is unbounded (in primal sense). If there is a variable, we then perform pivot and repeat. Trivial? ------------------------------------------- A) How do we get primal feasible? All variables have fake costs outside their feasible region so it is trivial to declare problem feasible. OSL did not have a phase 1/phase 2 approach but instead effectively put an extra cost on infeasible basic variables I am taking the same approach here, although it is generalized to allow for non-linear costs and dual information. In OSL, this weight was changed heuristically, here at present it is only increased if problem looks finished. If problem is feasible I check for unboundedness. If not unbounded we could play with going into dual. As long as weights increase any algorithm would be finite. B) Which incoming variable to choose is a virtual base class. For difficult problems steepest edge is preferred while for very easy (large) problems we will need partial scan. C) Sounds easy, but this is hardest part of algorithm. 1) Instead of stopping at first choice, we may be able to allow that variable to go through bound and if objective still improving choose again. These mini iterations can increase speed by orders of magnitude but we may need to go to more of a bucket choice of variable rather than looking at them one by one (for speed). 2) Accuracy. Basic infeasibilities may be less than tolerance. Pivoting on these makes objective go backwards. OSL modified cost so a zero move was made, Gill et al modified so a strictly positive move was made. The two problems are that re-factorizations can change rinfeasibilities above and below tolerances and that when finished we need to reset costs and try again. 3) Degeneracy. Gill et al helps but may not be enough. We may need more. Also it can improve speed a lot if we perturb the rhs and bounds significantly. References: Forrest and Goldfarb, Steepest-edge simplex algorithms for linear programming - Mathematical Programming 1992 Forrest and Tomlin, Implementing the simplex method for the Optimization Subroutine Library - IBM Systems Journal 1992 Gill, Murray, Saunders, Wright A Practical Anti-Cycling Procedure for Linear and Nonlinear Programming SOL report 1988 TODO: a) Better recovery procedures. At present I never check on forward progress. There is checkpoint/restart with reducing re-factorization frequency, but this is only on singular factorizations. b) Fast methods for large easy problems (and also the option for the code to automatically choose which method). c) We need to be able to stop in various ways for OSI - this is fairly easy. */ #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpSimplexPrimal.hpp" #include "ClpFactorization.hpp" #include "ClpNonLinearCost.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "ClpPrimalColumnPivot.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include #include #include #include #include #ifdef CLP_USER_DRIVEN1 /* Returns true if variable sequenceOut can leave basis when model->sequenceIn() enters. This function may be entered several times for each sequenceOut. The first time realAlpha will be positive if going to lower bound and negative if going to upper bound (scaled bounds in lower,upper) - then will be zero. currentValue is distance to bound. currentTheta is current theta. alpha is fabs(pivot element). Variable will change theta if currentValue - currentTheta*alpha < 0.0 */ bool userChoiceValid1(const ClpSimplex * model, int sequenceOut, double currentValue, double currentTheta, double alpha, double realAlpha); /* This returns true if chosen in/out pair valid. The main thing to check would be variable flipping bounds may be OK. This would be signaled by reasonable theta_ and valueOut_. If you return false sequenceIn_ will be flagged as ineligible. */ bool userChoiceValid2(const ClpSimplex * model); /* If a good pivot then you may wish to unflag some variables. */ void userChoiceWasGood(ClpSimplex * model); #endif // primal int ClpSimplexPrimal::primal (int ifValuesPass , int startFinishOptions) { /* Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of infeasibilityCost_ being given to getting primal feasible. In this version I have tried to be clever in a stupid way. The idea of fake bounds in dual seems to work so the primal analogue would be that of getting bounds on reduced costs (by a presolve approach) and using these for being above or below feasible region. I decided to waste memory and keep these explicitly. This allows for non-linear costs! The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find incoming variable for Dantzig row choice. For steepest edge we keep an updated list of dual infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure of the exact details. The flow of primal is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by changing bounds so primal feasible. If looks finished check fake primal bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot column (incoming variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot column in tableau Choose outgoing row. If we don't find one then we look primal unbounded so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find outgoing row, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve changing bounds on variables to stay primal feasible. } } At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot in option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. */ algorithm_ = +1; moreSpecialOptions_ &= ~16; // clear check replaceColumn accuracy // save data ClpDataSave data = saveData(); matrix_->refresh(this); // make sure matrix okay // Save so can see if doing after dual int initialStatus = problemStatus_; int initialIterations = numberIterations_; int initialNegDjs = -1; // initialize - maybe values pass and algorithm_ is +1 #if 0 // if so - put in any superbasic costed slacks if (ifValuesPass && specialOptions_ < 0x01000000) { // Get column copy const CoinPackedMatrix * columnCopy = matrix(); const int * row = columnCopy->getIndices(); const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); const int * columnLength = columnCopy->getVectorLengths(); //const double * element = columnCopy->getElements(); int n = 0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLength[iColumn] == 1) { Status status = getColumnStatus(iColumn); if (status != basic && status != isFree) { double value = columnActivity_[iColumn]; if (fabs(value - columnLower_[iColumn]) > primalTolerance_ && fabs(value - columnUpper_[iColumn]) > primalTolerance_) { int iRow = row[columnStart[iColumn]]; if (getRowStatus(iRow) == basic) { setRowStatus(iRow, superBasic); setColumnStatus(iColumn, basic); n++; } } } } } printf("%d costed slacks put in basis\n", n); } #endif // Start can skip some things in transposeTimes specialOptions_ |= 131072; if (!startup(ifValuesPass, startFinishOptions)) { // Set average theta nonLinearCost_->setAverageTheta(1.0e3); int lastCleaned = 0; // last time objective or bounds cleaned up // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // This says whether to restore things etc int factorType = 0; if (problemStatus_ < 0 && perturbation_ < 100 && !ifValuesPass) { perturb(0); // Can't get here if values pass assert (!ifValuesPass); gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } ClpSimplex * saveModel = NULL; int stopSprint = -1; int sprintPass = 0; int reasonableSprintIteration = 0; int lastSprintIteration = 0; double lastObjectiveValue = COIN_DBL_MAX; // Start check for cycles progress_.fillFromModel(this); progress_.startCheck(); /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible -5 - looks unbounded */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick #if 1 if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (specialOptions_ & 4) == 0 && initialStatus != 10) { perturb(1); matrix_->rhsOffset(this, true, false); } #endif // If we have done no iterations - special if (lastGoodIteration_ == numberIterations_ && factorType) factorType = 3; if (saveModel) { // Doing sprint if (sequenceIn_ < 0 || numberIterations_ >= stopSprint) { problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; if (sequenceIn_ < 0 && numberIterations_ < reasonableSprintIteration && sprintPass > 100) primalColumnPivot_->switchOffSprint(); //lastSprintIteration=numberIterations_; COIN_DETAIL_PRINT(printf("End small model\n")); } } // may factorize, checks if problem finished statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); if (initialStatus == 10) { // cleanup phase if(initialIterations != numberIterations_) { if (numberDualInfeasibilities_ > 10000 && numberDualInfeasibilities_ > 10 * initialNegDjs) { // getting worse - try perturbing if (perturbation_ < 101 && (specialOptions_ & 4) == 0) { perturb(1); matrix_->rhsOffset(this, true, false); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } } } else { // save number of negative djs if (!numberPrimalInfeasibilities_) initialNegDjs = numberDualInfeasibilities_; // make sure weight won't be changed if (infeasibilityCost_ == 1.0e10) infeasibilityCost_ = 1.000001e10; } } // See if sprint says redo because of problems if (numberDualInfeasibilities_ == -776) { // Need new set of variables problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; //lastSprintIteration=numberIterations_; COIN_DETAIL_PRINT(printf("End small model after\n")); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } int numberSprintIterations = 0; int numberSprintColumns = primalColumnPivot_->numberSprintColumns(numberSprintIterations); if (problemStatus_ == 777) { // problems so do one pass with normal problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; // Skip factorization //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,false,saveModel); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } else if (problemStatus_ < 0 && !saveModel && numberSprintColumns && firstFree_ < 0) { int numberSort = 0; int numberFixed = 0; int numberBasic = 0; reasonableSprintIteration = numberIterations_ + 100; int * whichColumns = new int[numberColumns_]; double * weight = new double[numberColumns_]; int numberNegative = 0; double sumNegative = 0.0; // now massage weight so all basic in plus good djs for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double dj = dj_[iColumn]; switch(getColumnStatus(iColumn)) { case basic: dj = -1.0e50; numberBasic++; break; case atUpperBound: dj = -dj; break; case isFixed: dj = 1.0e50; numberFixed++; break; case atLowerBound: dj = dj; break; case isFree: dj = -100.0 * fabs(dj); break; case superBasic: dj = -100.0 * fabs(dj); break; } if (dj < -dualTolerance_ && dj > -1.0e50) { numberNegative++; sumNegative -= dj; } weight[iColumn] = dj; whichColumns[iColumn] = iColumn; } handler_->message(CLP_SPRINT, messages_) << sprintPass << numberIterations_ - lastSprintIteration << objectiveValue() << sumNegative << numberNegative << CoinMessageEol; sprintPass++; lastSprintIteration = numberIterations_; if (objectiveValue()*optimizationDirection_ > lastObjectiveValue - 1.0e-7 && sprintPass > 5) { // switch off COIN_DETAIL_PRINT(printf("Switching off sprint\n")); primalColumnPivot_->switchOffSprint(); } else { lastObjectiveValue = objectiveValue() * optimizationDirection_; // sort CoinSort_2(weight, weight + numberColumns_, whichColumns); numberSort = CoinMin(numberColumns_ - numberFixed, numberBasic + numberSprintColumns); // Sort to make consistent ? std::sort(whichColumns, whichColumns + numberSort); saveModel = new ClpSimplex(this, numberSort, whichColumns); delete [] whichColumns; delete [] weight; // Skip factorization //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,false,saveModel); //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,true,saveModel); stopSprint = numberIterations_ + numberSprintIterations; COIN_DETAIL_PRINT(printf("Sprint with %d columns for %d iterations\n", numberSprintColumns, numberSprintIterations)); } } // Say good factorization factorType = 1; // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // exit if victory declared if (problemStatus_ >= 0) { #ifdef CLP_USER_DRIVEN int status = eventHandler_->event(ClpEventHandler::endInPrimal); if (status>=0&&status<10) { // carry on problemStatus_=-1; if (status==0) continue; // re-factorize } else if (status>=10) { problemStatus_=status-10; break; } else { break; } #else break; #endif } // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && firstFree_ < 0)) { problemStatus_ = 3; break; } if (firstFree_ < 0) { if (ifValuesPass) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } //#define FEB_TRY #if 1 //def FEB_TRY if (perturbation_ < 100) perturb(0); #endif } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { // if >=100 - then special e.g. unperturb if (status!=101) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } else { unPerturb(); continue; } } } // Iterate whileIterating(ifValuesPass ? 1 : 0); } } // if infeasible get real values //printf("XXXXY final cost %g\n",infeasibilityCost_); progress_.initialWeight_ = 0.0; if (problemStatus_ == 1 && secondaryStatus_ != 6) { infeasibilityCost_ = 0.0; createRim(1 + 4); delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); nonLinearCost_->checkInfeasibilities(0.0); sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities(); numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); // and get good feasible duals computeDuals(NULL); } // Stop can skip some things in transposeTimes specialOptions_ &= ~131072; // clean up unflag(); finish(startFinishOptions); restoreData(data); return problemStatus_; } /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) -4 end of values pass and done iterations +0 looks optimal (might be infeasible - but we will investigate) +2 looks unbounded +3 max iterations */ int ClpSimplexPrimal::whileIterating(int valuesOption) { // Say if values pass int ifValuesPass = (firstFree_ >= 0) ? 1 : 0; int returnCode = -1; int superBasicType = 1; if (valuesOption > 1) superBasicType = 3; // delete any rays delete [] ray_; ray_ = NULL; // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert while (problemStatus_ == -1) { //#define CLP_DEBUG 1 #ifdef CLP_DEBUG { int i; // not [1] as has information for (i = 0; i < 4; i++) { if (i != 1) rowArray_[i]->checkClear(); } for (i = 0; i < 2; i++) { columnArray_[i]->checkClear(); } } #endif #if 0 { int iPivot; double * array = rowArray_[3]->denseVector(); int * index = rowArray_[3]->getIndices(); int i; for (iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = pivotVariable_[iPivot]; unpackPacked(rowArray_[3], iSequence); factorization_->updateColumn(rowArray_[2], rowArray_[3]); int number = rowArray_[3]->getNumElements(); for (i = 0; i < number; i++) { int iRow = index[i]; if (iRow == iPivot) assert (fabs(array[i] - 1.0) < 1.0e-4); else assert (fabs(array[i]) < 1.0e-4); } rowArray_[3]->clear(); } } #endif #if 0 nonLinearCost_->checkInfeasibilities(primalTolerance_); printf("suminf %g number %d\n", nonLinearCost_->sumInfeasibilities(), nonLinearCost_->numberInfeasibilities()); #endif #if CLP_DEBUG>2 // very expensive if (numberIterations_ > 0 && numberIterations_ < 100 && !ifValuesPass) { handler_->setLogLevel(63); double saveValue = objectiveValue_; double * saveRow1 = new double[numberRows_]; double * saveRow2 = new double[numberRows_]; CoinMemcpyN(rowReducedCost_, numberRows_, saveRow1); CoinMemcpyN(rowActivityWork_, numberRows_, saveRow2); double * saveColumn1 = new double[numberColumns_]; double * saveColumn2 = new double[numberColumns_]; CoinMemcpyN(reducedCostWork_, numberColumns_, saveColumn1); CoinMemcpyN(columnActivityWork_, numberColumns_, saveColumn2); gutsOfSolution(NULL, NULL, false); printf("xxx %d old obj %g, recomputed %g, sum primal inf %g\n", numberIterations_, saveValue, objectiveValue_, sumPrimalInfeasibilities_); CoinMemcpyN(saveRow1, numberRows_, rowReducedCost_); CoinMemcpyN(saveRow2, numberRows_, rowActivityWork_); CoinMemcpyN(saveColumn1, numberColumns_, reducedCostWork_); CoinMemcpyN(saveColumn2, numberColumns_, columnActivityWork_); delete [] saveRow1; delete [] saveRow2; delete [] saveColumn1; delete [] saveColumn2; objectiveValue_ = saveValue; } #endif if (!ifValuesPass) { // choose column to come in // can use pivotRow_ to update weights // pass in list of cost changes so can do row updates (rowArray_[1]) // NOTE rowArray_[0] is used by computeDuals which is a // slow way of getting duals but might be used primalColumn(rowArray_[1], rowArray_[2], rowArray_[3], columnArray_[0], columnArray_[1]); } else { // in values pass int sequenceIn = nextSuperBasic(superBasicType, columnArray_[0]); if (valuesOption > 1) superBasicType = 2; if (sequenceIn < 0) { // end of values pass - initialize weights etc handler_->message(CLP_END_VALUES_PASS, messages_) << numberIterations_; primalColumnPivot_->saveWeights(this, 5); problemStatus_ = -2; // factorize now pivotRow_ = -1; // say no weights update returnCode = -4; // Clean up int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (getColumnStatus(i) == atLowerBound || getColumnStatus(i) == isFixed) solution_[i] = lower_[i]; else if (getColumnStatus(i) == atUpperBound) solution_[i] = upper_[i]; } break; } else { // normal sequenceIn_ = sequenceIn; valueIn_ = solution_[sequenceIn_]; lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; } } pivotRow_ = -1; sequenceOut_ = -1; rowArray_[1]->clear(); if (sequenceIn_ >= 0) { // we found a pivot column assert (!flagged(sequenceIn_)); #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) { char x = isColumn(sequenceIn_) ? 'C' : 'R'; std::cout << "pivot column " << x << sequenceWithin(sequenceIn_) << std::endl; } #endif #ifdef CLP_DEBUG { int checkSequence = -2077; if (checkSequence >= 0 && checkSequence < numberRows_ + numberColumns_ && !ifValuesPass) { rowArray_[2]->checkClear(); rowArray_[3]->checkClear(); double * array = rowArray_[3]->denseVector(); int * index = rowArray_[3]->getIndices(); unpackPacked(rowArray_[3], checkSequence); factorization_->updateColumnForDebug(rowArray_[2], rowArray_[3]); int number = rowArray_[3]->getNumElements(); double dualIn = cost_[checkSequence]; int i; for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; double alpha = array[i]; dualIn -= alpha * cost_[iPivot]; } printf("old dj for %d was %g, recomputed %g\n", checkSequence, dj_[checkSequence], dualIn); rowArray_[3]->clear(); if (numberIterations_ > 2000) exit(1); } } #endif // do second half of iteration returnCode = pivotResult(ifValuesPass); if (returnCode < -1 && returnCode > -5) { problemStatus_ = -2; // } else if (returnCode == -5) { if ((moreSpecialOptions_ & 16) == 0 && factorization_->pivots()) { moreSpecialOptions_ |= 16; problemStatus_ = -2; } // otherwise something flagged - continue; } else if (returnCode == 2) { problemStatus_ = -5; // looks unbounded } else if (returnCode == 4) { problemStatus_ = -2; // looks unbounded but has iterated } else if (returnCode != -1) { assert(returnCode == 3); if (problemStatus_ != 5) problemStatus_ = 3; } } else { // no pivot column #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (nonLinearCost_->numberInfeasibilities()) problemStatus_ = -4; // might be infeasible // Force to re-factorize early next time int numberPivots = factorization_->pivots(); returnCode = 0; #ifdef CLP_USER_DRIVEN // If large number of pivots trap later? if (problemStatus_==-1 && numberPivots<1000000) { int status = eventHandler_->event(ClpEventHandler::noCandidateInPrimal); if (status>=0&&status<10) { // carry on problemStatus_=-1; if (status==0) break; } else if (status>=10) { problemStatus_=status-10; break; } else { forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); break; } } #else forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); break; #endif } } if (valuesOption > 1) columnArray_[0]->setNumElements(0); return returnCode; } /* Checks if finished. Updates status */ void ClpSimplexPrimal::statusOfProblemInPrimal(int & lastCleaned, int type, ClpSimplexProgress * progress, bool doFactorization, int ifValuesPass, ClpSimplex * originalModel) { int dummy; // for use in generalExpanded int saveFirstFree = firstFree_; // number of pivots done int numberPivots = factorization_->pivots(); if (type == 2) { // trouble - restore solution CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); forceFactorization_ = 1; // a bit drastic but .. pivotRow_ = -1; // say no weights update changeMade_++; // say change made } int saveThreshold = factorization_->sparseThreshold(); int tentativeStatus = problemStatus_; int numberThrownOut = 1; // to loop round on bad factorization in values pass double lastSumInfeasibility = COIN_DBL_MAX; if (numberIterations_) lastSumInfeasibility = nonLinearCost_->sumInfeasibilities(); int nPass = 0; while (numberThrownOut) { int nSlackBasic = 0; if (nPass) { for (int i = 0; i < numberRows_; i++) { if (getRowStatus(i) == basic) nSlackBasic++; } } nPass++; if (problemStatus_ > -3 || problemStatus_ == -4) { // factorize // later on we will need to recover from singularities // also we could skip if first time // do weights // This may save pivotRow_ for use if (doFactorization) primalColumnPivot_->saveWeights(this, 1); if ((type && doFactorization) || nSlackBasic == numberRows_) { // is factorization okay? int factorStatus = internalFactorize(1); if (factorStatus) { if (solveType_ == 2 + 8) { // say odd problemStatus_ = 5; return; } if (type != 1 || largestPrimalError_ > 1.0e3 || largestDualError_ > 1.0e3) { // switch off dense int saveDense = factorization_->denseThreshold(); factorization_->setDenseThreshold(0); // Go to safe factorization_->pivotTolerance(0.99); // make sure will do safe factorization pivotVariable_[0] = -1; internalFactorize(2); factorization_->setDenseThreshold(saveDense); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); } else { // no - restore previous basis // Keep any flagged variables int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (flagged(i)) saveStatus_[i] |= 64; //say flagged } CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); if (numberPivots <= 1) { // throw out something if (sequenceIn_ >= 0 && getStatus(sequenceIn_) != basic) { setFlagged(sequenceIn_); } else if (sequenceOut_ >= 0 && getStatus(sequenceOut_) != basic) { setFlagged(sequenceOut_); } double newTolerance = CoinMax(0.5 + 0.499 * randomNumberGenerator_.randomDouble(), factorization_->pivotTolerance()); factorization_->pivotTolerance(newTolerance); } else { // Go to safe factorization_->pivotTolerance(0.99); } CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); matrix_->generalExpanded(this, 5, dummy); forceFactorization_ = 1; // a bit drastic but .. type = 2; if (internalFactorize(2) != 0) { largestPrimalError_ = 1.0e4; // force other type } } changeMade_++; // say change made } } if (problemStatus_ != -4) problemStatus_ = -3; } // at this stage status is -3 or -5 if looks unbounded // get primal and dual solutions // put back original costs and then check // createRim(4); // costs do not change // May need to do more if column generation dummy = 4; matrix_->generalExpanded(this, 9, dummy); #ifndef CLP_CAUTION #define CLP_CAUTION 1 #endif #if CLP_CAUTION double lastAverageInfeasibility = sumDualInfeasibilities_ / static_cast(numberDualInfeasibilities_ + 10); #endif #ifdef CLP_USER_DRIVEN int status = eventHandler_->event(ClpEventHandler::goodFactorization); if (status >= 0) { lastSumInfeasibility = COIN_DBL_MAX; } #endif numberThrownOut = gutsOfSolution(NULL, NULL, (firstFree_ >= 0)); double sumInfeasibility = nonLinearCost_->sumInfeasibilities(); int reason2 = 0; #if CLP_CAUTION #if CLP_CAUTION==2 double test2 = 1.0e5; #else double test2 = 1.0e-1; #endif if (!lastSumInfeasibility && sumInfeasibility && lastAverageInfeasibility < test2 && numberPivots > 10) reason2 = 3; if (lastSumInfeasibility < 1.0e-6 && sumInfeasibility > 1.0e-3 && numberPivots > 10) reason2 = 4; #endif if (numberThrownOut) reason2 = 1; if ((sumInfeasibility > 1.0e7 && sumInfeasibility > 100.0 * lastSumInfeasibility && factorization_->pivotTolerance() < 0.11) || (largestPrimalError_ > 1.0e10 && largestDualError_ > 1.0e10)) reason2 = 2; if (reason2) { problemStatus_ = tentativeStatus; doFactorization = true; if (numberPivots) { // go back // trouble - restore solution CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); if (reason2 < 3) { // Go to safe factorization_->pivotTolerance(CoinMin(0.99, 1.01 * factorization_->pivotTolerance())); forceFactorization_ = 1; // a bit drastic but .. } else if (forceFactorization_ < 0) { forceFactorization_ = CoinMin(numberPivots / 2, 100); } else { forceFactorization_ = CoinMin(forceFactorization_, CoinMax(3, numberPivots / 2)); } pivotRow_ = -1; // say no weights update changeMade_++; // say change made if (numberPivots == 1) { // throw out something if (sequenceIn_ >= 0 && getStatus(sequenceIn_) != basic) { setFlagged(sequenceIn_); } else if (sequenceOut_ >= 0 && getStatus(sequenceOut_) != basic) { setFlagged(sequenceOut_); } } type = 2; // so will restore weights if (internalFactorize(2) != 0) { largestPrimalError_ = 1.0e4; // force other type } numberPivots = 0; numberThrownOut = gutsOfSolution(NULL, NULL, (firstFree_ >= 0)); assert (!numberThrownOut); sumInfeasibility = nonLinearCost_->sumInfeasibilities(); } } } // Double check reduced costs if no action if (progress->lastIterationNumber(0) == numberIterations_) { if (primalColumnPivot_->looksOptimal()) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; } } // If in primal and small dj give up if ((specialOptions_ & 1024) != 0 && !numberPrimalInfeasibilities_ && numberDualInfeasibilities_) { double average = sumDualInfeasibilities_ / (static_cast (numberDualInfeasibilities_)); if (numberIterations_ > 300 && average < 1.0e-4) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; } } // Check if looping int loop; if (type != 2 && !ifValuesPass) loop = progress->looping(); else loop = -1; if (loop >= 0) { if (!problemStatus_) { // declaring victory numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else { problemStatus_ = loop; //exit if in loop problemStatus_ = 10; // instead - try other algorithm numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); } problemStatus_ = 10; // instead - try other algorithm return ; } else if (loop < -1) { // Is it time for drastic measures if (nonLinearCost_->numberInfeasibilities() && progress->badTimes() > 5 && progress->oddState() < 10 && progress->oddState() >= 0) { progress->newOddState(); nonLinearCost_->zapCosts(); } // something may have changed gutsOfSolution(NULL, NULL, ifValuesPass != 0); } // If progress then reset costs if (loop == -1 && !nonLinearCost_->numberInfeasibilities() && progress->oddState() < 0) { createRim(4, false); // costs back delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); progress->endOddState(); gutsOfSolution(NULL, NULL, ifValuesPass != 0); } // Flag to say whether to go to dual to clean up bool goToDual = false; // really for free variables in //if((progressFlag_&2)!=0) //problemStatus_=-1;; progressFlag_ = 0; //reset progress flag handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << nonLinearCost_->feasibleReportCost(); handler_->printing(nonLinearCost_->numberInfeasibilities() > 0) << nonLinearCost_->sumInfeasibilities() << nonLinearCost_->numberInfeasibilities(); handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; if (!primalFeasible()) { nonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfSolution(NULL, NULL, ifValuesPass != 0); nonLinearCost_->checkInfeasibilities(primalTolerance_); } if (nonLinearCost_->numberInfeasibilities() > 0 && !progress->initialWeight_ && !ifValuesPass && infeasibilityCost_ == 1.0e10) { // first time infeasible - start up weight computation double * oldDj = dj_; double * oldCost = cost_; int numberRows2 = numberRows_ + numberExtraRows_; int numberTotal = numberRows2 + numberColumns_; dj_ = new double[numberTotal]; cost_ = new double[numberTotal]; reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; double direction = optimizationDirection_ * objectiveScale_; const double * obj = objective(); memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double)); int iSequence; if (columnScale_) for (iSequence = 0; iSequence < numberColumns_; iSequence++) cost_[iSequence] = obj[iSequence] * direction * columnScale_[iSequence]; else for (iSequence = 0; iSequence < numberColumns_; iSequence++) cost_[iSequence] = obj[iSequence] * direction; computeDuals(NULL); int numberSame = 0; int numberDifferent = 0; int numberZero = 0; int numberFreeSame = 0; int numberFreeDifferent = 0; int numberFreeZero = 0; int n = 0; for (iSequence = 0; iSequence < numberTotal; iSequence++) { if (getStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double distanceUp = upper_[iSequence] - solution_[iSequence]; double distanceDown = solution_[iSequence] - lower_[iSequence]; double feasibleDj = dj_[iSequence]; double infeasibleDj = oldDj[iSequence] - feasibleDj; double value = feasibleDj * infeasibleDj; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown > primalTolerance_) { // free if (value > dualTolerance_) { numberFreeSame++; } else if(value < -dualTolerance_) { numberFreeDifferent++; dj_[n++] = feasibleDj / infeasibleDj; } else { numberFreeZero++; } } else { // should not be negative if (value > dualTolerance_) { numberSame++; } else if(value < -dualTolerance_) { numberDifferent++; dj_[n++] = feasibleDj / infeasibleDj; } else { numberZero++; } } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > dualTolerance_) { numberSame++; } else if(value < -dualTolerance_) { numberDifferent++; dj_[n++] = feasibleDj / infeasibleDj; } else { numberZero++; } } } progress->initialWeight_ = -1.0; } //printf("XXXX %d same, %d different, %d zero, -- free %d %d %d\n", // numberSame,numberDifferent,numberZero, // numberFreeSame,numberFreeDifferent,numberFreeZero); // we want most to be same if (n) { double most = 0.95; std::sort(dj_, dj_ + n); int which = static_cast ((1.0 - most) * static_cast (n)); double take = -dj_[which] * infeasibilityCost_; //printf("XXXXZ inf cost %g take %g (range %g %g)\n",infeasibilityCost_,take,-dj_[0]*infeasibilityCost_,-dj_[n-1]*infeasibilityCost_); take = -dj_[0] * infeasibilityCost_; infeasibilityCost_ = CoinMin(CoinMax(1000.0 * take, 1.0e8), 1.0000001e10);; //printf("XXXX increasing weight to %g\n",infeasibilityCost_); } delete [] dj_; delete [] cost_; dj_ = oldDj; cost_ = oldCost; reducedCostWork_ = dj_; rowReducedCost_ = dj_ + numberColumns_; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; if (n||matrix_->type()>=15) gutsOfSolution(NULL, NULL, ifValuesPass != 0); } double trueInfeasibility = nonLinearCost_->sumInfeasibilities(); if (!nonLinearCost_->numberInfeasibilities() && infeasibilityCost_ == 1.0e10 && !ifValuesPass && true) { // relax if default infeasibilityCost_ = CoinMin(CoinMax(100.0 * sumDualInfeasibilities_, 1.0e8), 1.00000001e10); // reset looping criterion progress->reset(); trueInfeasibility = 1.123456e10; } if (trueInfeasibility > 1.0) { // If infeasibility going up may change weights double testValue = trueInfeasibility - 1.0e-4 * (10.0 + trueInfeasibility); double lastInf = progress->lastInfeasibility(1); double lastInf3 = progress->lastInfeasibility(3); double thisObj = progress->lastObjective(0); double thisInf = progress->lastInfeasibility(0); thisObj += infeasibilityCost_ * 2.0 * thisInf; double lastObj = progress->lastObjective(1); lastObj += infeasibilityCost_ * 2.0 * lastInf; double lastObj3 = progress->lastObjective(3); lastObj3 += infeasibilityCost_ * 2.0 * lastInf3; if (lastObj < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj)) - 1.0e-7 && firstFree_ < 0) { if (handler_->logLevel() == 63) printf("lastobj %g this %g force %d\n", lastObj, thisObj, forceFactorization_); int maxFactor = factorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 2)); if (handler_->logLevel() == 63) printf("Reducing factorization frequency to %d\n", forceFactorization_); } } else if (lastObj3 < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj3)) - 1.0e-7 && firstFree_ < 0) { if (handler_->logLevel() == 63) printf("lastobj3 %g this3 %g force %d\n", lastObj3, thisObj, forceFactorization_); int maxFactor = factorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ * 2) / 3); if (handler_->logLevel() == 63) printf("Reducing factorization frequency to %d\n", forceFactorization_); } } else if(lastInf < testValue || trueInfeasibility == 1.123456e10) { if (infeasibilityCost_ < 1.0e14) { infeasibilityCost_ *= 1.5; // reset looping criterion progress->reset(); if (handler_->logLevel() == 63) printf("increasing weight to %g\n", infeasibilityCost_); gutsOfSolution(NULL, NULL, ifValuesPass != 0); } } } // we may wish to say it is optimal even if infeasible bool alwaysOptimal = (specialOptions_ & 1) != 0; // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; // But check if in sprint if (originalModel) { // Carry on and re-do numberDualInfeasibilities_ = -776; } // But if real primal infeasibilities nonzero carry on if (nonLinearCost_->numberInfeasibilities()) { // most likely to happen if infeasible double relaxedToleranceP = primalTolerance_; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, largestPrimalError_); // allow tolerance at least slightly bigger than standard relaxedToleranceP = relaxedToleranceP + error; int ninfeas = nonLinearCost_->numberInfeasibilities(); double sum = nonLinearCost_->sumInfeasibilities(); double average = sum / static_cast (ninfeas); #ifdef COIN_DEVELOP if (handler_->logLevel() > 0) printf("nonLinearCost says infeasible %d summing to %g\n", ninfeas, sum); #endif if (average > relaxedToleranceP) { sumOfRelaxedPrimalInfeasibilities_ = sum; numberPrimalInfeasibilities_ = ninfeas; sumPrimalInfeasibilities_ = sum; #ifdef COIN_DEVELOP bool unflagged = #endif unflag(); #ifdef COIN_DEVELOP if (unflagged && handler_->logLevel() > 0) printf(" - but flagged variables\n"); #endif } } } // had ||(type==3&&problemStatus_!=-5) -- ??? why ???? if ((dualFeasible() || problemStatus_ == -4) && !ifValuesPass) { // see if extra helps if (nonLinearCost_->numberInfeasibilities() && (nonLinearCost_->sumInfeasibilities() > 1.0e-3 || sumOfRelaxedPrimalInfeasibilities_) && !alwaysOptimal) { //may need infeasiblity cost changed // we can see if we can construct a ray // make up a new objective double saveWeight = infeasibilityCost_; // save nonlinear cost as we are going to switch off costs ClpNonLinearCost * nonLinear = nonLinearCost_; // do twice to make sure Primal solution has settled // put non-basics to bounds in case tolerance moved // put back original costs createRim(4); nonLinearCost_->checkInfeasibilities(0.0); gutsOfSolution(NULL, NULL, ifValuesPass != 0); infeasibilityCost_ = 1.0e100; // put back original costs createRim(4); nonLinearCost_->checkInfeasibilities(primalTolerance_); // may have fixed infeasibilities - double check if (nonLinearCost_->numberInfeasibilities() == 0) { // carry on problemStatus_ = -1; infeasibilityCost_ = saveWeight; nonLinearCost_->checkInfeasibilities(primalTolerance_); } else { nonLinearCost_ = NULL; // scale int i; for (i = 0; i < numberRows_ + numberColumns_; i++) cost_[i] *= 1.0e-95; gutsOfSolution(NULL, NULL, ifValuesPass != 0); nonLinearCost_ = nonLinear; infeasibilityCost_ = saveWeight; if ((infeasibilityCost_ >= 1.0e18 || numberDualInfeasibilities_ == 0) && perturbation_ == 101) { goToDual = unPerturb(); // stop any further perturbation if (nonLinearCost_->sumInfeasibilities() > 1.0e-1) goToDual = false; nonLinearCost_->checkInfeasibilities(primalTolerance_); numberDualInfeasibilities_ = 1; // carry on problemStatus_ = -1; } else if (numberDualInfeasibilities_ == 0 && largestDualError_ > 1.0e-2 && (moreSpecialOptions_ & (256|8192)) == 0) { goToDual = true; factorization_->pivotTolerance(CoinMax(0.9, factorization_->pivotTolerance())); } if (!goToDual) { if (infeasibilityCost_ >= 1.0e20 || numberDualInfeasibilities_ == 0) { // we are infeasible - use as ray delete [] ray_; ray_ = new double [numberRows_]; // swap sign for (int i=0;icheckInfeasibilities(primalTolerance_); gutsOfSolution(NULL, NULL, ifValuesPass != 0); // so will exit infeasibilityCost_ = 1.0e30; // reset infeasibilities sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities();; numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); } if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; // reset looping criterion progress->reset(); changeMade_++; // say change made handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check createRim(4); nonLinearCost_->checkInfeasibilities(0.0); gutsOfSolution(NULL, NULL, ifValuesPass != 0); problemStatus_ = -1; //continue goToDual = false; } else { // say infeasible problemStatus_ = 1; } } } } else { // may be optimal if (perturbation_ == 101) { goToDual = unPerturb(); // stop any further perturbation if ((numberRows_ > 20000 || numberDualInfeasibilities_) && !numberTimesOptimal_) goToDual = false; // Better to carry on a bit longer lastCleaned = -1; // carry on } bool unflagged = (unflag() != 0); if ( lastCleaned != numberIterations_ || unflagged) { handler_->message(CLP_PRIMAL_OPTIMAL, messages_) << primalTolerance_ << CoinMessageEol; if (numberTimesOptimal_ < 4) { numberTimesOptimal_++; changeMade_++; // say change made if (numberTimesOptimal_ == 1) { // better to have small tolerance even if slower factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15)); } lastCleaned = numberIterations_; if (primalTolerance_ != dblParam_[ClpPrimalTolerance]) handler_->message(CLP_PRIMAL_ORIGINAL, messages_) << CoinMessageEol; double oldTolerance = primalTolerance_; primalTolerance_ = dblParam_[ClpPrimalTolerance]; #if 0 double * xcost = new double[numberRows_+numberColumns_]; double * xlower = new double[numberRows_+numberColumns_]; double * xupper = new double[numberRows_+numberColumns_]; double * xdj = new double[numberRows_+numberColumns_]; double * xsolution = new double[numberRows_+numberColumns_]; CoinMemcpyN(cost_, (numberRows_ + numberColumns_), xcost); CoinMemcpyN(lower_, (numberRows_ + numberColumns_), xlower); CoinMemcpyN(upper_, (numberRows_ + numberColumns_), xupper); CoinMemcpyN(dj_, (numberRows_ + numberColumns_), xdj); CoinMemcpyN(solution_, (numberRows_ + numberColumns_), xsolution); #endif // put back original costs and then check createRim(4); nonLinearCost_->checkInfeasibilities(oldTolerance); #if 0 int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (cost_[i] != xcost[i]) printf("** %d old cost %g new %g sol %g\n", i, xcost[i], cost_[i], solution_[i]); if (lower_[i] != xlower[i]) printf("** %d old lower %g new %g sol %g\n", i, xlower[i], lower_[i], solution_[i]); if (upper_[i] != xupper[i]) printf("** %d old upper %g new %g sol %g\n", i, xupper[i], upper_[i], solution_[i]); if (dj_[i] != xdj[i]) printf("** %d old dj %g new %g sol %g\n", i, xdj[i], dj_[i], solution_[i]); if (solution_[i] != xsolution[i]) printf("** %d old solution %g new %g sol %g\n", i, xsolution[i], solution_[i], solution_[i]); } delete [] xcost; delete [] xupper; delete [] xlower; delete [] xdj; delete [] xsolution; #endif gutsOfSolution(NULL, NULL, ifValuesPass != 0); if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } if (dualFeasible() && !nonLinearCost_->numberInfeasibilities() && lastCleaned >= 0) problemStatus_ = 0; else problemStatus_ = -1; } else { problemStatus_ = 0; // optimal if (lastCleaned < numberIterations_) { handler_->message(CLP_SIMPLEX_GIVINGUP, messages_) << CoinMessageEol; } } } else { if (!alwaysOptimal || !sumOfRelaxedPrimalInfeasibilities_) problemStatus_ = 0; // optimal else problemStatus_ = 1; // infeasible } } } else { // see if looks unbounded if (problemStatus_ == -5) { if (nonLinearCost_->numberInfeasibilities()) { if (infeasibilityCost_ > 1.0e18 && perturbation_ == 101) { // back off weight infeasibilityCost_ = 1.0e13; // reset looping criterion progress->reset(); unPerturb(); // stop any further perturbation } //we need infeasiblity cost changed if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; // reset looping criterion progress->reset(); changeMade_++; // say change made handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check createRim(4); gutsOfSolution(NULL, NULL, ifValuesPass != 0); problemStatus_ = -1; //continue } else { // say infeasible problemStatus_ = 1; // we are infeasible - use as ray delete [] ray_; ray_ = new double [numberRows_]; CoinMemcpyN(dual_, numberRows_, ray_); } } else { // say unbounded problemStatus_ = 2; } } else { // carry on problemStatus_ = -1; if(type == 3 && !ifValuesPass) { //bool unflagged = unflag(); if (sumDualInfeasibilities_ < 1.0e-3 || (sumDualInfeasibilities_ / static_cast (numberDualInfeasibilities_)) < 1.0e-5 || progress->lastIterationNumber(0) == numberIterations_) { if (!numberPrimalInfeasibilities_) { if (numberTimesOptimal_ < 4) { numberTimesOptimal_++; changeMade_++; // say change made } else { problemStatus_ = 0; secondaryStatus_ = 5; } } } } } } if (problemStatus_ == 0) { double objVal = (nonLinearCost_->feasibleCost() + objective_->nonlinearOffset()); objVal /= (objectiveScale_ * rhsScale_); double tol = 1.0e-10 * CoinMax(fabs(objVal), fabs(objectiveValue_)) + 1.0e-8; if (fabs(objVal - objectiveValue_) > tol) { #ifdef COIN_DEVELOP if (handler_->logLevel() > 0) printf("nonLinearCost has feasible obj of %g, objectiveValue_ is %g\n", objVal, objectiveValue_); #endif objectiveValue_ = objVal; } } // save extra stuff matrix_->generalExpanded(this, 5, dummy); if (type == 0 || type == 1) { if (type != 1 || !saveStatus_) { // create save arrays delete [] saveStatus_; delete [] savedSolution_; saveStatus_ = new unsigned char [numberRows_+numberColumns_]; savedSolution_ = new double [numberRows_+numberColumns_]; } // save arrays CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus_); CoinMemcpyN(rowActivityWork_, numberRows_, savedSolution_ + numberColumns_); CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_); } // see if in Cbc etc bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; bool disaster = false; if (disasterArea_ && inCbcOrOther && disasterArea_->check()) { disasterArea_->saveInfo(); disaster = true; } if (disaster) problemStatus_ = 3; if (problemStatus_ < 0 && !changeMade_) { problemStatus_ = 4; // unknown } lastGoodIteration_ = numberIterations_; if (numberIterations_ > lastBadIteration_ + 100) moreSpecialOptions_ &= ~16; // clear check accuracy flag if ((moreSpecialOptions_ & 256) != 0) goToDual=false; if (goToDual || (numberIterations_ > 1000 && largestPrimalError_ > 1.0e6 && largestDualError_ > 1.0e6)) { problemStatus_ = 10; // try dual // See if second call if ((moreSpecialOptions_ & 256) != 0||nonLinearCost_->sumInfeasibilities()>1.0e2) { numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities(); // say infeasible if (numberPrimalInfeasibilities_) problemStatus_ = 1; } } // make sure first free monotonic if (firstFree_ >= 0 && saveFirstFree >= 0) { firstFree_ = (numberIterations_) ? saveFirstFree : -1; nextSuperBasic(1, NULL); } if (doFactorization) { // restore weights (if saved) - also recompute infeasibility list if (tentativeStatus > -3) primalColumnPivot_->saveWeights(this, (type < 2) ? 2 : 4); else primalColumnPivot_->saveWeights(this, 3); if (saveThreshold) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } } // Allow matrices to be sorted etc int fake = -999; // signal sort matrix_->correctSequence(this, fake, fake); } /* Row array has pivot column This chooses pivot row. For speed, we may need to go to a bucket approach when many variables go through bounds On exit rhsArray will have changes in costs of basic variables */ void ClpSimplexPrimal::primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, int valuesPass) { double saveDj = dualIn_; if (valuesPass && objective_->type() < 2) { dualIn_ = cost_[sequenceIn_]; double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; int iPivot = pivotVariable_[iRow]; dualIn_ -= alpha * cost_[iPivot]; } // determine direction here if (dualIn_ < -dualTolerance_) { directionIn_ = 1; } else if (dualIn_ > dualTolerance_) { directionIn_ = -1; } else { // towards nearest bound if (valueIn_ - lowerIn_ < upperIn_ - valueIn_) { directionIn_ = -1; dualIn_ = dualTolerance_; } else { directionIn_ = 1; dualIn_ = -dualTolerance_; } } } // sequence stays as row number until end pivotRow_ = -1; int numberRemaining = 0; double totalThru = 0.0; // for when variables flip // Allow first few iterations to take tiny double acceptablePivot = 1.0e-1 * acceptablePivot_; if (numberIterations_ > 100) acceptablePivot = acceptablePivot_; if (factorization_->pivots() > 10) acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (factorization_->pivots() > 5) acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (factorization_->pivots()) acceptablePivot = acceptablePivot_; // relax double bestEverPivot = acceptablePivot; int lastPivotRow = -1; double lastPivot = 0.0; double lastTheta = 1.0e50; // use spareArrays to put ones looked at in // First one is list of candidates // We could compress if we really know we won't need any more // Second array has current set of pivot candidates // with a backup list saved in double * part of indexed vector // pivot elements double * spare; // indices int * index; spareArray->clear(); spare = spareArray->denseVector(); index = spareArray->getIndices(); // we also need somewhere for effective rhs double * rhs = rhsArray->denseVector(); // and we can use indices to point to alpha // that way we can store fabs(alpha) int * indexPoint = rhsArray->getIndices(); //int numberFlip=0; // Those which may change if flips /* First we get a list of possible pivots. We can also see if the problem looks unbounded. At first we increase theta and see what happens. We start theta at a reasonable guess. If in right area then we do bit by bit. We save possible pivot candidates */ // do first pass to get possibles // We can also see if unbounded double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); // we need to swap sign if coming in from ub double way = directionIn_; double maximumMovement; if (way > 0.0) maximumMovement = CoinMin(1.0e30, upperIn_ - valueIn_); else maximumMovement = CoinMin(1.0e30, valueIn_ - lowerIn_); double averageTheta = nonLinearCost_->averageTheta(); double tentativeTheta = CoinMin(10.0 * averageTheta, maximumMovement); double upperTheta = maximumMovement; if (tentativeTheta > 0.5 * maximumMovement) tentativeTheta = maximumMovement; bool thetaAtMaximum = tentativeTheta == maximumMovement; // In case tiny bounds increase if (maximumMovement < 1.0) tentativeTheta *= 1.1; double dualCheck = fabs(dualIn_); // but make a bit more pessimistic dualCheck = CoinMax(dualCheck - 100.0 * dualTolerance_, 0.99 * dualCheck); int iIndex; int pivotOne = -1; //#define CLP_DEBUG #ifdef CLP_DEBUG if (numberIterations_ == -3839 || numberIterations_ == -3840) { double dj = cost_[sequenceIn_]; printf("cost in on %d is %g, dual in %g\n", sequenceIn_, dj, dualIn_); for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; int iPivot = pivotVariable_[iRow]; dj -= alpha * cost_[iPivot]; printf("row %d var %d current %g %g %g, alpha %g so sol => %g (cost %g, dj %g)\n", iRow, iPivot, lower_[iPivot], solution_[iPivot], upper_[iPivot], alpha, solution_[iPivot] - 1.0e9 * alpha, cost_[iPivot], dj); } } #endif while (true) { pivotOne = -1; totalThru = 0.0; // We also re-compute reduced cost numberRemaining = 0; dualIn_ = cost_[sequenceIn_]; #ifndef NDEBUG //double tolerance = primalTolerance_ * 1.002; #endif for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; int iPivot = pivotVariable_[iRow]; if (cost_[iPivot]) dualIn_ -= alpha * cost_[iPivot]; alpha *= way; double oldValue = solution_[iPivot]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) bool possible; // do computation same way as later on in primal if (alpha > 0.0) { // basic variable going towards lower bound double bound = lower_[iPivot]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) <= bound + primalTolerance_; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upper_[iPivot]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) >= bound - primalTolerance_; oldValue = bound - oldValue; alpha = - alpha; } double value; //assert (oldValue >= -10.0*tolerance); if (possible) { value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 if(!userChoiceValid1(this,iPivot,oldValue, upperTheta,alpha,work[iIndex]*way)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; pivotOne = numberRemaining; } // add to list spare[numberRemaining] = alpha; rhs[numberRemaining] = oldValue; indexPoint[numberRemaining] = iIndex; index[numberRemaining++] = iRow; totalThru += alpha; setActive(iRow); //} else if (value= 1.0001 * dualCheck) { // Can pivot here break; } else if (!thetaAtMaximum) { //printf("Going round with average theta of %g\n",averageTheta); tentativeTheta = maximumMovement; thetaAtMaximum = true; // seems to be odd compiler error } else { break; } } totalThru = 0.0; theta_ = maximumMovement; bool goBackOne = false; if (objective_->type() > 1) dualIn_ = saveDj; //printf("%d remain out of %d\n",numberRemaining,number); int iTry = 0; #define MAXTRY 1000 if (numberRemaining && upperTheta < maximumMovement) { // First check if previously chosen one will work if (pivotOne >= 0 && 0) { double thruCost = infeasibilityCost_ * spare[pivotOne]; if (thruCost >= 0.99 * fabs(dualIn_)) COIN_DETAIL_PRINT(printf("Could pivot on %d as change %g dj %g\n", index[pivotOne], thruCost, dualIn_)); double alpha = spare[pivotOne]; double oldValue = rhs[pivotOne]; theta_ = oldValue / alpha; pivotRow_ = pivotOne; // Stop loop iTry = MAXTRY; } // first get ratio with tolerance for ( ; iTry < MAXTRY; iTry++) { upperTheta = maximumMovement; int iBest = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 int sequenceOut=pivotVariable_[index[iIndex]]; if(!userChoiceValid1(this,sequenceOut,oldValue, upperTheta,alpha, 0.0)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; iBest = iIndex; // just in case weird numbers } } // now look at best in this lot // But also see how infeasible small pivots will make double sumInfeasibilities = 0.0; double bestPivot = acceptablePivot; pivotRow_ = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { int iRow = index[iIndex]; double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; if (value <= 0 || iBest == iIndex) { // how much would it cost to go thru and modify bound double trueAlpha = way * work[indexPoint[iIndex]]; totalThru += nonLinearCost_->changeInCost(pivotVariable_[iRow], trueAlpha, rhs[iIndex]); setActive(iRow); if (alpha > bestPivot) { bestPivot = alpha; theta_ = oldValue / bestPivot; pivotRow_ = iIndex; } else if (alpha < acceptablePivot #ifdef CLP_USER_DRIVEN1 ||!userChoiceValid1(this,pivotVariable_[index[iIndex]], oldValue,upperTheta,alpha,0.0) #endif ) { if (value < -primalTolerance_) sumInfeasibilities += -value - primalTolerance_; } } } if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && bestPivot < 1.0e-3) { // back to previous one goBackOne = true; break; } else if (pivotRow_ == -1 && upperTheta > largeValue_) { if (lastPivot > acceptablePivot) { // back to previous one goBackOne = true; } else { // can only get here if all pivots so far too small } break; } else if (totalThru >= dualCheck) { if (sumInfeasibilities > primalTolerance_ && !nonLinearCost_->numberInfeasibilities()) { // Looks a bad choice if (lastPivot > acceptablePivot) { goBackOne = true; } else { // say no good dualIn_ = 0.0; } } break; // no point trying another loop } else { lastPivotRow = pivotRow_; lastTheta = theta_; if (bestPivot > bestEverPivot) bestEverPivot = bestPivot; } } // can get here without pivotRow_ set but with lastPivotRow if (goBackOne || (pivotRow_ < 0 && lastPivotRow >= 0)) { // back to previous one pivotRow_ = lastPivotRow; theta_ = lastTheta; } } else if (pivotRow_ < 0 && maximumMovement > 1.0e20) { // looks unbounded valueOut_ = COIN_DBL_MAX; // say odd if (nonLinearCost_->numberInfeasibilities()) { // but infeasible?? // move variable but don't pivot tentativeTheta = 1.0e50; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; int iPivot = pivotVariable_[iRow]; alpha *= way; double oldValue = solution_[iPivot]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) if (alpha > 0.0) { // basic variable going towards lower bound double bound = lower_[iPivot]; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upper_[iPivot]; oldValue = bound - oldValue; alpha = - alpha; } if (oldValue - tentativeTheta * alpha < 0.0) { tentativeTheta = oldValue / alpha; } } // If free in then see if we can get to 0.0 if (lowerIn_ < -1.0e20 && upperIn_ > 1.0e20) { if (dualIn_ * valueIn_ > 0.0) { if (fabs(valueIn_) < 1.0e-2 && (tentativeTheta < fabs(valueIn_) || tentativeTheta > 1.0e20)) { tentativeTheta = fabs(valueIn_); } } } if (tentativeTheta < 1.0e10) valueOut_ = valueIn_ + way * tentativeTheta; } } //if (iTry>50) //printf("** %d tries\n",iTry); if (pivotRow_ >= 0) { int position = pivotRow_; // position in list pivotRow_ = index[position]; alpha_ = work[indexPoint[position]]; // translate to sequence sequenceOut_ = pivotVariable_[pivotRow_]; valueOut_ = solution(sequenceOut_); lowerOut_ = lower_[sequenceOut_]; upperOut_ = upper_[sequenceOut_]; #define MINIMUMTHETA 1.0e-12 // Movement should be minimum for anti-degeneracy - unless // fixed variable out double minimumTheta; if (upperOut_ > lowerOut_) minimumTheta = MINIMUMTHETA; else minimumTheta = 0.0; // But can't go infeasible double distance; if (alpha_ * way > 0.0) distance = valueOut_ - lowerOut_; else distance = upperOut_ - valueOut_; if (distance - minimumTheta * fabs(alpha_) < -primalTolerance_) minimumTheta = CoinMax(0.0, (distance + 0.5 * primalTolerance_) / fabs(alpha_)); // will we need to increase tolerance //#define CLP_DEBUG double largestInfeasibility = primalTolerance_; if (theta_ < minimumTheta && (specialOptions_ & 4) == 0 && !valuesPass) { theta_ = minimumTheta; for (iIndex = 0; iIndex < numberRemaining - numberRemaining; iIndex++) { largestInfeasibility = CoinMax(largestInfeasibility, -(rhs[iIndex] - spare[iIndex] * theta_)); } //#define CLP_DEBUG #ifdef CLP_DEBUG if (largestInfeasibility > primalTolerance_ && (handler_->logLevel() & 32) > -1) printf("Primal tolerance increased from %g to %g\n", primalTolerance_, largestInfeasibility); #endif //#undef CLP_DEBUG primalTolerance_ = CoinMax(primalTolerance_, largestInfeasibility); } // Need to look at all in some cases if (theta_ > tentativeTheta) { for (iIndex = 0; iIndex < number; iIndex++) setActive(which[iIndex]); } if (way < 0.0) theta_ = - theta_; double newValue = valueOut_ - theta_ * alpha_; // If 4 bit set - Force outgoing variables to exact bound (primal) if (alpha_ * way < 0.0) { directionOut_ = -1; // to upper bound if (fabs(theta_) > 1.0e-6 || (specialOptions_ & 4) != 0) { upperOut_ = nonLinearCost_->nearest(sequenceOut_, newValue); } else { upperOut_ = newValue; } } else { directionOut_ = 1; // to lower bound if (fabs(theta_) > 1.0e-6 || (specialOptions_ & 4) != 0) { lowerOut_ = nonLinearCost_->nearest(sequenceOut_, newValue); } else { lowerOut_ = newValue; } } dualOut_ = reducedCost(sequenceOut_); } else if (maximumMovement < 1.0e20) { // flip pivotRow_ = -2; // so we can tell its a flip sequenceOut_ = sequenceIn_; valueOut_ = valueIn_; dualOut_ = dualIn_; lowerOut_ = lowerIn_; upperOut_ = upperIn_; alpha_ = 0.0; if (way < 0.0) { directionOut_ = 1; // to lower bound theta_ = lowerOut_ - valueOut_; } else { directionOut_ = -1; // to upper bound theta_ = upperOut_ - valueOut_; } } double theta1 = CoinMax(theta_, 1.0e-12); double theta2 = numberIterations_ * nonLinearCost_->averageTheta(); // Set average theta nonLinearCost_->setAverageTheta((theta1 + theta2) / (static_cast (numberIterations_ + 1))); //if (numberIterations_%1000==0) //printf("average theta is %g\n",nonLinearCost_->averageTheta()); // clear arrays CoinZeroN(spare, numberRemaining); // put back original bounds etc CoinMemcpyN(index, numberRemaining, rhsArray->getIndices()); rhsArray->setNumElements(numberRemaining); rhsArray->setPacked(); nonLinearCost_->goBackAll(rhsArray); rhsArray->clear(); } /* Chooses primal pivot column updateArray has cost updates (also use pivotRow_ from last iteration) Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first columns we look at */ void ClpSimplexPrimal::primalColumn(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { ClpMatrixBase * saveMatrix = matrix_; double * saveRowScale = rowScale_; if (scaledMatrix_) { rowScale_ = NULL; matrix_ = scaledMatrix_; } sequenceIn_ = primalColumnPivot_->pivotColumn(updates, spareRow1, spareRow2, spareColumn1, spareColumn2); if (scaledMatrix_) { matrix_ = saveMatrix; rowScale_ = saveRowScale; } if (sequenceIn_ >= 0) { valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (nonLinearCost_->lookBothWays()) { // double check ClpSimplex::Status status = getStatus(sequenceIn_); switch(status) { case ClpSimplex::atUpperBound: if (dualIn_ < 0.0) { // move to other side COIN_DETAIL_PRINT(printf("For %d U (%g, %g, %g) dj changed from %g", sequenceIn_, lower_[sequenceIn_], solution_[sequenceIn_], upper_[sequenceIn_], dualIn_)); dualIn_ -= nonLinearCost_->changeUpInCost(sequenceIn_); COIN_DETAIL_PRINT(printf(" to %g\n", dualIn_)); nonLinearCost_->setOne(sequenceIn_, upper_[sequenceIn_] + 2.0 * currentPrimalTolerance()); setStatus(sequenceIn_, ClpSimplex::atLowerBound); } break; case ClpSimplex::atLowerBound: if (dualIn_ > 0.0) { // move to other side COIN_DETAIL_PRINT(printf("For %d L (%g, %g, %g) dj changed from %g", sequenceIn_, lower_[sequenceIn_], solution_[sequenceIn_], upper_[sequenceIn_], dualIn_)); dualIn_ -= nonLinearCost_->changeDownInCost(sequenceIn_); COIN_DETAIL_PRINT(printf(" to %g\n", dualIn_)); nonLinearCost_->setOne(sequenceIn_, lower_[sequenceIn_] - 2.0 * currentPrimalTolerance()); setStatus(sequenceIn_, ClpSimplex::atUpperBound); } break; default: break; } } lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; if (dualIn_ > 0.0) directionIn_ = -1; else directionIn_ = 1; } else { sequenceIn_ = -1; } } /* The primals are updated by the given array. Returns number of infeasibilities. After rowArray will have list of cost changes */ int ClpSimplexPrimal::updatePrimalsInPrimal(CoinIndexedVector * rowArray, double theta, double & objectiveChange, int valuesPass) { // Cost on pivot row may change - may need to change dualIn double oldCost = 0.0; if (pivotRow_ >= 0) oldCost = cost_[sequenceOut_]; //rowArray->scanAndPack(); double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); int newNumber = 0; int pivotPosition = -1; nonLinearCost_->setChangeInCost(0.0); //printf("XX 4138 sol %g lower %g upper %g cost %g status %d\n", // solution_[4138],lower_[4138],upper_[4138],cost_[4138],status_[4138]); // allow for case where bound+tolerance == bound //double tolerance = 0.999999*primalTolerance_; double relaxedTolerance = 1.001 * primalTolerance_; int iIndex; if (!valuesPass) { for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; work[iIndex] = 0.0; int iPivot = pivotVariable_[iRow]; double change = theta * alpha; double value = solution_[iPivot] - change; solution_[iPivot] = value; #ifndef NDEBUG // check if not active then okay if (!active(iRow) && (specialOptions_ & 4) == 0 && pivotRow_ != -1) { // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= lower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value > lower_[iPivot] - relaxedTolerance) value = lower_[iPivot]; //double difference = nonLinearCost_->setOne(iPivot, value); //assert (!difference || fabs(change) > 1.0e9); } } else { // going up if (value >= upper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < upper_[iPivot] + relaxedTolerance) value = upper_[iPivot]; //double difference = nonLinearCost_->setOne(iPivot, value); //assert (!difference || fabs(change) > 1.0e9); } } } #endif if (active(iRow) || theta_ < 0.0) { clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= lower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value >= lower_[iPivot] - relaxedTolerance) value = lower_[iPivot]; double difference = nonLinearCost_->setOne(iPivot, value); if (difference) { if (iRow == pivotRow_) pivotPosition = newNumber; work[newNumber] = difference; //change reduced cost on this dj_[iPivot] = -difference; which[newNumber++] = iRow; } } } else { // going up if (value >= upper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < upper_[iPivot] + relaxedTolerance) value = upper_[iPivot]; double difference = nonLinearCost_->setOne(iPivot, value); if (difference) { if (iRow == pivotRow_) pivotPosition = newNumber; work[newNumber] = difference; //change reduced cost on this dj_[iPivot] = -difference; which[newNumber++] = iRow; } } } } } } else { // values pass so look at all for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; work[iIndex] = 0.0; int iPivot = pivotVariable_[iRow]; double change = theta * alpha; double value = solution_[iPivot] - change; solution_[iPivot] = value; clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= lower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value > lower_[iPivot] - relaxedTolerance) value = lower_[iPivot]; double difference = nonLinearCost_->setOne(iPivot, value); if (difference) { if (iRow == pivotRow_) pivotPosition = newNumber; work[newNumber] = difference; //change reduced cost on this dj_[iPivot] = -difference; which[newNumber++] = iRow; } } } else { // going up if (value >= upper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < upper_[iPivot] + relaxedTolerance) value = upper_[iPivot]; double difference = nonLinearCost_->setOne(iPivot, value); if (difference) { if (iRow == pivotRow_) pivotPosition = newNumber; work[newNumber] = difference; //change reduced cost on this dj_[iPivot] = -difference; which[newNumber++] = iRow; } } } } } objectiveChange += nonLinearCost_->changeInCost(); rowArray->setPacked(); #if 0 rowArray->setNumElements(newNumber); rowArray->expand(); if (pivotRow_ >= 0) { dualIn_ += (oldCost - cost_[sequenceOut_]); // update change vector to include pivot rowArray->add(pivotRow_, -dualIn_); // and convert to packed rowArray->scanAndPack(); } else { // and convert to packed rowArray->scanAndPack(); } #else if (pivotRow_ >= 0) { double dualIn = dualIn_ + (oldCost - cost_[sequenceOut_]); // update change vector to include pivot if (pivotPosition >= 0) { work[pivotPosition] -= dualIn; } else { work[newNumber] = -dualIn; which[newNumber++] = pivotRow_; } } rowArray->setNumElements(newNumber); #endif return 0; } // Perturbs problem void ClpSimplexPrimal::perturb(int type) { if (perturbation_ > 100) return; //perturbed already if (perturbation_ == 100) perturbation_ = 50; // treat as normal int savePerturbation = perturbation_; int i; if (!numberIterations_) cleanStatus(); // make sure status okay // Make sure feasible bounds if (nonLinearCost_) { nonLinearCost_->checkInfeasibilities(); //nonLinearCost_->feasibleBounds(); } // look at element range double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive); largestPositive = CoinMax(fabs(largestNegative), largestPositive); double elementRatio = largestPositive / smallestPositive; if (!numberIterations_ && perturbation_ == 50) { // See if we need to perturb int numberTotal = CoinMax(numberRows_, numberColumns_); double * sort = new double[numberTotal]; int nFixed = 0; for (i = 0; i < numberRows_; i++) { double lo = fabs(rowLower_[i]); double up = fabs(rowUpper_[i]); double value = 0.0; if (lo && lo < 1.0e20) { if (up && up < 1.0e20) { value = 0.5 * (lo + up); if (lo == up) nFixed++; } else { value = lo; } } else { if (up && up < 1.0e20) value = up; } sort[i] = value; } std::sort(sort, sort + numberRows_); int number = 1; double last = sort[0]; for (i = 1; i < numberRows_; i++) { if (last != sort[i]) number++; last = sort[i]; } #ifdef KEEP_GOING_IF_FIXED //printf("ratio number diff rhs %g (%d %d fixed), element ratio %g\n",((double)number)/((double) numberRows_), // numberRows_,nFixed,elementRatio); #endif if (number * 4 > numberRows_ || elementRatio > 1.0e12) { perturbation_ = 100; delete [] sort; return; // good enough } number = 0; #ifdef KEEP_GOING_IF_FIXED if (!integerType_) { // look at columns nFixed = 0; for (i = 0; i < numberColumns_; i++) { double lo = fabs(columnLower_[i]); double up = fabs(columnUpper_[i]); double value = 0.0; if (lo && lo < 1.0e20) { if (up && up < 1.0e20) { value = 0.5 * (lo + up); if (lo == up) nFixed++; } else { value = lo; } } else { if (up && up < 1.0e20) value = up; } sort[i] = value; } std::sort(sort, sort + numberColumns_); number = 1; last = sort[0]; for (i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } //printf("cratio number diff bounds %g (%d %d fixed)\n",((double)number)/((double) numberColumns_), // numberColumns_,nFixed); } #endif delete [] sort; if (number * 4 > numberColumns_) { perturbation_ = 100; return; // good enough } } // primal perturbation double perturbation = 1.0e-20; double bias = 1.0; int numberNonZero = 0; // maximum fraction of rhs/bounds to perturb double maximumFraction = 1.0e-5; if (perturbation_ >= 50) { perturbation = 1.0e-4; for (i = 0; i < numberColumns_ + numberRows_; i++) { if (upper_[i] > lower_[i] + primalTolerance_) { double lowerValue, upperValue; if (lower_[i] > -1.0e20) lowerValue = fabs(lower_[i]); else lowerValue = 0.0; if (upper_[i] < 1.0e20) upperValue = fabs(upper_[i]); else upperValue = 0.0; double value = CoinMax(fabs(lowerValue), fabs(upperValue)); value = CoinMin(value, upper_[i] - lower_[i]); #if 1 if (value) { perturbation += value; numberNonZero++; } #else perturbation = CoinMax(perturbation, value); #endif } } if (numberNonZero) perturbation /= static_cast (numberNonZero); else perturbation = 1.0e-1; if (perturbation_ > 50 && perturbation_ < 55) { // reduce while (perturbation_ > 50) { perturbation_--; perturbation *= 0.25; bias *= 0.25; } } else if (perturbation_ >= 55 && perturbation_ < 60) { // increase while (perturbation_ > 55) { perturbation_--; perturbation *= 4.0; } perturbation_ = 50; } } else if (perturbation_ < 100) { perturbation = pow(10.0, perturbation_); // user is in charge maximumFraction = 1.0; } double largestZero = 0.0; double largest = 0.0; double largestPerCent = 0.0; bool printOut = (handler_->logLevel() == 63); printOut = false; //off // Check if all slack int number = 0; int iSequence; for (iSequence = 0; iSequence < numberRows_; iSequence++) { if (getRowStatus(iSequence) == basic) number++; } if (rhsScale_ > 100.0) { // tone down perturbation maximumFraction *= 0.1; } if (savePerturbation==51) { perturbation = CoinMin(0.1,perturbation); maximumFraction *=0.1; } if (number != numberRows_) type = 1; // modify bounds // Change so at least 1.0e-5 and no more than 0.1 // For now just no more than 0.1 // printf("Pert type %d perturbation %g, maxF %g\n",type,perturbation,maximumFraction); // seems much slower???#define SAVE_PERT #ifdef SAVE_PERT if (2 * numberColumns_ > maximumPerturbationSize_) { delete [] perturbationArray_; maximumPerturbationSize_ = 2 * numberColumns_; perturbationArray_ = new double [maximumPerturbationSize_]; for (int iColumn = 0; iColumn < maximumPerturbationSize_; iColumn++) { perturbationArray_[iColumn] = randomNumberGenerator_.randomDouble(); } } #endif if (type == 1) { double tolerance = 100.0 * primalTolerance_; //double multiplier = perturbation*maximumFraction; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { if (getStatus(iSequence) == basic) { double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; if (upperValue > lowerValue + tolerance) { double solutionValue = solution_[iSequence]; double difference = upperValue - lowerValue; difference = CoinMin(difference, perturbation); difference = CoinMin(difference, fabs(solutionValue) + 1.0); double value = maximumFraction * (difference + bias); value = CoinMin(value, 0.1); value = CoinMax(value,primalTolerance_); #ifndef SAVE_PERT value *= randomNumberGenerator_.randomDouble(); #else value *= perturbationArray_[2*iSequence]; #endif if (solutionValue - lowerValue <= primalTolerance_) { lower_[iSequence] -= value; } else if (upperValue - solutionValue <= primalTolerance_) { upper_[iSequence] += value; } else { #if 0 if (iSequence >= numberColumns_) { // may not be at bound - but still perturb (unless free) if (upperValue > 1.0e30 && lowerValue < -1.0e30) value = 0.0; else value = - value; // as -1.0 in matrix } else { value = 0.0; } #else value = 0.0; #endif } if (value) { if (printOut) printf("col %d lower from %g to %g, upper from %g to %g\n", iSequence, lower_[iSequence], lowerValue, upper_[iSequence], upperValue); if (solutionValue) { largest = CoinMax(largest, value); if (value > (fabs(solutionValue) + 1.0)*largestPerCent) largestPerCent = value / (fabs(solutionValue) + 1.0); } else { largestZero = CoinMax(largestZero, value); } } } } } } else { double tolerance = 100.0 * primalTolerance_; for (i = 0; i < numberColumns_; i++) { double lowerValue = lower_[i], upperValue = upper_[i]; if (upperValue > lowerValue + primalTolerance_) { double value = perturbation * maximumFraction; value = CoinMin(value, 0.1); #ifndef SAVE_PERT value *= randomNumberGenerator_.randomDouble(); #else value *= perturbationArray_[2*i+1]; #endif value *= randomNumberGenerator_.randomDouble(); if (savePerturbation != 50) { if (fabs(value) <= primalTolerance_) value = 0.0; if (lowerValue > -1.0e20 && lowerValue) lowerValue -= value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); if (upperValue < 1.0e20 && upperValue) upperValue += value * (CoinMax(1.0e-2, 1.0e-5 * fabs(upperValue))); } else if (value) { double valueL = value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); // get in range if (valueL <= tolerance) { valueL *= 10.0; while (valueL <= tolerance) valueL *= 10.0; } else if (valueL > 1.0) { valueL *= 0.1; while (valueL > 1.0) valueL *= 0.1; } if (lowerValue > -1.0e20 && lowerValue) lowerValue -= valueL; double valueU = value * (CoinMax(1.0e-2, 1.0e-5 * fabs(upperValue))); // get in range if (valueU <= tolerance) { valueU *= 10.0; while (valueU <= tolerance) valueU *= 10.0; } else if (valueU > 1.0) { valueU *= 0.1; while (valueU > 1.0) valueU *= 0.1; } if (upperValue < 1.0e20 && upperValue) upperValue += valueU; } if (lowerValue != lower_[i]) { double difference = fabs(lowerValue - lower_[i]); largest = CoinMax(largest, difference); if (difference > fabs(lower_[i])*largestPerCent) largestPerCent = fabs(difference / lower_[i]); } if (upperValue != upper_[i]) { double difference = fabs(upperValue - upper_[i]); largest = CoinMax(largest, difference); if (difference > fabs(upper_[i])*largestPerCent) largestPerCent = fabs(difference / upper_[i]); } if (printOut) printf("col %d lower from %g to %g, upper from %g to %g\n", i, lower_[i], lowerValue, upper_[i], upperValue); } lower_[i] = lowerValue; upper_[i] = upperValue; } for (; i < numberColumns_ + numberRows_; i++) { double lowerValue = lower_[i], upperValue = upper_[i]; double value = perturbation * maximumFraction; value = CoinMin(value, 0.1); value *= randomNumberGenerator_.randomDouble(); if (upperValue > lowerValue + tolerance) { if (savePerturbation != 50) { if (fabs(value) <= primalTolerance_) value = 0.0; if (lowerValue > -1.0e20 && lowerValue) lowerValue -= value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); if (upperValue < 1.0e20 && upperValue) upperValue += value * (CoinMax(1.0e-2, 1.0e-5 * fabs(upperValue))); } else if (value) { double valueL = value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); // get in range if (valueL <= tolerance) { valueL *= 10.0; while (valueL <= tolerance) valueL *= 10.0; } else if (valueL > 1.0) { valueL *= 0.1; while (valueL > 1.0) valueL *= 0.1; } if (lowerValue > -1.0e20 && lowerValue) lowerValue -= valueL; double valueU = value * (CoinMax(1.0e-2, 1.0e-5 * fabs(upperValue))); // get in range if (valueU <= tolerance) { valueU *= 10.0; while (valueU <= tolerance) valueU *= 10.0; } else if (valueU > 1.0) { valueU *= 0.1; while (valueU > 1.0) valueU *= 0.1; } if (upperValue < 1.0e20 && upperValue) upperValue += valueU; } } else if (upperValue > 0.0) { upperValue -= value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); lowerValue -= value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); } else if (upperValue < 0.0) { upperValue += value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); lowerValue += value * (CoinMax(1.0e-2, 1.0e-5 * fabs(lowerValue))); } else { } if (lowerValue != lower_[i]) { double difference = fabs(lowerValue - lower_[i]); largest = CoinMax(largest, difference); if (difference > fabs(lower_[i])*largestPerCent) largestPerCent = fabs(difference / lower_[i]); } if (upperValue != upper_[i]) { double difference = fabs(upperValue - upper_[i]); largest = CoinMax(largest, difference); if (difference > fabs(upper_[i])*largestPerCent) largestPerCent = fabs(difference / upper_[i]); } if (printOut) printf("row %d lower from %g to %g, upper from %g to %g\n", i - numberColumns_, lower_[i], lowerValue, upper_[i], upperValue); lower_[i] = lowerValue; upper_[i] = upperValue; } } // Clean up for (i = 0; i < numberColumns_ + numberRows_; i++) { switch(getStatus(i)) { case basic: break; case atUpperBound: solution_[i] = upper_[i]; break; case isFixed: case atLowerBound: solution_[i] = lower_[i]; break; case isFree: break; case superBasic: break; } } handler_->message(CLP_SIMPLEX_PERTURB, messages_) << 100.0 * maximumFraction << perturbation << largest << 100.0 * largestPerCent << largestZero << CoinMessageEol; // redo nonlinear costs // say perturbed perturbation_ = 101; } // un perturb bool ClpSimplexPrimal::unPerturb() { if (perturbation_ != 101) return false; // put back original bounds and costs createRim(1 + 4); sanityCheck(); // unflag unflag(); // get a valid nonlinear cost function delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); perturbation_ = 102; // stop any further perturbation // move non basic variables to new bounds nonLinearCost_->checkInfeasibilities(0.0); #if 1 // Try using dual return true; #else gutsOfSolution(NULL, NULL, ifValuesPass != 0); return false; #endif } // Unflag all variables and return number unflagged int ClpSimplexPrimal::unflag() { int i; int number = numberRows_ + numberColumns_; int numberFlagged = 0; // we can't really trust infeasibilities if there is dual error // allow tolerance bigger than standard to check on duals double relaxedToleranceD = dualTolerance_ + CoinMin(1.0e-2, 10.0 * largestDualError_); for (i = 0; i < number; i++) { if (flagged(i)) { clearFlagged(i); // only say if reasonable dj if (fabs(dj_[i]) > relaxedToleranceD) numberFlagged++; } } numberFlagged += matrix_->generalExpanded(this, 8, i); if (handler_->logLevel() > 2 && numberFlagged && objective_->type() > 1) printf("%d unflagged\n", numberFlagged); return numberFlagged; } // Do not change infeasibility cost and always say optimal void ClpSimplexPrimal::alwaysOptimal(bool onOff) { if (onOff) specialOptions_ |= 1; else specialOptions_ &= ~1; } bool ClpSimplexPrimal::alwaysOptimal() const { return (specialOptions_ & 1) != 0; } // Flatten outgoing variables i.e. - always to exact bound void ClpSimplexPrimal::exactOutgoing(bool onOff) { if (onOff) specialOptions_ |= 4; else specialOptions_ &= ~4; } bool ClpSimplexPrimal::exactOutgoing() const { return (specialOptions_ & 4) != 0; } /* Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done) */ int ClpSimplexPrimal::pivotResult(int ifValuesPass) { bool roundAgain = true; int returnCode = -1; // loop round if user setting and doing refactorization while (roundAgain) { roundAgain = false; returnCode = -1; pivotRow_ = -1; sequenceOut_ = -1; rowArray_[1]->clear(); #if 0 { int seq[] = {612, 643}; int k; for (k = 0; k < sizeof(seq) / sizeof(int); k++) { int iSeq = seq[k]; if (getColumnStatus(iSeq) != basic) { double djval; double * work; int number; int * which; int iIndex; unpack(rowArray_[1], iSeq); factorization_->updateColumn(rowArray_[2], rowArray_[1]); djval = cost_[iSeq]; work = rowArray_[1]->denseVector(); number = rowArray_[1]->getNumElements(); which = rowArray_[1]->getIndices(); for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; int iPivot = pivotVariable_[iRow]; djval -= alpha * cost_[iPivot]; } double comp = 1.0e-8 + 1.0e-7 * (CoinMax(fabs(dj_[iSeq]), fabs(djval))); if (fabs(djval - dj_[iSeq]) > comp) printf("Bad dj %g for %d - true is %g\n", dj_[iSeq], iSeq, djval); assert (fabs(djval) < 1.0e-3 || djval * dj_[iSeq] > 0.0); rowArray_[1]->clear(); } } } #endif // we found a pivot column // update the incoming column unpackPacked(rowArray_[1]); // save reduced cost double saveDj = dualIn_; factorization_->updateColumnFT(rowArray_[2], rowArray_[1]); // Get extra rows matrix_->extendUpdated(this, rowArray_[1], 0); // do ratio test and re-compute dj #ifdef CLP_USER_DRIVEN if (solveType_ != 2 || (moreSpecialOptions_ & 512) == 0) { #endif primalRow(rowArray_[1], rowArray_[3], rowArray_[2], ifValuesPass); #ifdef CLP_USER_DRIVEN // user can tell which use it is int status = eventHandler_->event(ClpEventHandler::pivotRow); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::pivotRow; break; } } else { int status = eventHandler_->event(ClpEventHandler::pivotRow); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::pivotRow; break; } } #endif if (ifValuesPass) { saveDj = dualIn_; //assert (fabs(alpha_)>=1.0e-5||(objective_->type()<2||!objective_->activated())||pivotRow_==-2); if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { if(fabs(dualIn_) < 1.0e2 * dualTolerance_ && objective_->type() < 2) { // try other way directionIn_ = -directionIn_; primalRow(rowArray_[1], rowArray_[3], rowArray_[2], 0); } if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { if (solveType_ == 1) { // reject it char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; } returnCode = -5; break; } } } // need to clear toIndex_ in gub // ? when can I clear stuff // Clean up any gub stuff matrix_->extendUpdated(this, rowArray_[1], 1); double checkValue = 1.0e-2; if (largestDualError_ > 1.0e-5) checkValue = 1.0e-1; double test2 = dualTolerance_; double test1 = 1.0e-20; #if 0 //def FEB_TRY if (factorization_->pivots() < 1) { test1 = -1.0e-4; if ((saveDj < 0.0 && dualIn_ < -1.0e-5 * dualTolerance_) || (saveDj > 0.0 && dualIn_ > 1.0e-5 * dualTolerance_)) test2 = 0.0; // allow through } #endif if (!ifValuesPass && solveType_ == 1 && (saveDj * dualIn_ < test1 || fabs(saveDj - dualIn_) > checkValue*(1.0 + fabs(saveDj)) || fabs(dualIn_) < test2)) { if (!(saveDj * dualIn_ > 0.0 && CoinMin(fabs(saveDj), fabs(dualIn_)) > 1.0e5)) { char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_PRIMAL_DJ, messages_) << x << sequenceWithin(sequenceIn_) << saveDj << dualIn_ << CoinMessageEol; if(lastGoodIteration_ != numberIterations_) { clearAll(); pivotRow_ = -1; // say no weights update returnCode = -4; if(lastGoodIteration_ + 1 == numberIterations_) { // not looking wonderful - try cleaning bounds // put non-basics to bounds in case tolerance moved nonLinearCost_->checkInfeasibilities(0.0); } sequenceOut_ = -1; break; } else { // take on more relaxed criterion if (saveDj * dualIn_ < test1 || fabs(saveDj - dualIn_) > 2.0e-1 * (1.0 + fabs(dualIn_)) || fabs(dualIn_) < test2) { // need to reject something char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); #if 1 //def FEB_TRY // Make safer? factorization_->saferTolerances (-0.99, -1.03); #endif progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; returnCode = -5; sequenceOut_ = -1; break; } } } else { //printf("%d %g %g\n",numberIterations_,saveDj,dualIn_); } } if (pivotRow_ >= 0) { #ifdef CLP_USER_DRIVEN1 // Got good pivot - may need to unflag stuff userChoiceWasGood(this); #endif if (solveType_ >= 2 && (moreSpecialOptions_ & 512) == 0) { // **** Coding for user interface // do ray if (solveType_==2) primalRay(rowArray_[1]); // update duals // as packed need to find pivot row //assert (rowArray_[1]->packedMode()); //int i; //alpha_ = rowArray_[1]->denseVector()[pivotRow_]; CoinAssert (fabs(alpha_) > 1.0e-12); double multiplier = dualIn_ / alpha_; #ifndef NDEBUG rowArray_[0]->checkClear(); #endif rowArray_[0]->insert(pivotRow_, multiplier); factorization_->updateColumnTranspose(rowArray_[2], rowArray_[0]); // put row of tableau in rowArray[0] and columnArray[0] matrix_->transposeTimes(this, -1.0, rowArray_[0], columnArray_[1], columnArray_[0]); // update column djs int i; int * index = columnArray_[0]->getIndices(); int number = columnArray_[0]->getNumElements(); double * element = columnArray_[0]->denseVector(); for (i = 0; i < number; i++) { int ii = index[i]; dj_[ii] += element[ii]; reducedCost_[ii] = dj_[ii]; element[ii] = 0.0; } columnArray_[0]->setNumElements(0); // and row djs index = rowArray_[0]->getIndices(); number = rowArray_[0]->getNumElements(); element = rowArray_[0]->denseVector(); for (i = 0; i < number; i++) { int ii = index[i]; dj_[ii+numberColumns_] += element[ii]; dual_[ii] = dj_[ii+numberColumns_]; element[ii] = 0.0; } rowArray_[0]->setNumElements(0); // check incoming CoinAssert (fabs(dj_[sequenceIn_]) < 1.0e-1); } // if stable replace in basis // If gub or odd then alpha and pivotRow may change int updateType = 0; int updateStatus = matrix_->generalExpanded(this, 3, updateType); if (updateType >= 0) updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_, (moreSpecialOptions_ & 16) != 0); // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { returnCode = -3; } } else if (updateStatus == 2) { // major error // better to have small tolerance even if slower factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15)); int maxFactor = factorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); } // later we may need to unwind more e.g. fake bounds if(lastGoodIteration_ != numberIterations_) { clearAll(); pivotRow_ = -1; if (solveType_ == 1 || (moreSpecialOptions_ & 512) != 0) { returnCode = -4; break; } else { // user in charge - re-factorize int lastCleaned = 0; ClpSimplexProgress dummyProgress; if (saveStatus_) statusOfProblemInPrimal(lastCleaned, 1, &dummyProgress, true, ifValuesPass); else statusOfProblemInPrimal(lastCleaned, 0, &dummyProgress, true, ifValuesPass); roundAgain = true; continue; } } else { // need to reject something if (solveType_ == 1) { char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); progress_.clearBadTimes(); } lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; sequenceOut_ = -1; returnCode = -5; break; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); returnCode = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } // here do part of steepest - ready for next iteration if (!ifValuesPass) primalColumnPivot_->updateWeights(rowArray_[1]); } else { if (pivotRow_ == -1) { // no outgoing row is valid if (valueOut_ != COIN_DBL_MAX) { double objectiveChange = 0.0; theta_ = valueOut_ - valueIn_; updatePrimalsInPrimal(rowArray_[1], theta_, objectiveChange, ifValuesPass); solution_[sequenceIn_] += theta_; } rowArray_[0]->clear(); #ifdef CLP_USER_DRIVEN1 /* Note if valueOut_ < COIN_DBL_MAX and theta_ reasonable then this may be a valid sub flip */ if(!userChoiceValid2(this)) { if (factorization_->pivots()<5) { // flag variable char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); progress_.clearBadTimes(); roundAgain = true; continue; } else { // try refactorizing first returnCode = 4; //say looks odd but has iterated break; } } #endif if (!factorization_->pivots() && acceptablePivot_ <= 1.0e-8 ) { returnCode = 2; //say looks unbounded // do ray if (!nonLinearCost_->sumInfeasibilities()) primalRay(rowArray_[1]); } else if (solveType_ == 2 && (moreSpecialOptions_ & 512) == 0) { // refactorize int lastCleaned = 0; ClpSimplexProgress dummyProgress; if (saveStatus_) statusOfProblemInPrimal(lastCleaned, 1, &dummyProgress, true, ifValuesPass); else statusOfProblemInPrimal(lastCleaned, 0, &dummyProgress, true, ifValuesPass); roundAgain = true; continue; } else { acceptablePivot_ = 1.0e-8; returnCode = 4; //say looks unbounded but has iterated } break; } else { // flipping from bound to bound } } double oldCost = 0.0; if (sequenceOut_ >= 0) oldCost = cost_[sequenceOut_]; // update primal solution double objectiveChange = 0.0; // after this rowArray_[1] is not empty - used to update djs // If pivot row >= numberRows then may be gub int savePivot = pivotRow_; if (pivotRow_ >= numberRows_) pivotRow_ = -1; #ifdef CLP_USER_DRIVEN if (theta_<0.0) { if (theta_>=-1.0e-12) theta_=0.0; //else //printf("negative theta %g\n",theta_); } #endif updatePrimalsInPrimal(rowArray_[1], theta_, objectiveChange, ifValuesPass); pivotRow_ = savePivot; double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ -= fabs(theta_); } else { valueIn_ = lowerIn_; } } else { // as if from lower bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ += fabs(theta_); } else { valueIn_ = upperIn_; } } objectiveChange += dualIn_ * (valueIn_ - oldValue); // outgoing if (sequenceIn_ != sequenceOut_) { if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } if(valueOut_ < lower_[sequenceOut_] - primalTolerance_) valueOut_ = lower_[sequenceOut_] - 0.9 * primalTolerance_; else if (valueOut_ > upper_[sequenceOut_] + primalTolerance_) valueOut_ = upper_[sequenceOut_] + 0.9 * primalTolerance_; // may not be exactly at bound and bounds may have changed // Make sure outgoing looks feasible directionOut_ = nonLinearCost_->setOneOutgoing(sequenceOut_, valueOut_); // May have got inaccurate //if (oldCost!=cost_[sequenceOut_]) //printf("costchange on %d from %g to %g\n",sequenceOut_, // oldCost,cost_[sequenceOut_]); if (solveType_ < 2) dj_[sequenceOut_] = cost_[sequenceOut_] - oldCost; // normally updated next iteration solution_[sequenceOut_] = valueOut_; } // change cost and bounds on incoming if primal nonLinearCost_->setOne(sequenceIn_, valueIn_); int whatNext = housekeeping(objectiveChange); //nonLinearCost_->validate(); #if CLP_DEBUG >1 { double sum; int ninf = matrix_->checkFeasible(this, sum); if (ninf) printf("infeas %d\n", ninf); } #endif if (whatNext == 1) { returnCode = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent returnCode = 3; } else if(numberIterations_ == lastGoodIteration_ + 2 * factorization_->maximumPivots()) { // done a lot of flips - be safe returnCode = -2; // refactorize } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 3; } } } if ((solveType_ == 2 && (moreSpecialOptions_ & 512) == 0) && (returnCode == -2 || returnCode == -3)) { // refactorize here int lastCleaned = 0; ClpSimplexProgress dummyProgress; if (saveStatus_) statusOfProblemInPrimal(lastCleaned, 1, &dummyProgress, true, ifValuesPass); else statusOfProblemInPrimal(lastCleaned, 0, &dummyProgress, true, ifValuesPass); if (problemStatus_ == 5) { COIN_DETAIL_PRINT(printf("Singular basis\n")); problemStatus_ = -1; returnCode = 5; } } #ifdef CLP_DEBUG { int i; // not [1] as may have information for (i = 0; i < 4; i++) { if (i != 1) rowArray_[i]->checkClear(); } for (i = 0; i < 2; i++) { columnArray_[i]->checkClear(); } } #endif return returnCode; } // Create primal ray void ClpSimplexPrimal::primalRay(CoinIndexedVector * rowArray) { delete [] ray_; ray_ = new double [numberColumns_]; CoinZeroN(ray_, numberColumns_); int number = rowArray->getNumElements(); int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); double way = -directionIn_; int i; double zeroTolerance = 1.0e-12; if (sequenceIn_ < numberColumns_) ray_[sequenceIn_] = directionIn_; if (!rowArray->packedMode()) { for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; double arrayValue = array[iRow]; if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance) ray_[iPivot] = way * arrayValue; } } else { for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; double arrayValue = array[i]; if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance) ray_[iPivot] = way * arrayValue; } } } /* Get next superbasic -1 if none, Normal type is 1 If type is 3 then initializes sorted list if 2 uses list. */ int ClpSimplexPrimal::nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray) { int returnValue = -1; bool finished = false; while (!finished) { returnValue = firstFree_; int iColumn = firstFree_ + 1; if (superBasicType > 1) { if (superBasicType > 2) { // Initialize list // Wild guess that lower bound more natural than upper int number = 0; double * work = columnArray->denseVector(); int * which = columnArray->getIndices(); for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (getStatus(iColumn) == superBasic) { if (fabs(solution_[iColumn] - lower_[iColumn]) <= primalTolerance_) { solution_[iColumn] = lower_[iColumn]; setStatus(iColumn, atLowerBound); } else if (fabs(solution_[iColumn] - upper_[iColumn]) <= primalTolerance_) { solution_[iColumn] = upper_[iColumn]; setStatus(iColumn, atUpperBound); } else if (lower_[iColumn] < -1.0e20 && upper_[iColumn] > 1.0e20) { setStatus(iColumn, isFree); break; } else if (!flagged(iColumn)) { // put ones near bounds at end after sorting work[number] = - CoinMin(0.1 * (solution_[iColumn] - lower_[iColumn]), upper_[iColumn] - solution_[iColumn]); which[number++] = iColumn; } } } } CoinSort_2(work, work + number, which); columnArray->setNumElements(number); CoinZeroN(work, number); } int * which = columnArray->getIndices(); int number = columnArray->getNumElements(); if (!number) { // finished iColumn = numberRows_ + numberColumns_; returnValue = -1; } else { number--; returnValue = which[number]; iColumn = returnValue; columnArray->setNumElements(number); } } else { for (; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (getStatus(iColumn) == superBasic) { if (fabs(solution_[iColumn] - lower_[iColumn]) <= primalTolerance_) { solution_[iColumn] = lower_[iColumn]; setStatus(iColumn, atLowerBound); } else if (fabs(solution_[iColumn] - upper_[iColumn]) <= primalTolerance_) { solution_[iColumn] = upper_[iColumn]; setStatus(iColumn, atUpperBound); } else if (lower_[iColumn] < -1.0e20 && upper_[iColumn] > 1.0e20) { setStatus(iColumn, isFree); if (fabs(dj_[iColumn])>dualTolerance_) break; } else { break; } } } } } firstFree_ = iColumn; finished = true; if (firstFree_ == numberRows_ + numberColumns_) firstFree_ = -1; if (returnValue >= 0 && getStatus(returnValue) != superBasic && getStatus(returnValue) != isFree) finished = false; // somehow picked up odd one } return returnValue; } void ClpSimplexPrimal::clearAll() { // Clean up any gub stuff matrix_->extendUpdated(this, rowArray_[1], 1); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; clearActive(iRow); } rowArray_[1]->clear(); // make sure any gub sets are clean matrix_->generalExpanded(this, 11, sequenceIn_); } // Sort of lexicographic resolve int ClpSimplexPrimal::lexSolve() { algorithm_ = +1; //specialOptions_ |= 4; // save data ClpDataSave data = saveData(); matrix_->refresh(this); // make sure matrix okay // Save so can see if doing after dual int initialStatus = problemStatus_; int initialIterations = numberIterations_; int initialNegDjs = -1; // initialize - maybe values pass and algorithm_ is +1 int ifValuesPass = 0; #if 0 // if so - put in any superbasic costed slacks // Start can skip some things in transposeTimes specialOptions_ |= 131072; if (ifValuesPass && specialOptions_ < 0x01000000) { // Get column copy const CoinPackedMatrix * columnCopy = matrix(); const int * row = columnCopy->getIndices(); const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); const int * columnLength = columnCopy->getVectorLengths(); //const double * element = columnCopy->getElements(); int n = 0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLength[iColumn] == 1) { Status status = getColumnStatus(iColumn); if (status != basic && status != isFree) { double value = columnActivity_[iColumn]; if (fabs(value - columnLower_[iColumn]) > primalTolerance_ && fabs(value - columnUpper_[iColumn]) > primalTolerance_) { int iRow = row[columnStart[iColumn]]; if (getRowStatus(iRow) == basic) { setRowStatus(iRow, superBasic); setColumnStatus(iColumn, basic); n++; } } } } } printf("%d costed slacks put in basis\n", n); } #endif double * originalCost = NULL; double * originalLower = NULL; double * originalUpper = NULL; if (!startup(0, 0)) { // Set average theta nonLinearCost_->setAverageTheta(1.0e3); int lastCleaned = 0; // last time objective or bounds cleaned up // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // This says whether to restore things etc int factorType = 0; if (problemStatus_ < 0 && perturbation_ < 100) { perturb(0); // Can't get here if values pass assert (!ifValuesPass); gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } ClpSimplex * saveModel = NULL; int stopSprint = -1; int sprintPass = 0; int reasonableSprintIteration = 0; int lastSprintIteration = 0; double lastObjectiveValue = COIN_DBL_MAX; // Start check for cycles progress_.fillFromModel(this); progress_.startCheck(); /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible -5 - looks unbounded */ originalCost = CoinCopyOfArray(cost_, numberColumns_ + numberRows_); originalLower = CoinCopyOfArray(lower_, numberColumns_ + numberRows_); originalUpper = CoinCopyOfArray(upper_, numberColumns_ + numberRows_); while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick #if 1 if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (specialOptions_ & 4) == 0 && initialStatus != 10) { perturb(1); matrix_->rhsOffset(this, true, false); } #endif // If we have done no iterations - special if (lastGoodIteration_ == numberIterations_ && factorType) factorType = 3; if (saveModel) { // Doing sprint if (sequenceIn_ < 0 || numberIterations_ >= stopSprint) { problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; if (sequenceIn_ < 0 && numberIterations_ < reasonableSprintIteration && sprintPass > 100) primalColumnPivot_->switchOffSprint(); //lastSprintIteration=numberIterations_; COIN_DETAIL_PRINT(printf("End small model\n")); } } // may factorize, checks if problem finished statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); if (initialStatus == 10) { // cleanup phase if(initialIterations != numberIterations_) { if (numberDualInfeasibilities_ > 10000 && numberDualInfeasibilities_ > 10 * initialNegDjs) { // getting worse - try perturbing if (perturbation_ < 101 && (specialOptions_ & 4) == 0) { perturb(1); matrix_->rhsOffset(this, true, false); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } } } else { // save number of negative djs if (!numberPrimalInfeasibilities_) initialNegDjs = numberDualInfeasibilities_; // make sure weight won't be changed if (infeasibilityCost_ == 1.0e10) infeasibilityCost_ = 1.000001e10; } } // See if sprint says redo because of problems if (numberDualInfeasibilities_ == -776) { // Need new set of variables problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; //lastSprintIteration=numberIterations_; COIN_DETAIL_PRINT(printf("End small model after\n")); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } int numberSprintIterations = 0; int numberSprintColumns = primalColumnPivot_->numberSprintColumns(numberSprintIterations); if (problemStatus_ == 777) { // problems so do one pass with normal problemStatus_ = -1; originalModel(saveModel); saveModel = NULL; // Skip factorization //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,false,saveModel); statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, ifValuesPass, saveModel); } else if (problemStatus_ < 0 && !saveModel && numberSprintColumns && firstFree_ < 0) { int numberSort = 0; int numberFixed = 0; int numberBasic = 0; reasonableSprintIteration = numberIterations_ + 100; int * whichColumns = new int[numberColumns_]; double * weight = new double[numberColumns_]; int numberNegative = 0; double sumNegative = 0.0; // now massage weight so all basic in plus good djs for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double dj = dj_[iColumn]; switch(getColumnStatus(iColumn)) { case basic: dj = -1.0e50; numberBasic++; break; case atUpperBound: dj = -dj; break; case isFixed: dj = 1.0e50; numberFixed++; break; case atLowerBound: dj = dj; break; case isFree: dj = -100.0 * fabs(dj); break; case superBasic: dj = -100.0 * fabs(dj); break; } if (dj < -dualTolerance_ && dj > -1.0e50) { numberNegative++; sumNegative -= dj; } weight[iColumn] = dj; whichColumns[iColumn] = iColumn; } handler_->message(CLP_SPRINT, messages_) << sprintPass << numberIterations_ - lastSprintIteration << objectiveValue() << sumNegative << numberNegative << CoinMessageEol; sprintPass++; lastSprintIteration = numberIterations_; if (objectiveValue()*optimizationDirection_ > lastObjectiveValue - 1.0e-7 && sprintPass > 5) { // switch off COIN_DETAIL_PRINT(printf("Switching off sprint\n")); primalColumnPivot_->switchOffSprint(); } else { lastObjectiveValue = objectiveValue() * optimizationDirection_; // sort CoinSort_2(weight, weight + numberColumns_, whichColumns); numberSort = CoinMin(numberColumns_ - numberFixed, numberBasic + numberSprintColumns); // Sort to make consistent ? std::sort(whichColumns, whichColumns + numberSort); saveModel = new ClpSimplex(this, numberSort, whichColumns); delete [] whichColumns; delete [] weight; // Skip factorization //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,false,saveModel); //statusOfProblemInPrimal(lastCleaned,factorType,&progress_,true,saveModel); stopSprint = numberIterations_ + numberSprintIterations; COIN_DETAIL_PRINT(printf("Sprint with %d columns for %d iterations\n", numberSprintColumns, numberSprintIterations)); } } // Say good factorization factorType = 1; // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // exit if victory declared if (problemStatus_ >= 0) { if (originalCost) { // find number nonbasic with zero reduced costs int numberDegen = 0; int numberTotal = numberColumns_; //+numberRows_; for (int i = 0; i < numberTotal; i++) { cost_[i] = 0.0; if (getStatus(i) == atLowerBound) { if (dj_[i] <= dualTolerance_) { cost_[i] = numberTotal - i + randomNumberGenerator_.randomDouble() * 0.5; numberDegen++; } else { // fix cost_[i] = 1.0e10; //upper_[i]=lower_[i]; } } else if (getStatus(i) == atUpperBound) { if (dj_[i] >= -dualTolerance_) { cost_[i] = (numberTotal - i) + randomNumberGenerator_.randomDouble() * 0.5; numberDegen++; } else { // fix cost_[i] = -1.0e10; //lower_[i]=upper_[i]; } } else if (getStatus(i) == basic) { cost_[i] = (numberTotal - i) + randomNumberGenerator_.randomDouble() * 0.5; } } problemStatus_ = -1; lastObjectiveValue = COIN_DBL_MAX; // Start check for cycles progress_.fillFromModel(this); progress_.startCheck(); COIN_DETAIL_PRINT(printf("%d degenerate after %d iterations\n", numberDegen, numberIterations_)); if (!numberDegen) { CoinMemcpyN(originalCost, numberTotal, cost_); delete [] originalCost; originalCost = NULL; CoinMemcpyN(originalLower, numberTotal, lower_); delete [] originalLower; CoinMemcpyN(originalUpper, numberTotal, upper_); delete [] originalUpper; } delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); progress_.endOddState(); continue; } else { COIN_DETAIL_PRINT(printf("exiting after %d iterations\n", numberIterations_)); break; } } // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && firstFree_ < 0)) { problemStatus_ = 3; break; } if (firstFree_ < 0) { if (ifValuesPass) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Iterate whileIterating(ifValuesPass ? 1 : 0); } } assert (!originalCost); // if infeasible get real values //printf("XXXXY final cost %g\n",infeasibilityCost_); progress_.initialWeight_ = 0.0; if (problemStatus_ == 1 && secondaryStatus_ != 6) { infeasibilityCost_ = 0.0; createRim(1 + 4); nonLinearCost_->checkInfeasibilities(0.0); sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities(); numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); // and get good feasible duals computeDuals(NULL); } // Stop can skip some things in transposeTimes specialOptions_ &= ~131072; // clean up unflag(); finish(0); restoreData(data); return problemStatus_; } Clp-1.15.10/src/ClpModel.cpp0000644000076600007660000052203312372677302014063 0ustar coincoin/* $Id: ClpModel.cpp 2045 2014-08-13 15:05:38Z 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 #include #include /* CLP_NO_VECTOR There's no hint of the motivation for this, so here's a bit of speculation. CLP_NO_VECTOR excises CoinPackedVector from the code. Looking over affected code here, and the much more numerous occurrences of affected code in CoinUtils, it looks to be an efficiency issue. One good example is CoinPackedMatrix.isEquivalent. The default version tests equivalence of major dimension vectors by retrieving them as CPVs and invoking CPV.isEquivalent. As pointed out in the documention, CPV.isEquivalent implicitly sorts the nonzeros of each vector (insertion in a map) prior to comparison. As a one-off, this is arguably more efficient than allocating and clearing a full vector, then dropping in the nonzeros, then checking against the second vector (in fact, this is the algorithm for testing a packed vector against a full vector). In CPM.isEquivalent, we have a whole sequence of vectors to compare. Better to allocate a full vector sized to match, clear it (one time cost), then edit nonzeros in and out while doing comparisons. The cost of allocating and clearing the full vector is amortised over all columns. */ #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "ClpModel.hpp" #include "ClpEventHandler.hpp" #include "ClpPackedMatrix.hpp" #ifndef SLIM_CLP #include "ClpPlusMinusOneMatrix.hpp" #endif #ifndef CLP_NO_VECTOR #include "CoinPackedVector.hpp" #endif #include "CoinIndexedVector.hpp" #if SLIM_CLP==2 #define SLIM_NOIO #endif #ifndef SLIM_NOIO #include "CoinMpsIO.hpp" #include "CoinFileIO.hpp" #include "CoinModel.hpp" #endif #include "ClpMessage.hpp" #include "CoinMessage.hpp" #include "ClpLinearObjective.hpp" #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" #include "CoinBuild.hpp" #endif //############################################################################# ClpModel::ClpModel (bool emptyMessages) : optimizationDirection_(1), objectiveValue_(0.0), smallElement_(1.0e-20), objectiveScale_(1.0), rhsScale_(1.0), numberRows_(0), numberColumns_(0), rowActivity_(NULL), columnActivity_(NULL), dual_(NULL), reducedCost_(NULL), rowLower_(NULL), rowUpper_(NULL), objective_(NULL), rowObjective_(NULL), columnLower_(NULL), columnUpper_(NULL), matrix_(NULL), rowCopy_(NULL), scaledMatrix_(NULL), ray_(NULL), rowScale_(NULL), columnScale_(NULL), inverseRowScale_(NULL), inverseColumnScale_(NULL), scalingFlag_(3), status_(NULL), integerType_(NULL), userPointer_(NULL), trustedUserPointer_(NULL), numberIterations_(0), solveType_(0), whatsChanged_(0), problemStatus_(-1), secondaryStatus_(0), lengthNames_(0), numberThreads_(0), specialOptions_(0), #ifndef CLP_NO_STD defaultHandler_(true), rowNames_(), columnNames_(), #else defaultHandler_(true), #endif maximumColumns_(-1), maximumRows_(-1), maximumInternalColumns_(-1), maximumInternalRows_(-1), savedRowScale_(NULL), savedColumnScale_(NULL) { intParam_[ClpMaxNumIteration] = 2147483647; intParam_[ClpMaxNumIterationHotStart] = 9999999; intParam_[ClpNameDiscipline] = 1; dblParam_[ClpDualObjectiveLimit] = COIN_DBL_MAX; dblParam_[ClpPrimalObjectiveLimit] = COIN_DBL_MAX; dblParam_[ClpDualTolerance] = 1e-7; dblParam_[ClpPrimalTolerance] = 1e-7; dblParam_[ClpObjOffset] = 0.0; dblParam_[ClpMaxSeconds] = -1.0; dblParam_[ClpMaxWallSeconds] = -1.0; dblParam_[ClpPresolveTolerance] = 1.0e-8; #ifndef CLP_NO_STD strParam_[ClpProbName] = "ClpDefaultName"; #endif handler_ = new CoinMessageHandler(); handler_->setLogLevel(1); eventHandler_ = new ClpEventHandler(); if (!emptyMessages) { messages_ = ClpMessage(); coinMessages_ = CoinMessage(); } randomNumberGenerator_.setSeed(1234567); } //----------------------------------------------------------------------------- ClpModel::~ClpModel () { if (defaultHandler_) { delete handler_; handler_ = NULL; } gutsOfDelete(0); } // Does most of deletion (0 = all, 1 = most) void ClpModel::gutsOfDelete(int type) { if (!type || !permanentArrays()) { maximumRows_ = -1; maximumColumns_ = -1; delete [] rowActivity_; rowActivity_ = NULL; delete [] columnActivity_; columnActivity_ = NULL; delete [] dual_; dual_ = NULL; delete [] reducedCost_; reducedCost_ = NULL; delete [] rowLower_; delete [] rowUpper_; delete [] rowObjective_; rowLower_ = NULL; rowUpper_ = NULL; rowObjective_ = NULL; delete [] columnLower_; delete [] columnUpper_; delete objective_; columnLower_ = NULL; columnUpper_ = NULL; objective_ = NULL; delete [] savedRowScale_; if (rowScale_ == savedRowScale_) rowScale_ = NULL; savedRowScale_ = NULL; delete [] savedColumnScale_; if (columnScale_ == savedColumnScale_) columnScale_ = NULL; savedColumnScale_ = NULL; delete [] rowScale_; rowScale_ = NULL; delete [] columnScale_; columnScale_ = NULL; delete [] integerType_; integerType_ = NULL; delete [] status_; status_ = NULL; delete eventHandler_; eventHandler_ = NULL; } whatsChanged_ = 0; delete matrix_; matrix_ = NULL; delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL, delete [] ray_; ray_ = NULL; specialOptions_ = 0; } void ClpModel::setRowScale(double * scale) { if (!savedRowScale_) { delete [] reinterpret_cast (rowScale_); rowScale_ = scale; } else { assert (!scale); rowScale_ = NULL; } } void ClpModel::setColumnScale(double * scale) { if (!savedColumnScale_) { delete [] reinterpret_cast (columnScale_); columnScale_ = scale; } else { assert (!scale); columnScale_ = NULL; } } //############################################################################# void ClpModel::setPrimalTolerance( double value) { if (value > 0.0 && value < 1.0e10) dblParam_[ClpPrimalTolerance] = value; } void ClpModel::setDualTolerance( double value) { if (value > 0.0 && value < 1.0e10) dblParam_[ClpDualTolerance] = value; } void ClpModel::setOptimizationDirection( double value) { optimizationDirection_ = value; } void ClpModel::gutsOfLoadModel (int numberRows, int numberColumns, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { // save event handler in case already set ClpEventHandler * handler = eventHandler_->clone(); // Save specialOptions int saveOptions = specialOptions_; gutsOfDelete(0); specialOptions_ = saveOptions; eventHandler_ = handler; numberRows_ = numberRows; numberColumns_ = numberColumns; rowActivity_ = new double[numberRows_]; columnActivity_ = new double[numberColumns_]; dual_ = new double[numberRows_]; reducedCost_ = new double[numberColumns_]; CoinZeroN(dual_, numberRows_); CoinZeroN(reducedCost_, numberColumns_); int iRow, iColumn; rowLower_ = ClpCopyOfArray(rowlb, numberRows_, -COIN_DBL_MAX); rowUpper_ = ClpCopyOfArray(rowub, numberRows_, COIN_DBL_MAX); double * objective = ClpCopyOfArray(obj, numberColumns_, 0.0); objective_ = new ClpLinearObjective(objective, numberColumns_); delete [] objective; rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_); columnLower_ = ClpCopyOfArray(collb, numberColumns_, 0.0); columnUpper_ = ClpCopyOfArray(colub, numberColumns_, COIN_DBL_MAX); // set default solution and clean bounds for (iRow = 0; iRow < numberRows_; iRow++) { if (rowLower_[iRow] > 0.0) { rowActivity_[iRow] = rowLower_[iRow]; } else if (rowUpper_[iRow] < 0.0) { rowActivity_[iRow] = rowUpper_[iRow]; } else { rowActivity_[iRow] = 0.0; } if (rowLower_[iRow] < -1.0e27) rowLower_[iRow] = -COIN_DBL_MAX; if (rowUpper_[iRow] > 1.0e27) rowUpper_[iRow] = COIN_DBL_MAX; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLower_[iColumn] > 0.0) { columnActivity_[iColumn] = columnLower_[iColumn]; } else if (columnUpper_[iColumn] < 0.0) { columnActivity_[iColumn] = columnUpper_[iColumn]; } else { columnActivity_[iColumn] = 0.0; } if (columnLower_[iColumn] < -1.0e27) columnLower_[iColumn] = -COIN_DBL_MAX; if (columnUpper_[iColumn] > 1.0e27) columnUpper_[iColumn] = COIN_DBL_MAX; } } // This just loads up a row objective void ClpModel::setRowObjective(const double * rowObjective) { delete [] rowObjective_; rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_); whatsChanged_ = 0; } void ClpModel::loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(), collb, colub, obj, rowlb, rowub, rowObjective); if (matrix.isColOrdered()) { matrix_ = matrix.clone(); } else { // later may want to keep as unknown class CoinPackedMatrix matrix2; matrix2.setExtraGap(0.0); matrix2.setExtraMajor(0.0); matrix2.reverseOrderedCopyOf(*matrix.getPackedMatrix()); matrix.releasePackedMatrix(); matrix_ = new ClpPackedMatrix(matrix2); } matrix_->setDimensions(numberRows_, numberColumns_); } void ClpModel::loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); bool special = (clpMatrix) ? clpMatrix->wantsSpecialColumnCopy() : false; gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(), collb, colub, obj, rowlb, rowub, rowObjective); if (matrix.isColOrdered()) { matrix_ = new ClpPackedMatrix(matrix); if (special) { clpMatrix = static_cast< ClpPackedMatrix*>(matrix_); clpMatrix->makeSpecialColumnCopy(); } } else { CoinPackedMatrix matrix2; matrix2.setExtraGap(0.0); matrix2.setExtraMajor(0.0); matrix2.reverseOrderedCopyOf(matrix); matrix_ = new ClpPackedMatrix(matrix2); } matrix_->setDimensions(numberRows_, numberColumns_); } void ClpModel::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, const double * rowObjective) { gutsOfLoadModel(numrows, numcols, collb, colub, obj, rowlb, rowub, rowObjective); int numberElements = start ? start[numcols] : 0; CoinPackedMatrix matrix(true, numrows, numrows ? numcols : 0, numberElements, value, index, start, NULL); matrix_ = new ClpPackedMatrix(matrix); matrix_->setDimensions(numberRows_, numberColumns_); } void ClpModel::loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int* length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { gutsOfLoadModel(numrows, numcols, collb, colub, obj, rowlb, rowub, rowObjective); // Compute number of elements int numberElements = 0; int i; for (i = 0; i < numcols; i++) numberElements += length[i]; CoinPackedMatrix matrix(true, numrows, numcols, numberElements, value, index, start, length); matrix_ = new ClpPackedMatrix(matrix); } #ifndef SLIM_NOIO // This loads a model from a coinModel object - returns number of errors int ClpModel::loadProblem ( CoinModel & modelObject, bool tryPlusMinusOne) { if (modelObject.numberColumns() == 0 && modelObject.numberRows() == 0) return 0; int numberErrors = 0; // Set arrays for normal use double * rowLower = modelObject.rowLowerArray(); double * rowUpper = modelObject.rowUpperArray(); double * columnLower = modelObject.columnLowerArray(); double * columnUpper = modelObject.columnUpperArray(); double * objective = modelObject.objectiveArray(); int * integerType = modelObject.integerTypeArray(); double * associated = modelObject.associatedArray(); // If strings then do copies if (modelObject.stringsExist()) { numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper, objective, integerType, associated); } int numberRows = modelObject.numberRows(); int numberColumns = modelObject.numberColumns(); gutsOfLoadModel(numberRows, numberColumns, columnLower, columnUpper, objective, rowLower, rowUpper, NULL); setObjectiveOffset(modelObject.objectiveOffset()); CoinBigIndex * startPositive = NULL; CoinBigIndex * startNegative = NULL; delete matrix_; if (tryPlusMinusOne) { startPositive = new CoinBigIndex[numberColumns+1]; startNegative = new CoinBigIndex[numberColumns]; modelObject.countPlusMinusOne(startPositive, startNegative, associated); if (startPositive[0] < 0) { // no good tryPlusMinusOne = false; delete [] startPositive; delete [] startNegative; } } #ifndef SLIM_CLP if (!tryPlusMinusOne) { #endif CoinPackedMatrix matrix; modelObject.createPackedMatrix(matrix, associated); matrix_ = new ClpPackedMatrix(matrix); #ifndef SLIM_CLP } else { // create +-1 matrix CoinBigIndex size = startPositive[numberColumns]; int * indices = new int[size]; modelObject.createPlusMinusOne(startPositive, startNegative, indices, associated); // Get good object ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix(); matrix->passInCopy(numberRows, numberColumns, true, indices, startPositive, startNegative); matrix_ = matrix; } #endif #ifndef CLP_NO_STD // Do names if wanted int numberItems; numberItems = modelObject.rowNames()->numberItems(); if (numberItems) { const char *const * rowNames = modelObject.rowNames()->names(); copyRowNames(rowNames, 0, numberItems); } numberItems = modelObject.columnNames()->numberItems(); if (numberItems) { const char *const * columnNames = modelObject.columnNames()->names(); copyColumnNames(columnNames, 0, numberItems); } #endif // Do integers if wanted assert(integerType); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) setInteger(iColumn); } if (rowLower != modelObject.rowLowerArray() || columnLower != modelObject.columnLowerArray()) { delete [] rowLower; delete [] rowUpper; delete [] columnLower; delete [] columnUpper; delete [] objective; delete [] integerType; delete [] associated; if (numberErrors) handler_->message(CLP_BAD_STRING_VALUES, messages_) << numberErrors << CoinMessageEol; } matrix_->setDimensions(numberRows_, numberColumns_); return numberErrors; } #endif void ClpModel::getRowBound(int iRow, double& lower, double& upper) const { lower = -COIN_DBL_MAX; upper = COIN_DBL_MAX; if (rowUpper_) upper = rowUpper_[iRow]; if (rowLower_) lower = rowLower_[iRow]; } //------------------------------------------------------------------ #ifndef NDEBUG // For errors to make sure print to screen // only called in debug mode static void indexError(int index, std::string methodName) { std::cerr << "Illegal index " << index << " in ClpModel::" << methodName << std::endl; throw CoinError("Illegal index", methodName, "ClpModel"); } #endif /* Set an objective function coefficient */ void ClpModel::setObjectiveCoefficient( int elementIndex, double elementValue ) { #ifndef NDEBUG if (elementIndex < 0 || elementIndex >= numberColumns_) { indexError(elementIndex, "setObjectiveCoefficient"); } #endif objective()[elementIndex] = elementValue; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void ClpModel::setRowLower( int elementIndex, double elementValue ) { if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; rowLower_[elementIndex] = elementValue; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void ClpModel::setRowUpper( int elementIndex, double elementValue ) { if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; rowUpper_[elementIndex] = elementValue; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } /* Set a single row lower and upper bound */ void ClpModel::setRowBounds( int elementIndex, double lower, double upper ) { if (lower < -1.0e27) lower = -COIN_DBL_MAX; if (upper > 1.0e27) upper = COIN_DBL_MAX; CoinAssert (upper >= lower); rowLower_[elementIndex] = lower; rowUpper_[elementIndex] = upper; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } void ClpModel::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #ifndef NDEBUG int n = numberRows_; #endif double * lower = rowLower_; double * upper = rowUpper_; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) while (indexFirst != indexLast) { const int iRow = *indexFirst++; #ifndef NDEBUG if (iRow < 0 || iRow >= n) { indexError(iRow, "setRowSetBounds"); } #endif lower[iRow] = *boundList++; upper[iRow] = *boundList++; if (lower[iRow] < -1.0e27) lower[iRow] = -COIN_DBL_MAX; if (upper[iRow] > 1.0e27) upper[iRow] = COIN_DBL_MAX; CoinAssert (upper[iRow] >= lower[iRow]); } } //----------------------------------------------------------------------------- /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void ClpModel::setColumnLower( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; columnLower_[elementIndex] = elementValue; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void ClpModel::setColumnUpper( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; columnUpper_[elementIndex] = elementValue; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } /* Set a single column lower and upper bound */ void ClpModel::setColumnBounds( int elementIndex, double lower, double upper ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnBounds"); } #endif if (lower < -1.0e27) lower = -COIN_DBL_MAX; if (upper > 1.0e27) upper = COIN_DBL_MAX; columnLower_[elementIndex] = lower; columnUpper_[elementIndex] = upper; CoinAssert (upper >= lower); whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) } void ClpModel::setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { double * lower = columnLower_; double * upper = columnUpper_; whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep) #ifndef NDEBUG int n = numberColumns_; #endif while (indexFirst != indexLast) { const int iColumn = *indexFirst++; #ifndef NDEBUG if (iColumn < 0 || iColumn >= n) { indexError(iColumn, "setColumnSetBounds"); } #endif lower[iColumn] = *boundList++; upper[iColumn] = *boundList++; CoinAssert (upper[iColumn] >= lower[iColumn]); if (lower[iColumn] < -1.0e27) lower[iColumn] = -COIN_DBL_MAX; if (upper[iColumn] > 1.0e27) upper[iColumn] = COIN_DBL_MAX; } } //----------------------------------------------------------------------------- //############################################################################# // Copy constructor. ClpModel::ClpModel(const ClpModel &rhs, int scalingMode) : optimizationDirection_(rhs.optimizationDirection_), numberRows_(rhs.numberRows_), numberColumns_(rhs.numberColumns_), specialOptions_(rhs.specialOptions_), maximumColumns_(-1), maximumRows_(-1), maximumInternalColumns_(-1), maximumInternalRows_(-1), savedRowScale_(NULL), savedColumnScale_(NULL) { gutsOfCopy(rhs); if (scalingMode >= 0 && matrix_ && matrix_->allElementsInRange(this, smallElement_, 1.0e20)) { // really do scaling scalingFlag_ = scalingMode; setRowScale(NULL); setColumnScale(NULL); delete rowCopy_; // in case odd rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; if (scalingMode && !matrix_->scale(this)) { // scaling worked - now apply inverseRowScale_ = rowScale_ + numberRows_; inverseColumnScale_ = columnScale_ + numberColumns_; gutsOfScaling(); // pretend not scaled scalingFlag_ = -scalingFlag_; } else { // not scaled scalingFlag_ = 0; } } //randomNumberGenerator_.setSeed(1234567); } // Assignment operator. This copies the data ClpModel & ClpModel::operator=(const ClpModel & rhs) { if (this != &rhs) { if (defaultHandler_) { //delete handler_; //handler_ = NULL; } gutsOfDelete(1); optimizationDirection_ = rhs.optimizationDirection_; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; gutsOfCopy(rhs, -1); } return *this; } /* Does most of copying If trueCopy 0 then just points to arrays If -1 leaves as much as possible */ void ClpModel::gutsOfCopy(const ClpModel & rhs, int trueCopy) { defaultHandler_ = rhs.defaultHandler_; randomNumberGenerator_ = rhs.randomNumberGenerator_; if (trueCopy >= 0) { if (defaultHandler_) handler_ = new CoinMessageHandler(*rhs.handler_); else handler_ = rhs.handler_; eventHandler_ = rhs.eventHandler_->clone(); messages_ = rhs.messages_; coinMessages_ = rhs.coinMessages_; } else { if (!eventHandler_ && rhs.eventHandler_) eventHandler_ = rhs.eventHandler_->clone(); } intParam_[ClpMaxNumIteration] = rhs.intParam_[ClpMaxNumIteration]; intParam_[ClpMaxNumIterationHotStart] = rhs.intParam_[ClpMaxNumIterationHotStart]; intParam_[ClpNameDiscipline] = rhs.intParam_[ClpNameDiscipline] ; dblParam_[ClpDualObjectiveLimit] = rhs.dblParam_[ClpDualObjectiveLimit]; dblParam_[ClpPrimalObjectiveLimit] = rhs.dblParam_[ClpPrimalObjectiveLimit]; dblParam_[ClpDualTolerance] = rhs.dblParam_[ClpDualTolerance]; dblParam_[ClpPrimalTolerance] = rhs.dblParam_[ClpPrimalTolerance]; dblParam_[ClpObjOffset] = rhs.dblParam_[ClpObjOffset]; dblParam_[ClpMaxSeconds] = rhs.dblParam_[ClpMaxSeconds]; dblParam_[ClpMaxWallSeconds] = rhs.dblParam_[ClpMaxWallSeconds]; dblParam_[ClpPresolveTolerance] = rhs.dblParam_[ClpPresolveTolerance]; #ifndef CLP_NO_STD strParam_[ClpProbName] = rhs.strParam_[ClpProbName]; #endif optimizationDirection_ = rhs.optimizationDirection_; objectiveValue_ = rhs.objectiveValue_; smallElement_ = rhs.smallElement_; objectiveScale_ = rhs.objectiveScale_; rhsScale_ = rhs.rhsScale_; numberIterations_ = rhs.numberIterations_; solveType_ = rhs.solveType_; whatsChanged_ = rhs.whatsChanged_; problemStatus_ = rhs.problemStatus_; secondaryStatus_ = rhs.secondaryStatus_; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; userPointer_ = rhs.userPointer_; trustedUserPointer_ = rhs.trustedUserPointer_; scalingFlag_ = rhs.scalingFlag_; specialOptions_ = rhs.specialOptions_; if (trueCopy) { #ifndef CLP_NO_STD lengthNames_ = rhs.lengthNames_; if (lengthNames_) { rowNames_ = rhs.rowNames_; columnNames_ = rhs.columnNames_; } #endif numberThreads_ = rhs.numberThreads_; if (maximumRows_ < 0) { specialOptions_ &= ~65536; savedRowScale_ = NULL; savedColumnScale_ = NULL; integerType_ = CoinCopyOfArray(rhs.integerType_, numberColumns_); rowActivity_ = ClpCopyOfArray(rhs.rowActivity_, numberRows_); columnActivity_ = ClpCopyOfArray(rhs.columnActivity_, numberColumns_); dual_ = ClpCopyOfArray(rhs.dual_, numberRows_); reducedCost_ = ClpCopyOfArray(rhs.reducedCost_, numberColumns_); rowLower_ = ClpCopyOfArray ( rhs.rowLower_, numberRows_ ); rowUpper_ = ClpCopyOfArray ( rhs.rowUpper_, numberRows_ ); columnLower_ = ClpCopyOfArray ( rhs.columnLower_, numberColumns_ ); columnUpper_ = ClpCopyOfArray ( rhs.columnUpper_, numberColumns_ ); rowScale_ = ClpCopyOfArray(rhs.rowScale_, numberRows_ * 2); columnScale_ = ClpCopyOfArray(rhs.columnScale_, numberColumns_ * 2); if (rhs.objective_) objective_ = rhs.objective_->clone(); else objective_ = NULL; rowObjective_ = ClpCopyOfArray ( rhs.rowObjective_, numberRows_ ); status_ = ClpCopyOfArray( rhs.status_, numberColumns_ + numberRows_); ray_ = NULL; if (problemStatus_ == 1) ray_ = ClpCopyOfArray (rhs.ray_, numberRows_); else if (problemStatus_ == 2) ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_); if (rhs.rowCopy_) { rowCopy_ = rhs.rowCopy_->clone(); } else { rowCopy_ = NULL; } if (rhs.scaledMatrix_) { scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_); } else { scaledMatrix_ = NULL; } matrix_ = NULL; if (rhs.matrix_) { matrix_ = rhs.matrix_->clone(); } } else { // This already has arrays - just copy savedRowScale_ = NULL; savedColumnScale_ = NULL; startPermanentArrays(); if (rhs.integerType_) { assert (integerType_); ClpDisjointCopyN(rhs.integerType_, numberColumns_, integerType_); } else { integerType_ = NULL; } if (rhs.rowActivity_) { ClpDisjointCopyN ( rhs.rowActivity_, numberRows_ , rowActivity_); ClpDisjointCopyN ( rhs.columnActivity_, numberColumns_ , columnActivity_); ClpDisjointCopyN ( rhs.dual_, numberRows_ , dual_); ClpDisjointCopyN ( rhs.reducedCost_, numberColumns_ , reducedCost_); } else { rowActivity_ = NULL; columnActivity_ = NULL; dual_ = NULL; reducedCost_ = NULL; } ClpDisjointCopyN ( rhs.rowLower_, numberRows_, rowLower_ ); ClpDisjointCopyN ( rhs.rowUpper_, numberRows_, rowUpper_ ); ClpDisjointCopyN ( rhs.columnLower_, numberColumns_, columnLower_ ); assert ((specialOptions_ & 131072) == 0); abort(); ClpDisjointCopyN ( rhs.columnUpper_, numberColumns_, columnUpper_ ); if (rhs.objective_) { abort(); //check if same objective_ = rhs.objective_->clone(); } else { objective_ = NULL; } assert (!rhs.rowObjective_); ClpDisjointCopyN( rhs.status_, numberColumns_ + numberRows_, status_); ray_ = NULL; if (problemStatus_ == 1) ray_ = ClpCopyOfArray (rhs.ray_, numberRows_); else if (problemStatus_ == 2) ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_); assert (!ray_); delete rowCopy_; if (rhs.rowCopy_) { rowCopy_ = rhs.rowCopy_->clone(); } else { rowCopy_ = NULL; } delete scaledMatrix_; if (rhs.scaledMatrix_) { scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_); } else { scaledMatrix_ = NULL; } delete matrix_; matrix_ = NULL; if (rhs.matrix_) { matrix_ = rhs.matrix_->clone(); } if (rhs.savedRowScale_) { assert (savedRowScale_); assert (!rowScale_); ClpDisjointCopyN(rhs.savedRowScale_, 4 * maximumInternalRows_, savedRowScale_); ClpDisjointCopyN(rhs.savedColumnScale_, 4 * maximumInternalColumns_, savedColumnScale_); } else { assert (!savedRowScale_); if (rowScale_) { ClpDisjointCopyN(rhs.rowScale_, numberRows_, rowScale_); ClpDisjointCopyN(rhs.columnScale_, numberColumns_, columnScale_); } else { rowScale_ = NULL; columnScale_ = NULL; } } abort(); // look at resizeDouble and resize } } else { savedRowScale_ = rhs.savedRowScale_; assert (!savedRowScale_); savedColumnScale_ = rhs.savedColumnScale_; rowActivity_ = rhs.rowActivity_; columnActivity_ = rhs.columnActivity_; dual_ = rhs.dual_; reducedCost_ = rhs.reducedCost_; rowLower_ = rhs.rowLower_; rowUpper_ = rhs.rowUpper_; objective_ = rhs.objective_; rowObjective_ = rhs.rowObjective_; columnLower_ = rhs.columnLower_; columnUpper_ = rhs.columnUpper_; matrix_ = rhs.matrix_; rowCopy_ = NULL; scaledMatrix_ = NULL; ray_ = rhs.ray_; //rowScale_ = rhs.rowScale_; //columnScale_ = rhs.columnScale_; lengthNames_ = 0; numberThreads_ = rhs.numberThreads_; #ifndef CLP_NO_STD rowNames_ = std::vector (); columnNames_ = std::vector (); #endif integerType_ = NULL; status_ = rhs.status_; } inverseRowScale_ = NULL; inverseColumnScale_ = NULL; } // Copy contents - resizing if necessary - otherwise re-use memory void ClpModel::copy(const ClpMatrixBase * from, ClpMatrixBase * & to) { assert (from); const ClpPackedMatrix * matrixFrom = (dynamic_cast(from)); ClpPackedMatrix * matrixTo = (dynamic_cast< ClpPackedMatrix*>(to)); if (matrixFrom && matrixTo) { matrixTo->copy(matrixFrom); } else { delete to; to = from->clone(); } #if 0 delete modelPtr_->matrix_; if (continuousModel_->matrix_) { modelPtr_->matrix_ = continuousModel_->matrix_->clone(); } else { modelPtr_->matrix_ = NULL; } #endif } /* Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm */ void ClpModel::borrowModel(ClpModel & rhs) { if (defaultHandler_) { delete handler_; handler_ = NULL; } gutsOfDelete(1); optimizationDirection_ = rhs.optimizationDirection_; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; delete [] rhs.ray_; rhs.ray_ = NULL; // make sure scaled matrix not copied ClpPackedMatrix * save = rhs.scaledMatrix_; rhs.scaledMatrix_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; gutsOfCopy(rhs, 0); rhs.scaledMatrix_ = save; specialOptions_ = rhs.specialOptions_ & ~65536; savedRowScale_ = NULL; savedColumnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; } // Return model - nulls all arrays so can be deleted safely void ClpModel::returnModel(ClpModel & otherModel) { otherModel.objectiveValue_ = objectiveValue_; otherModel.numberIterations_ = numberIterations_; otherModel.problemStatus_ = problemStatus_; otherModel.secondaryStatus_ = secondaryStatus_; rowActivity_ = NULL; columnActivity_ = NULL; dual_ = NULL; reducedCost_ = NULL; rowLower_ = NULL; rowUpper_ = NULL; objective_ = NULL; rowObjective_ = NULL; columnLower_ = NULL; columnUpper_ = NULL; matrix_ = NULL; if (rowCopy_ != otherModel.rowCopy_) delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; delete [] otherModel.ray_; otherModel.ray_ = ray_; ray_ = NULL; if (rowScale_ && otherModel.rowScale_ != rowScale_) { delete [] rowScale_; delete [] columnScale_; } rowScale_ = NULL; columnScale_ = NULL; //rowScale_=NULL; //columnScale_=NULL; // do status if (otherModel.status_ != status_) { delete [] otherModel.status_; otherModel.status_ = status_; } status_ = NULL; if (defaultHandler_) { delete handler_; handler_ = NULL; } inverseRowScale_ = NULL; inverseColumnScale_ = NULL; } //############################################################################# // Parameter related methods //############################################################################# bool ClpModel::setIntParam(ClpIntParam key, int value) { switch (key) { case ClpMaxNumIteration: if (value < 0) return false; break; case ClpMaxNumIterationHotStart: if (value < 0) return false; break; case ClpNameDiscipline: if (value < 0) return false; break; default: return false; } intParam_[key] = value; return true; } //----------------------------------------------------------------------------- bool ClpModel::setDblParam(ClpDblParam key, double value) { switch (key) { case ClpDualObjectiveLimit: break; case ClpPrimalObjectiveLimit: break; case ClpDualTolerance: if (value <= 0.0 || value > 1.0e10) return false; break; case ClpPrimalTolerance: if (value <= 0.0 || value > 1.0e10) return false; break; case ClpObjOffset: break; case ClpMaxSeconds: if(value >= 0) value += CoinCpuTime(); else value = -1.0; break; case ClpMaxWallSeconds: if(value >= 0) value += CoinWallclockTime(); else value = -1.0; break; case ClpPresolveTolerance: if (value <= 0.0 || value > 1.0e10) return false; break; default: return false; } dblParam_[key] = value; return true; } //----------------------------------------------------------------------------- #ifndef CLP_NO_STD bool ClpModel::setStrParam(ClpStrParam key, const std::string & value) { switch (key) { case ClpProbName: break; default: return false; } strParam_[key] = value; return true; } #endif // Useful routines // Returns resized array and deletes incoming double * resizeDouble(double * array , int size, int newSize, double fill, bool createArray) { if ((array || createArray) && size < newSize) { int i; double * newArray = new double[newSize]; if (array) CoinMemcpyN(array, CoinMin(newSize, size), newArray); delete [] array; array = newArray; for (i = size; i < newSize; i++) array[i] = fill; } return array; } // Returns resized array and updates size double * deleteDouble(double * array , int size, int number, const int * which, int & newSize) { if (array) { int i ; char * deleted = new char[size]; int numberDeleted = 0; CoinZeroN(deleted, size); for (i = 0; i < number; i++) { int j = which[i]; if (j >= 0 && j < size && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } newSize = size - numberDeleted; double * newArray = new double[newSize]; int put = 0; for (i = 0; i < size; i++) { if (!deleted[i]) { newArray[put++] = array[i]; } } delete [] array; array = newArray; delete [] deleted; } return array; } char * deleteChar(char * array , int size, int number, const int * which, int & newSize, bool ifDelete) { if (array) { int i ; char * deleted = new char[size]; int numberDeleted = 0; CoinZeroN(deleted, size); for (i = 0; i < number; i++) { int j = which[i]; if (j >= 0 && j < size && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } newSize = size - numberDeleted; char * newArray = new char[newSize]; int put = 0; for (i = 0; i < size; i++) { if (!deleted[i]) { newArray[put++] = array[i]; } } if (ifDelete) delete [] array; array = newArray; delete [] deleted; } return array; } // Create empty ClpPackedMatrix void ClpModel::createEmptyMatrix() { delete matrix_; whatsChanged_ = 0; CoinPackedMatrix matrix2; matrix_ = new ClpPackedMatrix(matrix2); } /* Really clean up matrix. a) eliminate all duplicate AND small elements in matrix b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 c) reallocate arrays and make max lengths equal to lengths d) orders elements returns number of elements eliminated or -1 if not ClpMatrix */ int ClpModel::cleanMatrix(double threshold) { ClpPackedMatrix * matrix = (dynamic_cast< ClpPackedMatrix*>(matrix_)); if (matrix) { return matrix->getPackedMatrix()->cleanMatrix(threshold); } else { return -1; } } // Resizes void ClpModel::resize (int newNumberRows, int newNumberColumns) { if (newNumberRows == numberRows_ && newNumberColumns == numberColumns_) return; // nothing to do whatsChanged_ = 0; int numberRows2 = newNumberRows; int numberColumns2 = newNumberColumns; if (numberRows2 < maximumRows_) numberRows2 = maximumRows_; if (numberColumns2 < maximumColumns_) numberColumns2 = maximumColumns_; if (numberRows2 > maximumRows_) { rowActivity_ = resizeDouble(rowActivity_, numberRows_, newNumberRows, 0.0, true); dual_ = resizeDouble(dual_, numberRows_, newNumberRows, 0.0, true); rowObjective_ = resizeDouble(rowObjective_, numberRows_, newNumberRows, 0.0, false); rowLower_ = resizeDouble(rowLower_, numberRows_, newNumberRows, -COIN_DBL_MAX, true); rowUpper_ = resizeDouble(rowUpper_, numberRows_, newNumberRows, COIN_DBL_MAX, true); } if (numberColumns2 > maximumColumns_) { columnActivity_ = resizeDouble(columnActivity_, numberColumns_, newNumberColumns, 0.0, true); reducedCost_ = resizeDouble(reducedCost_, numberColumns_, newNumberColumns, 0.0, true); } if (savedRowScale_ && numberRows2 > maximumInternalRows_) { double * temp; temp = new double [4*newNumberRows]; CoinFillN(temp, 4 * newNumberRows, 1.0); CoinMemcpyN(savedRowScale_, numberRows_, temp); CoinMemcpyN(savedRowScale_ + maximumInternalRows_, numberRows_, temp + newNumberRows); CoinMemcpyN(savedRowScale_ + 2 * maximumInternalRows_, numberRows_, temp + 2 * newNumberRows); CoinMemcpyN(savedRowScale_ + 3 * maximumInternalRows_, numberRows_, temp + 3 * newNumberRows); delete [] savedRowScale_; savedRowScale_ = temp; } if (savedColumnScale_ && numberColumns2 > maximumInternalColumns_) { double * temp; temp = new double [4*newNumberColumns]; CoinFillN(temp, 4 * newNumberColumns, 1.0); CoinMemcpyN(savedColumnScale_, numberColumns_, temp); CoinMemcpyN(savedColumnScale_ + maximumInternalColumns_, numberColumns_, temp + newNumberColumns); CoinMemcpyN(savedColumnScale_ + 2 * maximumInternalColumns_, numberColumns_, temp + 2 * newNumberColumns); CoinMemcpyN(savedColumnScale_ + 3 * maximumInternalColumns_, numberColumns_, temp + 3 * newNumberColumns); delete [] savedColumnScale_; savedColumnScale_ = temp; } if (objective_ && numberColumns2 > maximumColumns_) objective_->resize(newNumberColumns); else if (!objective_) objective_ = new ClpLinearObjective(NULL, newNumberColumns); if (numberColumns2 > maximumColumns_) { columnLower_ = resizeDouble(columnLower_, numberColumns_, newNumberColumns, 0.0, true); columnUpper_ = resizeDouble(columnUpper_, numberColumns_, newNumberColumns, COIN_DBL_MAX, true); } if (newNumberRows < numberRows_) { int * which = new int[numberRows_-newNumberRows]; int i; for (i = newNumberRows; i < numberRows_; i++) which[i-newNumberRows] = i; matrix_->deleteRows(numberRows_ - newNumberRows, which); delete [] which; } if (numberRows_ != newNumberRows || numberColumns_ != newNumberColumns) { // set state back to unknown problemStatus_ = -1; secondaryStatus_ = 0; delete [] ray_; ray_ = NULL; } setRowScale(NULL); setColumnScale(NULL); if (status_) { if (newNumberColumns + newNumberRows) { if (newNumberColumns + newNumberRows > maximumRows_ + maximumColumns_) { unsigned char * tempC = new unsigned char [newNumberColumns+newNumberRows]; unsigned char * tempR = tempC + newNumberColumns; memset(tempC, 3, newNumberColumns * sizeof(unsigned char)); memset(tempR, 1, newNumberRows * sizeof(unsigned char)); CoinMemcpyN(status_, CoinMin(newNumberColumns, numberColumns_), tempC); CoinMemcpyN(status_ + numberColumns_, CoinMin(newNumberRows, numberRows_), tempR); delete [] status_; status_ = tempC; } else if (newNumberColumns < numberColumns_) { memmove(status_ + newNumberColumns, status_ + numberColumns_, newNumberRows); } else if (newNumberColumns > numberColumns_) { memset(status_ + numberColumns_, 3, newNumberColumns - numberColumns_); memmove(status_ + newNumberColumns, status_ + numberColumns_, newNumberRows); } } else { // empty model - some systems don't like new [0] delete [] status_; status_ = NULL; } } #ifndef CLP_NO_STD if (lengthNames_) { // redo row and column names (make sure clean) int numberRowNames = CoinMin(static_cast(rowNames_.size()),numberRows_); if (numberRowNames < newNumberRows) { rowNames_.resize(newNumberRows); lengthNames_ = CoinMax(lengthNames_, 8); char name[9]; for (int iRow = numberRowNames; iRow < newNumberRows; iRow++) { sprintf(name, "R%7.7d", iRow); rowNames_[iRow] = name; } } int numberColumnNames = CoinMin(static_cast(columnNames_.size()),numberColumns_); if (numberColumnNames < newNumberColumns) { columnNames_.resize(newNumberColumns); lengthNames_ = CoinMax(lengthNames_, 8); char name[9]; for (int iColumn = numberColumnNames; iColumn < newNumberColumns; iColumn++) { sprintf(name, "C%7.7d", iColumn); columnNames_[iColumn] = name; } } } #endif numberRows_ = newNumberRows; if (newNumberColumns < numberColumns_ && matrix_->getNumCols()) { int * which = new int[numberColumns_-newNumberColumns]; int i; for (i = newNumberColumns; i < numberColumns_; i++) which[i-newNumberColumns] = i; matrix_->deleteCols(numberColumns_ - newNumberColumns, which); delete [] which; } if (integerType_ && numberColumns2 > maximumColumns_) { char * temp = new char [newNumberColumns]; CoinZeroN(temp, newNumberColumns); CoinMemcpyN(integerType_, CoinMin(newNumberColumns, numberColumns_), temp); delete [] integerType_; integerType_ = temp; } numberColumns_ = newNumberColumns; if ((specialOptions_ & 65536) != 0) { // leave until next create rim to up numbers } if (maximumRows_ >= 0) { if (numberRows_ > maximumRows_) COIN_DETAIL_PRINT(printf("resize %d rows, %d old maximum rows\n", numberRows_, maximumRows_)); maximumRows_ = CoinMax(maximumRows_, numberRows_); maximumColumns_ = CoinMax(maximumColumns_, numberColumns_); } } // Deletes rows void ClpModel::deleteRows(int number, const int * which) { if (!number) return; // nothing to do whatsChanged_ &= ~(1 + 2 + 4 + 8 + 16 + 32); // all except columns changed int newSize = 0; if (maximumRows_ < 0) { rowActivity_ = deleteDouble(rowActivity_, numberRows_, number, which, newSize); dual_ = deleteDouble(dual_, numberRows_, number, which, newSize); rowObjective_ = deleteDouble(rowObjective_, numberRows_, number, which, newSize); rowLower_ = deleteDouble(rowLower_, numberRows_, number, which, newSize); rowUpper_ = deleteDouble(rowUpper_, numberRows_, number, which, newSize); if (matrix_->getNumRows()) matrix_->deleteRows(number, which); //matrix_->removeGaps(); // status if (status_) { if (numberColumns_ + newSize) { unsigned char * tempR = reinterpret_cast (deleteChar(reinterpret_cast(status_) + numberColumns_, numberRows_, number, which, newSize, false)); unsigned char * tempC = new unsigned char [numberColumns_+newSize]; CoinMemcpyN(status_, numberColumns_, tempC); CoinMemcpyN(tempR, newSize, tempC + numberColumns_); delete [] tempR; delete [] status_; status_ = tempC; } else { // empty model - some systems don't like new [0] delete [] status_; status_ = NULL; } } } else { char * deleted = new char [numberRows_]; int i; int numberDeleted = 0; CoinZeroN(deleted, numberRows_); for (i = 0; i < number; i++) { int j = which[i]; if (j >= 0 && j < numberRows_ && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } assert (!rowObjective_); unsigned char * status2 = status_ + numberColumns_; for (i = 0; i < numberRows_; i++) { if (!deleted[i]) { rowActivity_[newSize] = rowActivity_[i]; dual_[newSize] = dual_[i]; rowLower_[newSize] = rowLower_[i]; rowUpper_[newSize] = rowUpper_[i]; status2[newSize] = status2[i]; newSize++; } } if (matrix_->getNumRows()) matrix_->deleteRows(number, which); //matrix_->removeGaps(); delete [] deleted; } #ifndef CLP_NO_STD // Now works if which out of order if (lengthNames_) { char * mark = new char [numberRows_]; CoinZeroN(mark, numberRows_); int i; for (i = 0; i < number; i++) mark[which[i]] = 1; int k = 0; for ( i = 0; i < numberRows_; ++i) { if (!mark[i]) rowNames_[k++] = rowNames_[i]; } rowNames_.erase(rowNames_.begin() + k, rowNames_.end()); delete [] mark; } #endif numberRows_ = newSize; // set state back to unknown problemStatus_ = -1; secondaryStatus_ = 0; delete [] ray_; ray_ = NULL; if (savedRowScale_ != rowScale_) { delete [] rowScale_; delete [] columnScale_; } rowScale_ = NULL; columnScale_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; } // Deletes columns void ClpModel::deleteColumns(int number, const int * which) { if (!number) return; // nothing to do assert (maximumColumns_ < 0); whatsChanged_ &= ~(1 + 2 + 4 + 8 + 64 + 128 + 256); // all except rows changed int newSize = 0; columnActivity_ = deleteDouble(columnActivity_, numberColumns_, number, which, newSize); reducedCost_ = deleteDouble(reducedCost_, numberColumns_, number, which, newSize); objective_->deleteSome(number, which); columnLower_ = deleteDouble(columnLower_, numberColumns_, number, which, newSize); columnUpper_ = deleteDouble(columnUpper_, numberColumns_, number, which, newSize); // possible matrix is not full if (matrix_->getNumCols() < numberColumns_) { int * which2 = new int [number]; int n = 0; int nMatrix = matrix_->getNumCols(); for (int i = 0; i < number; i++) { if (which[i] < nMatrix) which2[n++] = which[i]; } matrix_->deleteCols(n, which2); delete [] which2; } else { matrix_->deleteCols(number, which); } //matrix_->removeGaps(); // status if (status_) { if (numberRows_ + newSize) { unsigned char * tempC = reinterpret_cast (deleteChar(reinterpret_cast(status_), numberColumns_, number, which, newSize, false)); unsigned char * temp = new unsigned char [numberRows_+newSize]; CoinMemcpyN(tempC, newSize, temp); CoinMemcpyN(status_ + numberColumns_, numberRows_, temp + newSize); delete [] tempC; delete [] status_; status_ = temp; } else { // empty model - some systems don't like new [0] delete [] status_; status_ = NULL; } } integerType_ = deleteChar(integerType_, numberColumns_, number, which, newSize, true); #ifndef CLP_NO_STD // Now works if which out of order if (lengthNames_) { char * mark = new char [numberColumns_]; CoinZeroN(mark, numberColumns_); int i; for (i = 0; i < number; i++) mark[which[i]] = 1; int k = 0; for ( i = 0; i < numberColumns_; ++i) { if (!mark[i]) columnNames_[k++] = columnNames_[i]; } columnNames_.erase(columnNames_.begin() + k, columnNames_.end()); delete [] mark; } #endif numberColumns_ = newSize; // set state back to unknown problemStatus_ = -1; secondaryStatus_ = 0; delete [] ray_; ray_ = NULL; setRowScale(NULL); setColumnScale(NULL); } // Deletes rows AND columns (does not reallocate) void ClpModel::deleteRowsAndColumns(int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) { if (!numberColumns) { deleteRows(numberRows,whichRows); } else if (!numberRows) { deleteColumns(numberColumns,whichColumns); } else { whatsChanged_ &= ~511; // all changed bool doStatus = status_!=NULL; int numberTotal=numberRows_+numberColumns_; int * backRows = new int [numberTotal]; int * backColumns = backRows+numberRows_; memset(backRows,0,numberTotal*sizeof(int)); int newNumberColumns=0; for (int i=0;i=0&&iColumntype()==1); double * obj = objective(); for (int i=0;i=0&&iRow(matrix_); CoinPackedMatrix * matrix = clpMatrix ? clpMatrix->matrix() : NULL; if (matrix_->getNumCols() < numberColumns_) { assert (matrix); CoinBigIndex nel=matrix->getNumElements(); int n=matrix->getNumCols(); matrix->reserve(numberColumns_,nel); CoinBigIndex * columnStart = matrix->getMutableVectorStarts(); int * columnLength = matrix->getMutableVectorLengths(); for (int i=n;isetExtraMajor(0.1); //CoinPackedMatrix temp(*matrix); matrix->setExtraGap(0.0); matrix->setExtraMajor(0.0); int * row = matrix->getMutableIndices(); CoinBigIndex * columnStart = matrix->getMutableVectorStarts(); int * columnLength = matrix->getMutableVectorLengths(); double * element = matrix->getMutableElements(); newNumberColumns=0; CoinBigIndex n=0; for (int iColumn=0;iColumn=0) { CoinBigIndex start = columnStart[iColumn]; int nSave=n; columnStart[newNumberColumns]=n; for (CoinBigIndex j=start;j=0) { row[n]=iRow; element[n++]=element[j]; } } columnLength[newNumberColumns++]=n-nSave; } } columnStart[newNumberColumns]=n; matrix->setNumElements(n); matrix->setMajorDim(newNumberColumns); matrix->setMinorDim(newNumberRows); clpMatrix->setNumberActiveColumns(newNumberColumns); //temp.deleteRows(numberRows, whichRows); //temp.deleteCols(numberColumns, whichColumns); //assert(matrix->isEquivalent2(temp)); //*matrix=temp; } else { matrix_->deleteRows(numberRows, whichRows); matrix_->deleteCols(numberColumns, whichColumns); } numberColumns_ = newNumberColumns; numberRows_ = newNumberRows; delete [] backRows; // set state back to unknown problemStatus_ = -1; secondaryStatus_ = 0; delete [] ray_; ray_ = NULL; if (savedRowScale_ != rowScale_) { delete [] rowScale_; delete [] columnScale_; } rowScale_ = NULL; columnScale_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; delete rowCopy_; rowCopy_ = NULL; } } // Add one row void ClpModel::addRow(int numberInRow, const int * columns, const double * elements, double rowLower, double rowUpper) { CoinBigIndex starts[2]; starts[0] = 0; starts[1] = numberInRow; addRows(1, &rowLower, &rowUpper, starts, columns, elements); } // Add rows void ClpModel::addRows(int number, const double * rowLower, const double * rowUpper, const CoinBigIndex * rowStarts, const int * columns, const double * elements) { if (number) { whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed int numberRowsNow = numberRows_; resize(numberRowsNow + number, numberColumns_); double * lower = rowLower_ + numberRowsNow; double * upper = rowUpper_ + numberRowsNow; int iRow; if (rowLower) { for (iRow = 0; iRow < number; iRow++) { double value = rowLower[iRow]; if (value < -1.0e20) value = -COIN_DBL_MAX; lower[iRow] = value; } } else { for (iRow = 0; iRow < number; iRow++) { lower[iRow] = -COIN_DBL_MAX; } } if (rowUpper) { for (iRow = 0; iRow < number; iRow++) { double value = rowUpper[iRow]; if (value > 1.0e20) value = COIN_DBL_MAX; upper[iRow] = value; } } else { for (iRow = 0; iRow < number; iRow++) { upper[iRow] = COIN_DBL_MAX; } } // Deal with matrix delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; if (!matrix_) createEmptyMatrix(); setRowScale(NULL); setColumnScale(NULL); #ifndef CLP_NO_STD if (lengthNames_) { rowNames_.resize(numberRows_); } #endif if (rowStarts) { // Make sure matrix has correct number of columns matrix_->getPackedMatrix()->reserve(numberColumns_, 0, true); matrix_->appendMatrix(number, 0, rowStarts, columns, elements); } } } // Add rows void ClpModel::addRows(int number, const double * rowLower, const double * rowUpper, const CoinBigIndex * rowStarts, const int * rowLengths, const int * columns, const double * elements) { if (number) { CoinBigIndex numberElements = 0; int iRow; for (iRow = 0; iRow < number; iRow++) numberElements += rowLengths[iRow]; int * newStarts = new int[number+1]; int * newIndex = new int[numberElements]; double * newElements = new double[numberElements]; numberElements = 0; newStarts[0] = 0; for (iRow = 0; iRow < number; iRow++) { int iStart = rowStarts[iRow]; int length = rowLengths[iRow]; CoinMemcpyN(columns + iStart, length, newIndex + numberElements); CoinMemcpyN(elements + iStart, length, newElements + numberElements); numberElements += length; newStarts[iRow+1] = numberElements; } addRows(number, rowLower, rowUpper, newStarts, newIndex, newElements); delete [] newStarts; delete [] newIndex; delete [] newElements; } } #ifndef CLP_NO_VECTOR void ClpModel::addRows(int number, const double * rowLower, const double * rowUpper, const CoinPackedVectorBase * const * rows) { if (!number) return; whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed int numberRowsNow = numberRows_; resize(numberRowsNow + number, numberColumns_); double * lower = rowLower_ + numberRowsNow; double * upper = rowUpper_ + numberRowsNow; int iRow; if (rowLower) { for (iRow = 0; iRow < number; iRow++) { double value = rowLower[iRow]; if (value < -1.0e20) value = -COIN_DBL_MAX; lower[iRow] = value; } } else { for (iRow = 0; iRow < number; iRow++) { lower[iRow] = -COIN_DBL_MAX; } } if (rowUpper) { for (iRow = 0; iRow < number; iRow++) { double value = rowUpper[iRow]; if (value > 1.0e20) value = COIN_DBL_MAX; upper[iRow] = value; } } else { for (iRow = 0; iRow < number; iRow++) { upper[iRow] = COIN_DBL_MAX; } } // Deal with matrix delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; if (!matrix_) createEmptyMatrix(); if (rows) matrix_->appendRows(number, rows); setRowScale(NULL); setColumnScale(NULL); if (lengthNames_) { rowNames_.resize(numberRows_); } } #endif #ifndef SLIM_CLP // Add rows from a build object int ClpModel::addRows(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates) { CoinAssertHint (buildObject.type() == 0, "Looks as if both addRows and addCols being used"); // check correct int number = buildObject.numberRows(); int numberErrors = 0; if (number) { CoinBigIndex size = 0; int iRow; double * lower = new double [number]; double * upper = new double [number]; if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) { // See if can be +-1 for (iRow = 0; iRow < number; iRow++) { const int * columns; const double * elements; int numberElements = buildObject.row(iRow, lower[iRow], upper[iRow], columns, elements); for (int i = 0; i < numberElements; i++) { // allow for zero elements if (elements[i]) { if (fabs(elements[i]) == 1.0) { size++; } else { // bad tryPlusMinusOne = false; } } } if (!tryPlusMinusOne) break; } } else { // Will add to whatever sort of matrix exists tryPlusMinusOne = false; } if (!tryPlusMinusOne) { CoinBigIndex numberElements = buildObject.numberElements(); CoinBigIndex * starts = new CoinBigIndex [number+1]; int * column = new int[numberElements]; double * element = new double[numberElements]; starts[0] = 0; numberElements = 0; for (iRow = 0; iRow < number; iRow++) { const int * columns; const double * elements; int numberElementsThis = buildObject.row(iRow, lower[iRow], upper[iRow], columns, elements); CoinMemcpyN(columns, numberElementsThis, column + numberElements); CoinMemcpyN(elements, numberElementsThis, element + numberElements); numberElements += numberElementsThis; starts[iRow+1] = numberElements; } addRows(number, lower, upper, NULL); // make sure matrix has enough columns matrix_->setDimensions(-1, numberColumns_); numberErrors = matrix_->appendMatrix(number, 0, starts, column, element, checkDuplicates ? numberColumns_ : -1); delete [] starts; delete [] column; delete [] element; } else { char * which = NULL; // for duplicates if (checkDuplicates) { which = new char[numberColumns_]; CoinZeroN(which, numberColumns_); } // build +-1 matrix // arrays already filled in addRows(number, lower, upper, NULL); CoinBigIndex * startPositive = new CoinBigIndex [numberColumns_+1]; CoinBigIndex * startNegative = new CoinBigIndex [numberColumns_]; int * indices = new int [size]; CoinZeroN(startPositive, numberColumns_); CoinZeroN(startNegative, numberColumns_); int maxColumn = -1; // need two passes for (iRow = 0; iRow < number; iRow++) { const int * columns; const double * elements; int numberElements = buildObject.row(iRow, lower[iRow], upper[iRow], columns, elements); for (int i = 0; i < numberElements; i++) { int iColumn = columns[i]; if (checkDuplicates) { if (iColumn >= numberColumns_) { if(which[iColumn]) numberErrors++; else which[iColumn] = 1; } else { numberErrors++; // and may as well switch off checkDuplicates = false; } } maxColumn = CoinMax(maxColumn, iColumn); if (elements[i] == 1.0) { startPositive[iColumn]++; } else if (elements[i] == -1.0) { startNegative[iColumn]++; } } if (checkDuplicates) { for (int i = 0; i < numberElements; i++) { int iColumn = columns[i]; which[iColumn] = 0; } } } // check size int numberColumns = maxColumn + 1; CoinAssertHint (numberColumns <= numberColumns_, "rows having column indices >= numberColumns_"); size = 0; int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex n = startPositive[iColumn]; startPositive[iColumn] = size; size += n; n = startNegative[iColumn]; startNegative[iColumn] = size; size += n; } startPositive[numberColumns_] = size; for (iRow = 0; iRow < number; iRow++) { const int * columns; const double * elements; int numberElements = buildObject.row(iRow, lower[iRow], upper[iRow], columns, elements); for (int i = 0; i < numberElements; i++) { int iColumn = columns[i]; maxColumn = CoinMax(maxColumn, iColumn); if (elements[i] == 1.0) { CoinBigIndex position = startPositive[iColumn]; indices[position] = iRow; startPositive[iColumn]++; } else if (elements[i] == -1.0) { CoinBigIndex position = startNegative[iColumn]; indices[position] = iRow; startNegative[iColumn]++; } } } // and now redo starts for (iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) { startPositive[iColumn+1] = startNegative[iColumn]; startNegative[iColumn] = startPositive[iColumn]; } startPositive[0] = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex start = startPositive[iColumn]; CoinBigIndex end = startNegative[iColumn]; std::sort(indices + start, indices + end); start = startNegative[iColumn]; end = startPositive[iColumn+1]; std::sort(indices + start, indices + end); } // Get good object delete matrix_; ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix(); matrix->passInCopy(numberRows_, numberColumns, true, indices, startPositive, startNegative); matrix_ = matrix; delete [] which; } delete [] lower; delete [] upper; // make sure matrix correct size matrix_->setDimensions(numberRows_, numberColumns_); } return numberErrors; } #endif #ifndef SLIM_NOIO // Add rows from a model object int ClpModel::addRows( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates) { if (modelObject.numberElements() == 0) return 0; bool goodState = true; int numberErrors = 0; if (modelObject.columnLowerArray()) { // some column information exists int numberColumns2 = modelObject.numberColumns(); const double * columnLower = modelObject.columnLowerArray(); const double * columnUpper = modelObject.columnUpperArray(); const double * objective = modelObject.objectiveArray(); const int * integerType = modelObject.integerTypeArray(); for (int i = 0; i < numberColumns2; i++) { if (columnLower[i] != 0.0) goodState = false; if (columnUpper[i] != COIN_DBL_MAX) goodState = false; if (objective[i] != 0.0) goodState = false; if (integerType[i] != 0) goodState = false; } } if (goodState) { // can do addRows // Set arrays for normal use double * rowLower = modelObject.rowLowerArray(); double * rowUpper = modelObject.rowUpperArray(); double * columnLower = modelObject.columnLowerArray(); double * columnUpper = modelObject.columnUpperArray(); double * objective = modelObject.objectiveArray(); int * integerType = modelObject.integerTypeArray(); double * associated = modelObject.associatedArray(); // If strings then do copies if (modelObject.stringsExist()) { numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper, objective, integerType, associated); } int numberRows = numberRows_; // save number of rows int numberRows2 = modelObject.numberRows(); if (numberRows2 && !numberErrors) { CoinBigIndex * startPositive = NULL; CoinBigIndex * startNegative = NULL; int numberColumns = modelObject.numberColumns(); if ((!matrix_ || !matrix_->getNumElements()) && !numberRows && tryPlusMinusOne) { startPositive = new CoinBigIndex[numberColumns+1]; startNegative = new CoinBigIndex[numberColumns]; modelObject.countPlusMinusOne(startPositive, startNegative, associated); if (startPositive[0] < 0) { // no good tryPlusMinusOne = false; delete [] startPositive; delete [] startNegative; } } else { // Will add to whatever sort of matrix exists tryPlusMinusOne = false; } assert (rowLower); addRows(numberRows2, rowLower, rowUpper, NULL, NULL, NULL); #ifndef SLIM_CLP if (!tryPlusMinusOne) { #endif CoinPackedMatrix matrix; modelObject.createPackedMatrix(matrix, associated); assert (!matrix.getExtraGap()); if (matrix_->getNumRows()) { // matrix by rows matrix.reverseOrdering(); assert (!matrix.getExtraGap()); const int * column = matrix.getIndices(); //const int * rowLength = matrix.getVectorLengths(); const CoinBigIndex * rowStart = matrix.getVectorStarts(); const double * element = matrix.getElements(); // make sure matrix has enough columns matrix_->setDimensions(-1, numberColumns_); numberErrors += matrix_->appendMatrix(numberRows2, 0, rowStart, column, element, checkDuplicates ? numberColumns_ : -1); } else { delete matrix_; matrix_ = new ClpPackedMatrix(matrix); } #ifndef SLIM_CLP } else { // create +-1 matrix CoinBigIndex size = startPositive[numberColumns]; int * indices = new int[size]; modelObject.createPlusMinusOne(startPositive, startNegative, indices, associated); // Get good object ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix(); matrix->passInCopy(numberRows2, numberColumns, true, indices, startPositive, startNegative); delete matrix_; matrix_ = matrix; } // Do names if wanted if (modelObject.rowNames()->numberItems()) { const char *const * rowNames = modelObject.rowNames()->names(); copyRowNames(rowNames, numberRows, numberRows_); } #endif } if (rowLower != modelObject.rowLowerArray()) { delete [] rowLower; delete [] rowUpper; delete [] columnLower; delete [] columnUpper; delete [] objective; delete [] integerType; delete [] associated; if (numberErrors) handler_->message(CLP_BAD_STRING_VALUES, messages_) << numberErrors << CoinMessageEol; } return numberErrors; } else { // not suitable for addRows handler_->message(CLP_COMPLICATED_MODEL, messages_) << modelObject.numberRows() << modelObject.numberColumns() << CoinMessageEol; return -1; } } #endif // Add one column void ClpModel::addColumn(int numberInColumn, const int * rows, const double * elements, double columnLower, double columnUpper, double objective) { CoinBigIndex starts[2]; starts[0] = 0; starts[1] = numberInColumn; addColumns(1, &columnLower, &columnUpper, &objective, starts, rows, elements); } // Add columns void ClpModel::addColumns(int number, const double * columnLower, const double * columnUpper, const double * objIn, const int * columnStarts, const int * rows, const double * elements) { // Create a list of CoinPackedVectors if (number) { whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed int numberColumnsNow = numberColumns_; resize(numberRows_, numberColumnsNow + number); double * lower = columnLower_ + numberColumnsNow; double * upper = columnUpper_ + numberColumnsNow; double * obj = objective() + numberColumnsNow; int iColumn; if (columnLower) { for (iColumn = 0; iColumn < number; iColumn++) { double value = columnLower[iColumn]; if (value < -1.0e20) value = -COIN_DBL_MAX; lower[iColumn] = value; } } else { for (iColumn = 0; iColumn < number; iColumn++) { lower[iColumn] = 0.0; } } if (columnUpper) { for (iColumn = 0; iColumn < number; iColumn++) { double value = columnUpper[iColumn]; if (value > 1.0e20) value = COIN_DBL_MAX; upper[iColumn] = value; } } else { for (iColumn = 0; iColumn < number; iColumn++) { upper[iColumn] = COIN_DBL_MAX; } } if (objIn) { for (iColumn = 0; iColumn < number; iColumn++) { obj[iColumn] = objIn[iColumn]; } } else { for (iColumn = 0; iColumn < number; iColumn++) { obj[iColumn] = 0.0; } } // Deal with matrix delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; if (!matrix_) createEmptyMatrix(); setRowScale(NULL); setColumnScale(NULL); #ifndef CLP_NO_STD if (lengthNames_) { columnNames_.resize(numberColumns_); } #endif // Do even if elements NULL (to resize) matrix_->appendMatrix(number, 1, columnStarts, rows, elements); } } // Add columns void ClpModel::addColumns(int number, const double * columnLower, const double * columnUpper, const double * objIn, const int * columnStarts, const int * columnLengths, const int * rows, const double * elements) { if (number) { CoinBigIndex numberElements = 0; int iColumn; for (iColumn = 0; iColumn < number; iColumn++) numberElements += columnLengths[iColumn]; int * newStarts = new int[number+1]; int * newIndex = new int[numberElements]; double * newElements = new double[numberElements]; numberElements = 0; newStarts[0] = 0; for (iColumn = 0; iColumn < number; iColumn++) { int iStart = columnStarts[iColumn]; int length = columnLengths[iColumn]; CoinMemcpyN(rows + iStart, length, newIndex + numberElements); CoinMemcpyN(elements + iStart, length, newElements + numberElements); numberElements += length; newStarts[iColumn+1] = numberElements; } addColumns(number, columnLower, columnUpper, objIn, newStarts, newIndex, newElements); delete [] newStarts; delete [] newIndex; delete [] newElements; } } #ifndef CLP_NO_VECTOR void ClpModel::addColumns(int number, const double * columnLower, const double * columnUpper, const double * objIn, const CoinPackedVectorBase * const * columns) { if (!number) return; whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed int numberColumnsNow = numberColumns_; resize(numberRows_, numberColumnsNow + number); double * lower = columnLower_ + numberColumnsNow; double * upper = columnUpper_ + numberColumnsNow; double * obj = objective() + numberColumnsNow; int iColumn; if (columnLower) { for (iColumn = 0; iColumn < number; iColumn++) { double value = columnLower[iColumn]; if (value < -1.0e20) value = -COIN_DBL_MAX; lower[iColumn] = value; } } else { for (iColumn = 0; iColumn < number; iColumn++) { lower[iColumn] = 0.0; } } if (columnUpper) { for (iColumn = 0; iColumn < number; iColumn++) { double value = columnUpper[iColumn]; if (value > 1.0e20) value = COIN_DBL_MAX; upper[iColumn] = value; } } else { for (iColumn = 0; iColumn < number; iColumn++) { upper[iColumn] = COIN_DBL_MAX; } } if (objIn) { for (iColumn = 0; iColumn < number; iColumn++) { obj[iColumn] = objIn[iColumn]; } } else { for (iColumn = 0; iColumn < number; iColumn++) { obj[iColumn] = 0.0; } } // Deal with matrix delete rowCopy_; rowCopy_ = NULL; delete scaledMatrix_; scaledMatrix_ = NULL; if (!matrix_) createEmptyMatrix(); if (columns) matrix_->appendCols(number, columns); setRowScale(NULL); setColumnScale(NULL); if (lengthNames_) { columnNames_.resize(numberColumns_); } } #endif #ifndef SLIM_CLP // Add columns from a build object int ClpModel::addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates) { CoinAssertHint (buildObject.type() == 1, "Looks as if both addRows and addCols being used"); // check correct int number = buildObject.numberColumns(); int numberErrors = 0; if (number) { CoinBigIndex size = 0; int maximumLength = 0; double * lower = new double [number]; double * upper = new double [number]; int iColumn; double * objective = new double [number]; if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) { // See if can be +-1 for (iColumn = 0; iColumn < number; iColumn++) { const int * rows; const double * elements; int numberElements = buildObject.column(iColumn, lower[iColumn], upper[iColumn], objective[iColumn], rows, elements); maximumLength = CoinMax(maximumLength, numberElements); for (int i = 0; i < numberElements; i++) { // allow for zero elements if (elements[i]) { if (fabs(elements[i]) == 1.0) { size++; } else { // bad tryPlusMinusOne = false; } } } if (!tryPlusMinusOne) break; } } else { // Will add to whatever sort of matrix exists tryPlusMinusOne = false; } if (!tryPlusMinusOne) { CoinBigIndex numberElements = buildObject.numberElements(); CoinBigIndex * starts = new CoinBigIndex [number+1]; int * row = new int[numberElements]; double * element = new double[numberElements]; starts[0] = 0; numberElements = 0; for (iColumn = 0; iColumn < number; iColumn++) { const int * rows; const double * elements; int numberElementsThis = buildObject.column(iColumn, lower[iColumn], upper[iColumn], objective[iColumn], rows, elements); CoinMemcpyN(rows, numberElementsThis, row + numberElements); CoinMemcpyN(elements, numberElementsThis, element + numberElements); numberElements += numberElementsThis; starts[iColumn+1] = numberElements; } addColumns(number, lower, upper, objective, NULL); // make sure matrix has enough rows matrix_->setDimensions(numberRows_, -1); numberErrors = matrix_->appendMatrix(number, 1, starts, row, element, checkDuplicates ? numberRows_ : -1); delete [] starts; delete [] row; delete [] element; } else { // arrays already filled in addColumns(number, lower, upper, objective, NULL); char * which = NULL; // for duplicates if (checkDuplicates) { which = new char[numberRows_]; CoinZeroN(which, numberRows_); } // build +-1 matrix CoinBigIndex * startPositive = new CoinBigIndex [number+1]; CoinBigIndex * startNegative = new CoinBigIndex [number]; int * indices = new int [size]; int * neg = new int[maximumLength]; startPositive[0] = 0; size = 0; int maxRow = -1; for (iColumn = 0; iColumn < number; iColumn++) { const int * rows; const double * elements; int numberElements = buildObject.column(iColumn, lower[iColumn], upper[iColumn], objective[iColumn], rows, elements); int nNeg = 0; CoinBigIndex start = size; for (int i = 0; i < numberElements; i++) { int iRow = rows[i]; if (checkDuplicates) { if (iRow >= numberRows_) { if(which[iRow]) numberErrors++; else which[iRow] = 1; } else { numberErrors++; // and may as well switch off checkDuplicates = false; } } maxRow = CoinMax(maxRow, iRow); if (elements[i] == 1.0) { indices[size++] = iRow; } else if (elements[i] == -1.0) { neg[nNeg++] = iRow; } } std::sort(indices + start, indices + size); std::sort(neg, neg + nNeg); startNegative[iColumn] = size; CoinMemcpyN(neg, nNeg, indices + size); size += nNeg; startPositive[iColumn+1] = size; } delete [] neg; // check size assert (maxRow + 1 <= numberRows_); // Get good object delete matrix_; ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix(); matrix->passInCopy(numberRows_, number, true, indices, startPositive, startNegative); matrix_ = matrix; delete [] which; } delete [] objective; delete [] lower; delete [] upper; } return 0; } #endif #ifndef SLIM_NOIO // Add columns from a model object int ClpModel::addColumns( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates) { if (modelObject.numberElements() == 0) return 0; bool goodState = true; if (modelObject.rowLowerArray()) { // some row information exists int numberRows2 = modelObject.numberRows(); const double * rowLower = modelObject.rowLowerArray(); const double * rowUpper = modelObject.rowUpperArray(); for (int i = 0; i < numberRows2; i++) { if (rowLower[i] != -COIN_DBL_MAX) goodState = false; if (rowUpper[i] != COIN_DBL_MAX) goodState = false; } } if (goodState) { // can do addColumns int numberErrors = 0; // Set arrays for normal use double * rowLower = modelObject.rowLowerArray(); double * rowUpper = modelObject.rowUpperArray(); double * columnLower = modelObject.columnLowerArray(); double * columnUpper = modelObject.columnUpperArray(); double * objective = modelObject.objectiveArray(); int * integerType = modelObject.integerTypeArray(); double * associated = modelObject.associatedArray(); // If strings then do copies if (modelObject.stringsExist()) { numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper, objective, integerType, associated); } int numberColumns = numberColumns_; // save number of columns int numberColumns2 = modelObject.numberColumns(); if (numberColumns2 && !numberErrors) { CoinBigIndex * startPositive = NULL; CoinBigIndex * startNegative = NULL; if ((!matrix_ || !matrix_->getNumElements()) && !numberColumns && tryPlusMinusOne) { startPositive = new CoinBigIndex[numberColumns2+1]; startNegative = new CoinBigIndex[numberColumns2]; modelObject.countPlusMinusOne(startPositive, startNegative, associated); if (startPositive[0] < 0) { // no good tryPlusMinusOne = false; delete [] startPositive; delete [] startNegative; } } else { // Will add to whatever sort of matrix exists tryPlusMinusOne = false; } assert (columnLower); addColumns(numberColumns2, columnLower, columnUpper, objective, NULL, NULL, NULL); #ifndef SLIM_CLP if (!tryPlusMinusOne) { #endif /* addColumns just above extended matrix - to keep things clean - take off again. I know it is a bit clumsy but won't break anything */ { int * which = new int [numberColumns2]; for (int i=0;ideleteCols(numberColumns2,which); delete [] which; } CoinPackedMatrix matrix; modelObject.createPackedMatrix(matrix, associated); assert (!matrix.getExtraGap()); if (matrix_->getNumCols()) { const int * row = matrix.getIndices(); //const int * columnLength = matrix.getVectorLengths(); const CoinBigIndex * columnStart = matrix.getVectorStarts(); const double * element = matrix.getElements(); // make sure matrix has enough rows matrix_->setDimensions(numberRows_, -1); numberErrors += matrix_->appendMatrix(numberColumns2, 1, columnStart, row, element, checkDuplicates ? numberRows_ : -1); } else { delete matrix_; matrix_ = new ClpPackedMatrix(matrix); } #ifndef SLIM_CLP } else { // create +-1 matrix CoinBigIndex size = startPositive[numberColumns2]; int * indices = new int[size]; modelObject.createPlusMinusOne(startPositive, startNegative, indices, associated); // Get good object ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix(); matrix->passInCopy(numberRows_, numberColumns2, true, indices, startPositive, startNegative); delete matrix_; matrix_ = matrix; } #endif #ifndef CLP_NO_STD // Do names if wanted if (modelObject.columnNames()->numberItems()) { const char *const * columnNames = modelObject.columnNames()->names(); copyColumnNames(columnNames, numberColumns, numberColumns_); } #endif // Do integers if wanted assert(integerType); for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { if (integerType[iColumn]) setInteger(iColumn + numberColumns); } } if (columnLower != modelObject.columnLowerArray()) { delete [] rowLower; delete [] rowUpper; delete [] columnLower; delete [] columnUpper; delete [] objective; delete [] integerType; delete [] associated; if (numberErrors) handler_->message(CLP_BAD_STRING_VALUES, messages_) << numberErrors << CoinMessageEol; } return numberErrors; } else { // not suitable for addColumns handler_->message(CLP_COMPLICATED_MODEL, messages_) << modelObject.numberRows() << modelObject.numberColumns() << CoinMessageEol; return -1; } } #endif // chgRowLower void ClpModel::chgRowLower(const double * rowLower) { int numberRows = numberRows_; int iRow; whatsChanged_ = 0; // Use ClpSimplex stuff to keep if (rowLower) { for (iRow = 0; iRow < numberRows; iRow++) { double value = rowLower[iRow]; if (value < -1.0e20) value = -COIN_DBL_MAX; rowLower_[iRow] = value; } } else { for (iRow = 0; iRow < numberRows; iRow++) { rowLower_[iRow] = -COIN_DBL_MAX; } } } // chgRowUpper void ClpModel::chgRowUpper(const double * rowUpper) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep int numberRows = numberRows_; int iRow; if (rowUpper) { for (iRow = 0; iRow < numberRows; iRow++) { double value = rowUpper[iRow]; if (value > 1.0e20) value = COIN_DBL_MAX; rowUpper_[iRow] = value; } } else { for (iRow = 0; iRow < numberRows; iRow++) { rowUpper_[iRow] = COIN_DBL_MAX;; } } } // chgColumnLower void ClpModel::chgColumnLower(const double * columnLower) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep int numberColumns = numberColumns_; int iColumn; if (columnLower) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = columnLower[iColumn]; if (value < -1.0e20) value = -COIN_DBL_MAX; columnLower_[iColumn] = value; } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnLower_[iColumn] = 0.0; } } } // chgColumnUpper void ClpModel::chgColumnUpper(const double * columnUpper) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep int numberColumns = numberColumns_; int iColumn; if (columnUpper) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = columnUpper[iColumn]; if (value > 1.0e20) value = COIN_DBL_MAX; columnUpper_[iColumn] = value; } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { columnUpper_[iColumn] = COIN_DBL_MAX;; } } } // chgObjCoefficients void ClpModel::chgObjCoefficients(const double * objIn) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep double * obj = objective(); int numberColumns = numberColumns_; int iColumn; if (objIn) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { obj[iColumn] = objIn[iColumn]; } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { obj[iColumn] = 0.0; } } } // Infeasibility/unbounded ray (NULL returned if none/wrong) double * ClpModel::infeasibilityRay(bool fullRay) const { double * array = NULL; if (problemStatus_ == 1 && ray_) { if (!fullRay) { array = ClpCopyOfArray(ray_, numberRows_); } else { array = new double [numberRows_+numberColumns_]; memcpy(array,ray_,numberRows_*sizeof(double)); memset(array+numberRows_,0,numberColumns_*sizeof(double)); transposeTimes(-1.0,array,array+numberRows_); } } return array; } double * ClpModel::unboundedRay() const { double * array = NULL; if (problemStatus_ == 2) array = ClpCopyOfArray(ray_, numberColumns_); return array; } void ClpModel::setMaximumIterations(int value) { if(value >= 0) intParam_[ClpMaxNumIteration] = value; } void ClpModel::setMaximumSeconds(double value) { if(value >= 0) dblParam_[ClpMaxSeconds] = value + CoinCpuTime(); else dblParam_[ClpMaxSeconds] = -1.0; } void ClpModel::setMaximumWallSeconds(double value) { if(value >= 0) dblParam_[ClpMaxWallSeconds] = value + CoinWallclockTime(); else dblParam_[ClpMaxWallSeconds] = -1.0; } // Returns true if hit maximum iterations (or time) bool ClpModel::hitMaximumIterations() const { // replaced - compiler error? bool hitMax= (numberIterations_>=maximumIterations()); bool hitMax = (numberIterations_ >= intParam_[ClpMaxNumIteration]); if (dblParam_[ClpMaxSeconds] >= 0.0 && !hitMax) { hitMax = (CoinCpuTime() >= dblParam_[ClpMaxSeconds]); } if (dblParam_[ClpMaxWallSeconds] >= 0.0 && !hitMax) { hitMax = (CoinWallclockTime() >= dblParam_[ClpMaxWallSeconds]); } return hitMax; } // On stopped - sets secondary status void ClpModel::onStopped() { if (problemStatus_ == 3) { secondaryStatus_ = 0; if ((CoinCpuTime() >= dblParam_[ClpMaxSeconds] && dblParam_[ClpMaxSeconds] >= 0.0) || (CoinWallclockTime() >= dblParam_[ClpMaxWallSeconds] && dblParam_[ClpMaxWallSeconds] >= 0.0)) secondaryStatus_ = 9; } } // Pass in Message handler (not deleted at end) void ClpModel::passInMessageHandler(CoinMessageHandler * handler) { if (defaultHandler_) delete handler_; defaultHandler_ = false; handler_ = handler; } // Pass in Message handler (not deleted at end) and return current CoinMessageHandler * ClpModel::pushMessageHandler(CoinMessageHandler * handler, bool & oldDefault) { CoinMessageHandler * returnValue = handler_; oldDefault = defaultHandler_; defaultHandler_ = false; handler_ = handler; return returnValue; } // back to previous message handler void ClpModel::popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault) { if (defaultHandler_) delete handler_; defaultHandler_ = oldDefault; handler_ = oldHandler; } // Overrides message handler with a default one void ClpModel::setDefaultMessageHandler() { int logLevel = handler_->logLevel(); if (defaultHandler_) delete handler_; defaultHandler_ = true; handler_ = new CoinMessageHandler(); handler_->setLogLevel(logLevel); } // Set language void ClpModel::newLanguage(CoinMessages::Language language) { messages_ = ClpMessage(language); } #ifndef SLIM_NOIO // Read an mps file from the given filename int ClpModel::readMps(const char *fileName, bool keepNames, bool ignoreErrors) { if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) { // stdin } else { std::string name = fileName; bool readable = fileCoinReadable(name); if (!readable) { handler_->message(CLP_UNABLE_OPEN, messages_) << fileName << CoinMessageEol; return -1; } } CoinMpsIO m; m.passInMessageHandler(handler_); *m.messagesPointer() = coinMessages(); bool savePrefix = m.messageHandler()->prefix(); m.messageHandler()->setPrefix(handler_->prefix()); m.setSmallElementValue(CoinMax(smallElement_, m.getSmallElementValue())); double time1 = CoinCpuTime(), time2; int status = 0; try { status = m.readMps(fileName, ""); } catch (CoinError e) { e.print(); status = -1; } m.messageHandler()->setPrefix(savePrefix); if (!status || (ignoreErrors && (status > 0 && status < 100000))) { loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (m.integerColumns()) { integerType_ = new char[numberColumns_]; CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_); } else { integerType_ = NULL; } #ifndef SLIM_CLP // get quadratic part if (m.reader()->whichSection ( ) == COIN_QUAD_SECTION ) { int * start = NULL; int * column = NULL; double * element = NULL; status = m.readQuadraticMps(NULL, start, column, element, 2); if (!status || ignoreErrors) loadQuadraticObjective(numberColumns_, start, column, element); delete [] start; delete [] column; delete [] element; } #endif #ifndef CLP_NO_STD // set problem name setStrParam(ClpProbName, m.getProblemName()); // do names if (keepNames) { unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { const char * name = m.rowName(iRow); maxLength = CoinMax(maxLength, static_cast (strlen(name))); rowNames_.push_back(name); } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { const char * name = m.columnName(iColumn); maxLength = CoinMax(maxLength, static_cast (strlen(name))); columnNames_.push_back(name); } lengthNames_ = static_cast (maxLength); } else { lengthNames_ = 0; } #endif setDblParam(ClpObjOffset, m.objectiveOffset()); time2 = CoinCpuTime(); handler_->message(CLP_IMPORT_RESULT, messages_) << fileName << time2 - time1 << CoinMessageEol; } else { // errors handler_->message(CLP_IMPORT_ERRORS, messages_) << status << fileName << CoinMessageEol; } return status; } // Read GMPL files from the given filenames int ClpModel::readGMPL(const char *fileName, const char * dataName, bool keepNames) { FILE *fp = fopen(fileName, "r"); if (fp) { // can open - lets go for it fclose(fp); if (dataName) { fp = fopen(dataName, "r"); if (fp) { fclose(fp); } else { handler_->message(CLP_UNABLE_OPEN, messages_) << dataName << CoinMessageEol; return -1; } } } else { handler_->message(CLP_UNABLE_OPEN, messages_) << fileName << CoinMessageEol; return -1; } CoinMpsIO m; m.passInMessageHandler(handler_); *m.messagesPointer() = coinMessages(); bool savePrefix = m.messageHandler()->prefix(); m.messageHandler()->setPrefix(handler_->prefix()); double time1 = CoinCpuTime(), time2; int status = m.readGMPL(fileName, dataName, keepNames); m.messageHandler()->setPrefix(savePrefix); if (!status) { loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (m.integerColumns()) { integerType_ = new char[numberColumns_]; CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_); } else { integerType_ = NULL; } #ifndef CLP_NO_STD // set problem name setStrParam(ClpProbName, m.getProblemName()); // do names if (keepNames) { unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { const char * name = m.rowName(iRow); maxLength = CoinMax(maxLength, static_cast (strlen(name))); rowNames_.push_back(name); } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { const char * name = m.columnName(iColumn); maxLength = CoinMax(maxLength, static_cast (strlen(name))); columnNames_.push_back(name); } lengthNames_ = static_cast (maxLength); } else { lengthNames_ = 0; } #endif setDblParam(ClpObjOffset, m.objectiveOffset()); time2 = CoinCpuTime(); handler_->message(CLP_IMPORT_RESULT, messages_) << fileName << time2 - time1 << CoinMessageEol; } else { // errors handler_->message(CLP_IMPORT_ERRORS, messages_) << status << fileName << CoinMessageEol; } return status; } #endif bool ClpModel::isPrimalObjectiveLimitReached() const { double limit = 0.0; getDblParam(ClpPrimalObjectiveLimit, limit); if (limit > 1e30) { // was not ever set return false; } const double obj = objectiveValue(); const double maxmin = optimizationDirection(); if (problemStatus_ == 0) // optimal return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/; else if (problemStatus_ == 2) return true; else return false; } bool ClpModel::isDualObjectiveLimitReached() const { double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if (limit > 1e30) { // was not ever set return false; } const double obj = objectiveValue(); const double maxmin = optimizationDirection(); if (problemStatus_ == 0) // optimal return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/; else if (problemStatus_ == 1) return true; else return false; } void ClpModel::copyInIntegerInformation(const char * information) { delete [] integerType_; if (information) { integerType_ = new char[numberColumns_]; CoinMemcpyN(information, numberColumns_, integerType_); } else { integerType_ = NULL; } } void ClpModel::setContinuous(int index) { if (integerType_) { #ifndef NDEBUG if (index < 0 || index >= numberColumns_) { indexError(index, "setContinuous"); } #endif integerType_[index] = 0; } } //----------------------------------------------------------------------------- void ClpModel::setInteger(int index) { if (!integerType_) { integerType_ = new char[numberColumns_]; CoinZeroN ( integerType_, numberColumns_); } #ifndef NDEBUG if (index < 0 || index >= numberColumns_) { indexError(index, "setInteger"); } #endif integerType_[index] = 1; } /* Return true if the index-th variable is an integer variable */ bool ClpModel::isInteger(int index) const { if (!integerType_) { return false; } else { #ifndef NDEBUG if (index < 0 || index >= numberColumns_) { indexError(index, "isInteger"); } #endif return (integerType_[index] != 0); } } #ifndef CLP_NO_STD // Drops names - makes lengthnames 0 and names empty void ClpModel::dropNames() { lengthNames_ = 0; rowNames_ = std::vector (); columnNames_ = std::vector (); } #endif // Drop integer informations void ClpModel::deleteIntegerInformation() { delete [] integerType_; integerType_ = NULL; } /* Return copy of status array (char[numberRows+numberColumns]), use delete [] */ unsigned char * ClpModel::statusCopy() const { return ClpCopyOfArray(status_, numberRows_ + numberColumns_); } // Copy in status vector void ClpModel::copyinStatus(const unsigned char * statusArray) { delete [] status_; if (statusArray) { status_ = new unsigned char [numberRows_+numberColumns_]; CoinMemcpyN(statusArray, (numberRows_ + numberColumns_), status_); } else { status_ = NULL; } } #ifndef SLIM_CLP // Load up quadratic objective void ClpModel::loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start, const int * column, const double * element) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep CoinAssert (numberColumns == numberColumns_); assert ((dynamic_cast< ClpLinearObjective*>(objective_))); double offset; ClpObjective * obj = new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false), numberColumns, start, column, element); delete objective_; objective_ = obj; } void ClpModel::loadQuadraticObjective ( const CoinPackedMatrix& matrix) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep CoinAssert (matrix.getNumCols() == numberColumns_); assert ((dynamic_cast< ClpLinearObjective*>(objective_))); double offset; ClpQuadraticObjective * obj = new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false), numberColumns_, NULL, NULL, NULL); delete objective_; objective_ = obj; obj->loadQuadraticObjective(matrix); } // Get rid of quadratic objective void ClpModel::deleteQuadraticObjective() { whatsChanged_ = 0; // Use ClpSimplex stuff to keep ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); if (obj) obj->deleteQuadraticObjective(); } #endif void ClpModel::setObjective(ClpObjective * objective) { whatsChanged_ = 0; // Use ClpSimplex stuff to keep delete objective_; objective_ = objective->clone(); } // Returns resized array and updates size double * whichDouble(double * array , int number, const int * which) { double * newArray = NULL; if (array && number) { int i ; newArray = new double[number]; for (i = 0; i < number; i++) newArray[i] = array[which[i]]; } return newArray; } char * whichChar(char * array , int number, const int * which) { char * newArray = NULL; if (array && number) { int i ; newArray = new char[number]; for (i = 0; i < number; i++) newArray[i] = array[which[i]]; } return newArray; } unsigned char * whichUnsignedChar(unsigned char * array , int number, const int * which) { unsigned char * newArray = NULL; if (array && number) { int i ; newArray = new unsigned char[number]; for (i = 0; i < number; i++) newArray[i] = array[which[i]]; } return newArray; } // Replace Clp Matrix (current is not deleted) void ClpModel::replaceMatrix( ClpMatrixBase * matrix, bool deleteCurrent) { if (deleteCurrent) delete matrix_; matrix_ = matrix; whatsChanged_ = 0; // Too big a change } // Subproblem constructor ClpModel::ClpModel ( const ClpModel * rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn, bool dropNames, bool dropIntegers) : specialOptions_(rhs->specialOptions_), maximumColumns_(-1), maximumRows_(-1), maximumInternalColumns_(-1), maximumInternalRows_(-1), savedRowScale_(NULL), savedColumnScale_(NULL) { defaultHandler_ = rhs->defaultHandler_; if (defaultHandler_) handler_ = new CoinMessageHandler(*rhs->handler_); else handler_ = rhs->handler_; eventHandler_ = rhs->eventHandler_->clone(); randomNumberGenerator_ = rhs->randomNumberGenerator_; messages_ = rhs->messages_; coinMessages_ = rhs->coinMessages_; maximumColumns_ = -1; maximumRows_ = -1; maximumInternalColumns_ = -1; maximumInternalRows_ = -1; savedRowScale_ = NULL; savedColumnScale_ = NULL; intParam_[ClpMaxNumIteration] = rhs->intParam_[ClpMaxNumIteration]; intParam_[ClpMaxNumIterationHotStart] = rhs->intParam_[ClpMaxNumIterationHotStart]; intParam_[ClpNameDiscipline] = rhs->intParam_[ClpNameDiscipline] ; dblParam_[ClpDualObjectiveLimit] = rhs->dblParam_[ClpDualObjectiveLimit]; dblParam_[ClpPrimalObjectiveLimit] = rhs->dblParam_[ClpPrimalObjectiveLimit]; dblParam_[ClpDualTolerance] = rhs->dblParam_[ClpDualTolerance]; dblParam_[ClpPrimalTolerance] = rhs->dblParam_[ClpPrimalTolerance]; dblParam_[ClpObjOffset] = rhs->dblParam_[ClpObjOffset]; dblParam_[ClpMaxSeconds] = rhs->dblParam_[ClpMaxSeconds]; dblParam_[ClpMaxWallSeconds] = rhs->dblParam_[ClpMaxWallSeconds]; dblParam_[ClpPresolveTolerance] = rhs->dblParam_[ClpPresolveTolerance]; #ifndef CLP_NO_STD strParam_[ClpProbName] = rhs->strParam_[ClpProbName]; #endif specialOptions_ = rhs->specialOptions_; optimizationDirection_ = rhs->optimizationDirection_; objectiveValue_ = rhs->objectiveValue_; smallElement_ = rhs->smallElement_; objectiveScale_ = rhs->objectiveScale_; rhsScale_ = rhs->rhsScale_; numberIterations_ = rhs->numberIterations_; solveType_ = rhs->solveType_; whatsChanged_ = 0; // Too big a change problemStatus_ = rhs->problemStatus_; secondaryStatus_ = rhs->secondaryStatus_; // check valid lists int numberBad = 0; int i; for (i = 0; i < numberRows; i++) if (whichRow[i] < 0 || whichRow[i] >= rhs->numberRows_) numberBad++; CoinAssertHint(!numberBad, "Bad row list for subproblem constructor"); numberBad = 0; for (i = 0; i < numberColumns; i++) if (whichColumn[i] < 0 || whichColumn[i] >= rhs->numberColumns_) numberBad++; CoinAssertHint(!numberBad, "Bad Column list for subproblem constructor"); numberRows_ = numberRows; numberColumns_ = numberColumns; userPointer_ = rhs->userPointer_; trustedUserPointer_ = rhs->trustedUserPointer_; numberThreads_ = 0; #ifndef CLP_NO_STD if (!dropNames) { unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { rowNames_.push_back(rhs->rowNames_[whichRow[iRow]]); maxLength = CoinMax(maxLength, static_cast (strlen(rowNames_[iRow].c_str()))); } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { columnNames_.push_back(rhs->columnNames_[whichColumn[iColumn]]); maxLength = CoinMax(maxLength, static_cast (strlen(columnNames_[iColumn].c_str()))); } lengthNames_ = static_cast (maxLength); } else { lengthNames_ = 0; rowNames_ = std::vector (); columnNames_ = std::vector (); } #endif if (rhs->integerType_ && !dropIntegers) { integerType_ = whichChar(rhs->integerType_, numberColumns, whichColumn); } else { integerType_ = NULL; } if (rhs->rowActivity_) { rowActivity_ = whichDouble(rhs->rowActivity_, numberRows, whichRow); dual_ = whichDouble(rhs->dual_, numberRows, whichRow); columnActivity_ = whichDouble(rhs->columnActivity_, numberColumns, whichColumn); reducedCost_ = whichDouble(rhs->reducedCost_, numberColumns, whichColumn); } else { rowActivity_ = NULL; columnActivity_ = NULL; dual_ = NULL; reducedCost_ = NULL; } rowLower_ = whichDouble(rhs->rowLower_, numberRows, whichRow); rowUpper_ = whichDouble(rhs->rowUpper_, numberRows, whichRow); columnLower_ = whichDouble(rhs->columnLower_, numberColumns, whichColumn); columnUpper_ = whichDouble(rhs->columnUpper_, numberColumns, whichColumn); if (rhs->objective_) objective_ = rhs->objective_->subsetClone(numberColumns, whichColumn); else objective_ = NULL; rowObjective_ = whichDouble(rhs->rowObjective_, numberRows, whichRow); // status has to be done in two stages if (rhs->status_) { status_ = new unsigned char[numberColumns_+numberRows_]; unsigned char * rowStatus = whichUnsignedChar(rhs->status_ + rhs->numberColumns_, numberRows_, whichRow); unsigned char * columnStatus = whichUnsignedChar(rhs->status_, numberColumns_, whichColumn); CoinMemcpyN(rowStatus, numberRows_, status_ + numberColumns_); delete [] rowStatus; CoinMemcpyN(columnStatus, numberColumns_, status_); delete [] columnStatus; } else { status_=NULL; } ray_ = NULL; if (problemStatus_ == 1) ray_ = whichDouble (rhs->ray_, numberRows, whichRow); else if (problemStatus_ == 2) ray_ = whichDouble (rhs->ray_, numberColumns, whichColumn); rowScale_ = NULL; columnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; scalingFlag_ = rhs->scalingFlag_; rowCopy_ = NULL; scaledMatrix_ = NULL; matrix_ = NULL; if (rhs->matrix_) { matrix_ = rhs->matrix_->subsetClone(numberRows, whichRow, numberColumns, whichColumn); } randomNumberGenerator_ = rhs->randomNumberGenerator_; } #ifndef CLP_NO_STD // Copies in names void ClpModel::copyNames(const std::vector & rowNames, const std::vector & columnNames) { unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { rowNames_.push_back(rowNames[iRow]); maxLength = CoinMax(maxLength, static_cast (strlen(rowNames_[iRow].c_str()))); } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { columnNames_.push_back(columnNames[iColumn]); maxLength = CoinMax(maxLength, static_cast (strlen(columnNames_[iColumn].c_str()))); } lengthNames_ = static_cast (maxLength); } // Return name or Rnnnnnnn std::string ClpModel::getRowName(int iRow) const { #ifndef NDEBUG if (iRow < 0 || iRow >= numberRows_) { indexError(iRow, "getRowName"); } #endif int size = static_cast(rowNames_.size()); if (size > iRow) { return rowNames_[iRow]; } else { char name[9]; sprintf(name, "R%7.7d", iRow); std::string rowName(name); return rowName; } } // Set row name void ClpModel::setRowName(int iRow, std::string &name) { #ifndef NDEBUG if (iRow < 0 || iRow >= numberRows_) { indexError(iRow, "setRowName"); } #endif unsigned int maxLength = lengthNames_; int size = static_cast(rowNames_.size()); if (size <= iRow) rowNames_.resize(iRow + 1); rowNames_[iRow] = name; maxLength = CoinMax(maxLength, static_cast (strlen(name.c_str()))); // May be too big - but we would have to check both rows and columns to be exact lengthNames_ = static_cast (maxLength); } // Return name or Cnnnnnnn std::string ClpModel::getColumnName(int iColumn) const { #ifndef NDEBUG if (iColumn < 0 || iColumn >= numberColumns_) { indexError(iColumn, "getColumnName"); } #endif int size = static_cast(columnNames_.size()); if (size > iColumn) { return columnNames_[iColumn]; } else { char name[9]; sprintf(name, "C%7.7d", iColumn); std::string columnName(name); return columnName; } } // Set column name void ClpModel::setColumnName(int iColumn, std::string &name) { #ifndef NDEBUG if (iColumn < 0 || iColumn >= numberColumns_) { indexError(iColumn, "setColumnName"); } #endif unsigned int maxLength = lengthNames_; int size = static_cast(columnNames_.size()); if (size <= iColumn) columnNames_.resize(iColumn + 1); columnNames_[iColumn] = name; maxLength = CoinMax(maxLength, static_cast (strlen(name.c_str()))); // May be too big - but we would have to check both columns and columns to be exact lengthNames_ = static_cast (maxLength); } // Copies in Row names - modifies names first .. last-1 void ClpModel::copyRowNames(const std::vector & rowNames, int first, int last) { // Do column names if necessary if (!lengthNames_&&numberColumns_) { lengthNames_=8; copyColumnNames(NULL,0,numberColumns_); } unsigned int maxLength = lengthNames_; int size = static_cast(rowNames_.size()); if (size != numberRows_) rowNames_.resize(numberRows_); int iRow; for (iRow = first; iRow < last; iRow++) { rowNames_[iRow] = rowNames[iRow-first]; maxLength = CoinMax(maxLength, static_cast (strlen(rowNames_[iRow-first].c_str()))); } // May be too big - but we would have to check both rows and columns to be exact lengthNames_ = static_cast (maxLength); } // Copies in Column names - modifies names first .. last-1 void ClpModel::copyColumnNames(const std::vector & columnNames, int first, int last) { // Do row names if necessary if (!lengthNames_&&numberRows_) { lengthNames_=8; copyRowNames(NULL,0,numberRows_); } unsigned int maxLength = lengthNames_; int size = static_cast(columnNames_.size()); if (size != numberColumns_) columnNames_.resize(numberColumns_); int iColumn; for (iColumn = first; iColumn < last; iColumn++) { columnNames_[iColumn] = columnNames[iColumn-first]; maxLength = CoinMax(maxLength, static_cast (strlen(columnNames_[iColumn-first].c_str()))); } // May be too big - but we would have to check both rows and columns to be exact lengthNames_ = static_cast (maxLength); } // Copies in Row names - modifies names first .. last-1 void ClpModel::copyRowNames(const char * const * rowNames, int first, int last) { // Do column names if necessary if (!lengthNames_&&numberColumns_) { lengthNames_=8; copyColumnNames(NULL,0,numberColumns_); } unsigned int maxLength = lengthNames_; int size = static_cast(rowNames_.size()); if (size != numberRows_) rowNames_.resize(numberRows_); int iRow; for (iRow = first; iRow < last; iRow++) { if (rowNames && rowNames[iRow-first] && strlen(rowNames[iRow-first])) { rowNames_[iRow] = rowNames[iRow-first]; maxLength = CoinMax(maxLength, static_cast (strlen(rowNames[iRow-first]))); } else { maxLength = CoinMax(maxLength, static_cast (8)); char name[9]; sprintf(name, "R%7.7d", iRow); rowNames_[iRow] = name; } } // May be too big - but we would have to check both rows and columns to be exact lengthNames_ = static_cast (maxLength); } // Copies in Column names - modifies names first .. last-1 void ClpModel::copyColumnNames(const char * const * columnNames, int first, int last) { // Do row names if necessary if (!lengthNames_&&numberRows_) { lengthNames_=8; copyRowNames(NULL,0,numberRows_); } unsigned int maxLength = lengthNames_; int size = static_cast(columnNames_.size()); if (size != numberColumns_) columnNames_.resize(numberColumns_); int iColumn; for (iColumn = first; iColumn < last; iColumn++) { if (columnNames && columnNames[iColumn-first] && strlen(columnNames[iColumn-first])) { columnNames_[iColumn] = columnNames[iColumn-first]; maxLength = CoinMax(maxLength, static_cast (strlen(columnNames[iColumn-first]))); } else { maxLength = CoinMax(maxLength, static_cast (8)); char name[9]; sprintf(name, "C%7.7d", iColumn); columnNames_[iColumn] = name; } } // May be too big - but we would have to check both rows and columns to be exact lengthNames_ = static_cast (maxLength); } #endif // Primal objective limit void ClpModel::setPrimalObjectiveLimit(double value) { dblParam_[ClpPrimalObjectiveLimit] = value; } // Dual objective limit void ClpModel::setDualObjectiveLimit(double value) { dblParam_[ClpDualObjectiveLimit] = value; } // Objective offset void ClpModel::setObjectiveOffset(double value) { dblParam_[ClpObjOffset] = value; } // Solve a problem with no elements - return status int ClpModel::emptyProblem(int * infeasNumber, double * infeasSum, bool printMessage) { secondaryStatus_ = 6; // so user can see something odd if (printMessage) handler_->message(CLP_EMPTY_PROBLEM, messages_) << numberRows_ << numberColumns_ << 0 << CoinMessageEol; int returnCode = 0; if (numberRows_ || numberColumns_) { if (!status_) { status_ = new unsigned char[numberRows_+numberColumns_]; CoinZeroN(status_, numberRows_ + numberColumns_); } } // status is set directly (as can be used by Interior methods) // check feasible int numberPrimalInfeasibilities = 0; double sumPrimalInfeasibilities = 0.0; int numberDualInfeasibilities = 0; double sumDualInfeasibilities = 0.0; if (numberRows_) { for (int i = 0; i < numberRows_; i++) { dual_[i] = 0.0; if (rowLower_[i] <= rowUpper_[i]) { if (rowLower_[i] > -1.0e30 || rowUpper_[i] < 1.0e30) { if (rowLower_[i] <= 0.0 && rowUpper_[i] >= 0.0) { if (fabs(rowLower_[i]) < fabs(rowUpper_[i])) rowActivity_[i] = rowLower_[i]; else rowActivity_[i] = rowUpper_[i]; } else { rowActivity_[i] = 0.0; numberPrimalInfeasibilities++; sumPrimalInfeasibilities += CoinMin(rowLower_[i], -rowUpper_[i]); returnCode = 1; } } else { rowActivity_[i] = 0.0; } } else { rowActivity_[i] = 0.0; numberPrimalInfeasibilities++; sumPrimalInfeasibilities += rowLower_[i] - rowUpper_[i]; returnCode = 1; } status_[i+numberColumns_] = 1; } } objectiveValue_ = 0.0; if (numberColumns_) { const double * cost = objective(); for (int i = 0; i < numberColumns_; i++) { reducedCost_[i] = cost[i]; double objValue = cost[i] * optimizationDirection_; if (columnLower_[i] <= columnUpper_[i]) { if (columnLower_[i] > -1.0e30 || columnUpper_[i] < 1.0e30) { if (!objValue) { if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) { columnActivity_[i] = columnLower_[i]; status_[i] = 3; } else { columnActivity_[i] = columnUpper_[i]; status_[i] = 2; } } else if (objValue > 0.0) { if (columnLower_[i] > -1.0e30) { columnActivity_[i] = columnLower_[i]; status_[i] = 3; } else { columnActivity_[i] = columnUpper_[i]; status_[i] = 2; numberDualInfeasibilities++;; sumDualInfeasibilities += fabs(objValue); returnCode |= 2; } objectiveValue_ += columnActivity_[i] * objValue; } else { if (columnUpper_[i] < 1.0e30) { columnActivity_[i] = columnUpper_[i]; status_[i] = 2; } else { columnActivity_[i] = columnLower_[i]; status_[i] = 3; numberDualInfeasibilities++;; sumDualInfeasibilities += fabs(objValue); returnCode |= 2; } objectiveValue_ += columnActivity_[i] * objValue; } } else { columnActivity_[i] = 0.0; if (objValue) { numberDualInfeasibilities++;; sumDualInfeasibilities += fabs(objValue); returnCode |= 2; } status_[i] = 0; } } else { if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) { columnActivity_[i] = columnLower_[i]; status_[i] = 3; } else { columnActivity_[i] = columnUpper_[i]; status_[i] = 2; } numberPrimalInfeasibilities++; sumPrimalInfeasibilities += columnLower_[i] - columnUpper_[i]; returnCode |= 1; } } } objectiveValue_ /= (objectiveScale_ * rhsScale_); if (infeasNumber) { infeasNumber[0] = numberDualInfeasibilities; infeasSum[0] = sumDualInfeasibilities; infeasNumber[1] = numberPrimalInfeasibilities; infeasSum[1] = sumPrimalInfeasibilities; } if (returnCode == 3) returnCode = 4; return returnCode; } #ifndef SLIM_NOIO /* Write the problem in MPS format to the specified file. Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex (later)
Returns non-zero on I/O error */ int ClpModel::writeMps(const char *filename, int formatType, int numberAcross, double objSense) const { matrix_->setDimensions(numberRows_, numberColumns_); // Get multiplier for objective function - default 1.0 double * objective = new double[numberColumns_]; CoinMemcpyN(getObjCoefficients(), numberColumns_, objective); if (objSense * getObjSense() < 0.0) { for (int i = 0; i < numberColumns_; ++i) objective [i] = - objective[i]; } // get names const char * const * const rowNames = rowNamesAsChar(); const char * const * const columnNames = columnNamesAsChar(); CoinMpsIO writer; writer.passInMessageHandler(handler_); *writer.messagesPointer() = coinMessages(); writer.setMpsData(*(matrix_->getPackedMatrix()), COIN_DBL_MAX, getColLower(), getColUpper(), objective, reinterpret_cast (NULL) /*integrality*/, getRowLower(), getRowUpper(), columnNames, rowNames); // Pass in array saying if each variable integer writer.copyInIntegerInformation(integerInformation()); writer.setObjectiveOffset(objectiveOffset()); delete [] objective; CoinPackedMatrix * quadratic = NULL; #ifndef SLIM_CLP // allow for quadratic objective #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); #endif int returnCode = writer.writeMps(filename, 0 /* do not gzip it*/, formatType, numberAcross, quadratic); if (rowNames) { deleteNamesAsChar(rowNames, numberRows_ + 1); deleteNamesAsChar(columnNames, numberColumns_); } return returnCode; } #ifndef CLP_NO_STD // Create row names as char ** const char * const * ClpModel::rowNamesAsChar() const { char ** rowNames = NULL; if (lengthNames()) { rowNames = new char * [numberRows_+1]; int numberNames = static_cast(rowNames_.size()); numberNames = CoinMin(numberRows_, numberNames); int iRow; for (iRow = 0; iRow < numberNames; iRow++) { if (rowName(iRow) != "") { rowNames[iRow] = CoinStrdup(rowName(iRow).c_str()); } else { char name[9]; sprintf(name, "R%7.7d", iRow); rowNames[iRow] = CoinStrdup(name); } #ifdef STRIPBLANKS char * xx = rowNames[iRow]; int i; int length = strlen(xx); int n = 0; for (i = 0; i < length; i++) { if (xx[i] != ' ') xx[n++] = xx[i]; } xx[n] = '\0'; #endif } char name[9]; for ( ; iRow < numberRows_; iRow++) { sprintf(name, "R%7.7d", iRow); rowNames[iRow] = CoinStrdup(name); } rowNames[numberRows_] = CoinStrdup("OBJROW"); } return reinterpret_cast(rowNames); } // Create column names as char ** const char * const * ClpModel::columnNamesAsChar() const { char ** columnNames = NULL; if (lengthNames()) { columnNames = new char * [numberColumns_]; int numberNames = static_cast(columnNames_.size()); numberNames = CoinMin(numberColumns_, numberNames); int iColumn; for (iColumn = 0; iColumn < numberNames; iColumn++) { if (columnName(iColumn) != "") { columnNames[iColumn] = CoinStrdup(columnName(iColumn).c_str()); } else { char name[9]; sprintf(name, "C%7.7d", iColumn); columnNames[iColumn] = CoinStrdup(name); } #ifdef STRIPBLANKS char * xx = columnNames[iColumn]; int i; int length = strlen(xx); int n = 0; for (i = 0; i < length; i++) { if (xx[i] != ' ') xx[n++] = xx[i]; } xx[n] = '\0'; #endif } char name[9]; for ( ; iColumn < numberColumns_; iColumn++) { sprintf(name, "C%7.7d", iColumn); columnNames[iColumn] = CoinStrdup(name); } } return /*reinterpret_cast*/(columnNames); } // Delete char * version of names void ClpModel::deleteNamesAsChar(const char * const * names, int number) const { for (int i = 0; i < number; i++) { free(const_cast(names[i])); } delete [] const_cast(names); } #endif #endif // Pass in Event handler (cloned and deleted at end) void ClpModel::passInEventHandler(const ClpEventHandler * eventHandler) { delete eventHandler_; eventHandler_ = eventHandler->clone(); } // Sets or unsets scaling, 0 -off, 1 on, 2 dynamic(later) void ClpModel::scaling(int mode) { // If mode changes then we treat as new matrix (need new row copy) if (mode != scalingFlag_) { whatsChanged_ &= ~(2 + 4 + 8); // Get rid of scaled matrix setClpScaledMatrix(NULL); } if (mode > 0 && mode < 6) { scalingFlag_ = mode; } else if (!mode) { scalingFlag_ = 0; setRowScale(NULL); setColumnScale(NULL); } } void ClpModel::times(double scalar, const double * x, double * y) const { if (!scaledMatrix_ || !rowScale_) { if (rowScale_) matrix_->times(scalar, x, y, rowScale_, columnScale_); else matrix_->times(scalar, x, y); } else { scaledMatrix_->times(scalar, x, y); } } void ClpModel::transposeTimes(double scalar, const double * x, double * y) const { if (!scaledMatrix_ || !rowScale_) { if (rowScale_) matrix_->transposeTimes(scalar, x, y, rowScale_, columnScale_, NULL); else matrix_->transposeTimes(scalar, x, y); } else { scaledMatrix_->transposeTimes(scalar, x, y); } } // Does much of scaling void ClpModel::gutsOfScaling() { int i; if (rowObjective_) { for (i = 0; i < numberRows_; i++) rowObjective_[i] /= rowScale_[i]; } for (i = 0; i < numberRows_; i++) { double multiplier = rowScale_[i]; double inverseMultiplier = 1.0 / multiplier; rowActivity_[i] *= multiplier; dual_[i] *= inverseMultiplier; if (rowLower_[i] > -1.0e30) rowLower_[i] *= multiplier; else rowLower_[i] = -COIN_DBL_MAX; if (rowUpper_[i] < 1.0e30) rowUpper_[i] *= multiplier; else rowUpper_[i] = COIN_DBL_MAX; } for (i = 0; i < numberColumns_; i++) { double multiplier = 1.0 * inverseColumnScale_[i]; columnActivity_[i] *= multiplier; reducedCost_[i] *= columnScale_[i]; if (columnLower_[i] > -1.0e30) columnLower_[i] *= multiplier; else columnLower_[i] = -COIN_DBL_MAX; if (columnUpper_[i] < 1.0e30) columnUpper_[i] *= multiplier; else columnUpper_[i] = COIN_DBL_MAX; } //now replace matrix //and objective matrix_->reallyScale(rowScale_, columnScale_); objective_->reallyScale(columnScale_); } /* If we constructed a "really" scaled model then this reverses the operation. Quantities may not be exactly as they were before due to rounding errors */ void ClpModel::unscale() { if (rowScale_) { int i; // reverse scaling for (i = 0; i < numberRows_; i++) rowScale_[i] = 1.0 * inverseRowScale_[i]; for (i = 0; i < numberColumns_; i++) columnScale_[i] = 1.0 * inverseColumnScale_[i]; gutsOfScaling(); } scalingFlag_ = 0; setRowScale(NULL); setColumnScale(NULL); } void ClpModel::setSpecialOptions(unsigned int value) { specialOptions_ = value; } /* This creates a coinModel object */ CoinModel * ClpModel::createCoinModel() const { CoinModel * coinModel = new CoinModel(); CoinPackedMatrix matrixByRow; matrixByRow.setExtraGap(0.0); matrixByRow.setExtraMajor(0.0); matrixByRow.reverseOrderedCopyOf(*matrix()); coinModel->setObjectiveOffset(objectiveOffset()); coinModel->setProblemName(problemName().c_str()); // 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(); int i; for (i = 0; i < numberRows_; i++) { coinModel->addRow(rowLength[i], column + rowStart[i], element + rowStart[i], rowLower_[i], rowUpper_[i]); } // Now do column part const double * objective = this->objective(); for (i = 0; i < numberColumns_; i++) { coinModel->setColumnBounds(i, columnLower_[i], columnUpper_[i]); coinModel->setColumnObjective(i, objective[i]); } for ( i = 0; i < numberColumns_; i++) { if (isInteger(i)) coinModel->setColumnIsInteger(i, true); } // do names - clear out coinModel->zapRowNames(); coinModel->zapColumnNames(); for (i = 0; i < numberRows_; i++) { char temp[30]; strcpy(temp, rowName(i).c_str()); size_t length = strlen(temp); for (size_t j = 0; j < length; j++) { if (temp[j] == '-') temp[j] = '_'; } coinModel->setRowName(i, temp); } for (i = 0; i < numberColumns_; i++) { char temp[30]; strcpy(temp, columnName(i).c_str()); size_t length = strlen(temp); for (size_t j = 0; j < length; j++) { if (temp[j] == '-') temp[j] = '_'; } coinModel->setColumnName(i, temp); } ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); if (obj) { const CoinPackedMatrix * quadObj = obj->quadraticObjective(); // add in quadratic const double * element = quadObj->getElements(); const int * row = quadObj->getIndices(); const CoinBigIndex * columnStart = quadObj->getVectorStarts(); const int * columnLength = quadObj->getVectorLengths(); for (i = 0; i < numberColumns_; i++) { int nels = columnLength[i]; if (nels) { CoinBigIndex start = columnStart[i]; double constant = coinModel->getColumnObjective(i); char temp[100000]; char temp2[30]; sprintf(temp, "%g", constant); for (CoinBigIndex k = start; k < start + nels; k++) { int kColumn = row[k]; double value = element[k]; #if 1 // ampl gives twice with assumed 0.5 if (kColumn < i) continue; else if (kColumn == i) value *= 0.5; #endif if (value == 1.0) sprintf(temp2, "+%s", coinModel->getColumnName(kColumn)); else if (value == -1.0) sprintf(temp2, "-%s", coinModel->getColumnName(kColumn)); else if (value > 0.0) sprintf(temp2, "+%g*%s", value, coinModel->getColumnName(kColumn)); else sprintf(temp2, "%g*%s", value, coinModel->getColumnName(kColumn)); strcat(temp, temp2); assert (strlen(temp) < 100000); } coinModel->setObjective(i, temp); if (logLevel() > 2) printf("el for objective column %s is %s\n", coinModel->getColumnName(i), temp); } } } return coinModel; } // Start or reset using maximumRows_ and Columns_ void ClpModel::startPermanentArrays() { COIN_DETAIL_PRINT(printf("startperm a %d rows, %d maximum rows\n", numberRows_, maximumRows_)); if ((specialOptions_ & 65536) != 0) { if (numberRows_ > maximumRows_ || numberColumns_ > maximumColumns_) { if (numberRows_ > maximumRows_) { if (maximumRows_ > 0) maximumRows_ = numberRows_ + 10 + numberRows_ / 100; else maximumRows_ = numberRows_; } if (numberColumns_ > maximumColumns_) { if (maximumColumns_ > 0) maximumColumns_ = numberColumns_ + 10 + numberColumns_ / 100; else maximumColumns_ = numberColumns_; } // need to make sure numberRows_ OK and size of matrices resize(maximumRows_, maximumColumns_); COIN_DETAIL_PRINT(printf("startperm b %d rows, %d maximum rows\n", numberRows_, maximumRows_)); } else { return; } } else { specialOptions_ |= 65536; maximumRows_ = numberRows_; maximumColumns_ = numberColumns_; baseMatrix_ = *matrix(); baseMatrix_.cleanMatrix(); baseRowCopy_.setExtraGap(0.0); baseRowCopy_.setExtraMajor(0.0); baseRowCopy_.reverseOrderedCopyOf(baseMatrix_); COIN_DETAIL_PRINT(printf("startperm c %d rows, %d maximum rows\n", numberRows_, maximumRows_)); } } // Stop using maximumRows_ and Columns_ void ClpModel::stopPermanentArrays() { specialOptions_ &= ~65536; maximumRows_ = -1; maximumColumns_ = -1; if (rowScale_ != savedRowScale_) { delete [] savedRowScale_; delete [] savedColumnScale_; } savedRowScale_ = NULL; savedColumnScale_ = NULL; } // Set new row matrix void ClpModel::setNewRowCopy(ClpMatrixBase * newCopy) { delete rowCopy_; rowCopy_ = newCopy; } /* Find a network subset. rotate array should be numberRows. On output -1 not in network 0 in network as is 1 in network with signs swapped Returns number of network rows (positive if exact network, negative if needs extra row) From Gulpinar, Gutin, Maros and Mitra */ int ClpModel::findNetwork(char * rotate, double fractionNeeded) { int * mapping = new int [numberRows_]; // Get column copy CoinPackedMatrix * columnCopy = matrix(); // Get a row copy in standard format CoinPackedMatrix * copy = new CoinPackedMatrix(); copy->setExtraGap(0.0); copy->setExtraMajor(0.0); copy->reverseOrderedCopyOf(*columnCopy); // make sure ordered and no gaps copy->cleanMatrix(); // get matrix data pointers const int * columnIn = copy->getIndices(); const CoinBigIndex * rowStartIn = copy->getVectorStarts(); const int * rowLength = copy->getVectorLengths(); const double * elementByRowIn = copy->getElements(); int iRow, iColumn; int numberEligible = 0; int numberIn = 0; int numberElements = 0; for (iRow = 0; iRow < numberRows_; iRow++) { bool possible = true; mapping[iRow] = -1; rotate[iRow] = -1; for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) { //int iColumn = column[j]; double value = elementByRowIn[j]; if (fabs(value) != 1.0) { possible = false; break; } } if (rowLength[iRow] && possible) { mapping[iRow] = numberEligible; numberEligible++; numberElements += rowLength[iRow]; } } if (numberEligible < fractionNeeded * numberRows_) { delete [] mapping; delete copy; return 0; } // create arrays int * eligible = new int [numberRows_]; int * column = new int [numberElements]; CoinBigIndex * rowStart = new CoinBigIndex [numberEligible+1]; char * elementByRow = new char [numberElements]; numberEligible = 0; numberElements = 0; rowStart[0] = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (mapping[iRow] < 0) continue; assert (numberEligible == mapping[iRow]); rotate[numberEligible] = 0; for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) { column[numberElements] = columnIn[j]; double value = elementByRowIn[j]; if (value == 1.0) elementByRow[numberElements++] = 1; else elementByRow[numberElements++] = -1; } numberEligible++; rowStart[numberEligible] = numberElements; } // get rid of copy to save space delete copy; const int * rowIn = columnCopy->getIndices(); const CoinBigIndex * columnStartIn = columnCopy->getVectorStarts(); const int * columnLengthIn = columnCopy->getVectorLengths(); const double * elementByColumnIn = columnCopy->getElements(); int * columnLength = new int [numberColumns_]; // May just be that is a network - worth checking bool isNetworkAlready = true; bool trueNetwork = true; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double product = 1.0; int n = 0; for (CoinBigIndex j = columnStartIn[iColumn]; j < columnStartIn[iColumn] + columnLengthIn[iColumn]; j++) { iRow = mapping[rowIn[j]]; if (iRow >= 0) { n++; product *= elementByColumnIn[j]; } } if (n >= 2) { if (product != -1.0 || n > 2) isNetworkAlready = false; } else if (n == 1) { trueNetwork = false; } columnLength[iColumn] = n; } if (!isNetworkAlready) { // For sorting double * count = new double [numberRows_]; int * which = new int [numberRows_]; int numberLast = -1; // Count for columns char * columnCount = new char[numberColumns_]; memset(columnCount, 0, numberColumns_); char * currentColumnCount = new char[numberColumns_]; // Now do main loop while (numberIn > numberLast) { numberLast = numberIn; int numberLeft = 0; for (iRow = 0; iRow < numberEligible; iRow++) { if (rotate[iRow] == 0 && rowStart[iRow+1] > rowStart[iRow]) { which[numberLeft] = iRow; int merit = 0; bool OK = true; bool reflectionOK = true; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { iColumn = column[j]; int iCount = columnCount[iColumn]; int absCount = CoinAbs(iCount); if (absCount < 2) { merit = CoinMax(columnLength[iColumn] - absCount - 1, merit); if (elementByRow[j] == iCount) OK = false; else if (elementByRow[j] == -iCount) reflectionOK = false; } else { merit = -2; break; } } if (merit > -2 && (OK || reflectionOK) && (!OK || !reflectionOK || !numberIn)) { //if (!numberLast) merit=1; count[numberLeft++] = (rowStart[iRow+1] - rowStart[iRow] - 1) * (static_cast(merit)); if (OK) rotate[iRow] = 0; else rotate[iRow] = 1; } else { // no good rotate[iRow] = -1; } } } CoinSort_2(count, count + numberLeft, which); // Get G memset(currentColumnCount, 0, numberColumns_); for (iRow = 0; iRow < numberLeft; iRow++) { int jRow = which[iRow]; bool possible = true; for (int i = 0; i < numberIn; i++) { for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) { if (currentColumnCount[column[j]]) { possible = false; break; } } } if (possible) { rotate[jRow] = static_cast(rotate[jRow] + 2); eligible[numberIn++] = jRow; char multiplier = static_cast((rotate[jRow] == 2) ? 1 : -1); for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) { iColumn = column[j]; currentColumnCount[iColumn]++; int iCount = columnCount[iColumn]; int absCount = CoinAbs(iCount); if (!absCount) { columnCount[iColumn] = static_cast(elementByRow[j] * multiplier); } else { columnCount[iColumn] = 2; } } } } } #ifndef NDEBUG for (iRow = 0; iRow < numberIn; iRow++) { int kRow = eligible[iRow]; assert (rotate[kRow] >= 2); } #endif trueNetwork = true; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (CoinAbs(static_cast(columnCount[iColumn])) == 1) { trueNetwork = false; break; } } delete [] currentColumnCount; delete [] columnCount; delete [] which; delete [] count; } else { numberIn = numberEligible; for (iRow = 0; iRow < numberRows_; iRow++) { int kRow = mapping[iRow]; if (kRow >= 0) { rotate[kRow] = 2; } } } if (!trueNetwork) numberIn = - numberIn; delete [] column; delete [] rowStart; delete [] elementByRow; delete [] columnLength; // redo rotate char * rotate2 = CoinCopyOfArray(rotate, numberEligible); for (iRow = 0; iRow < numberRows_; iRow++) { int kRow = mapping[iRow]; if (kRow >= 0) { int iState = rotate2[kRow]; if (iState > 1) iState -= 2; else iState = -1; rotate[iRow] = static_cast(iState); } else { rotate[iRow] = -1; } } delete [] rotate2; delete [] eligible; delete [] mapping; return numberIn; } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDataSave::ClpDataSave () { dualBound_ = 0.0; infeasibilityCost_ = 0.0; sparseThreshold_ = 0; pivotTolerance_ = 0.0; zeroFactorizationTolerance_ = 1.0e13; zeroSimplexTolerance_ = 1.0e-13; acceptablePivot_ = 0.0; objectiveScale_ = 1.0; perturbation_ = 0; forceFactorization_ = -1; scalingFlag_ = 0; specialOptions_ = 0; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDataSave::ClpDataSave (const ClpDataSave & rhs) { dualBound_ = rhs.dualBound_; infeasibilityCost_ = rhs.infeasibilityCost_; pivotTolerance_ = rhs.pivotTolerance_; zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_; zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_; acceptablePivot_ = rhs.acceptablePivot_; objectiveScale_ = rhs.objectiveScale_; sparseThreshold_ = rhs.sparseThreshold_; perturbation_ = rhs.perturbation_; forceFactorization_ = rhs.forceFactorization_; scalingFlag_ = rhs.scalingFlag_; specialOptions_ = rhs.specialOptions_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDataSave::~ClpDataSave () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDataSave & ClpDataSave::operator=(const ClpDataSave& rhs) { if (this != &rhs) { dualBound_ = rhs.dualBound_; infeasibilityCost_ = rhs.infeasibilityCost_; pivotTolerance_ = rhs.pivotTolerance_; zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_; zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_; acceptablePivot_ = rhs.acceptablePivot_; objectiveScale_ = rhs.objectiveScale_; sparseThreshold_ = rhs.sparseThreshold_; perturbation_ = rhs.perturbation_; forceFactorization_ = rhs.forceFactorization_; scalingFlag_ = rhs.scalingFlag_; specialOptions_ = rhs.specialOptions_; } return *this; } // Create C++ lines to get to current state void ClpModel::generateCpp( FILE * fp) { // Stuff that can't be done easily if (!lengthNames_) { // no names fprintf(fp, " clpModel->dropNames();\n"); } ClpModel defaultModel; ClpModel * other = &defaultModel; int iValue1, iValue2; double dValue1, dValue2; iValue1 = this->maximumIterations(); iValue2 = other->maximumIterations(); fprintf(fp, "%d int save_maximumIterations = clpModel->maximumIterations();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setMaximumIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->setMaximumIterations(save_maximumIterations);\n", iValue1 == iValue2 ? 7 : 6); dValue1 = this->primalTolerance(); dValue2 = other->primalTolerance(); fprintf(fp, "%d double save_primalTolerance = clpModel->primalTolerance();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setPrimalTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setPrimalTolerance(save_primalTolerance);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->dualTolerance(); dValue2 = other->dualTolerance(); fprintf(fp, "%d double save_dualTolerance = clpModel->dualTolerance();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setDualTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setDualTolerance(save_dualTolerance);\n", dValue1 == dValue2 ? 7 : 6); iValue1 = this->numberIterations(); iValue2 = other->numberIterations(); fprintf(fp, "%d int save_numberIterations = clpModel->numberIterations();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setNumberIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->setNumberIterations(save_numberIterations);\n", iValue1 == iValue2 ? 7 : 6); dValue1 = this->maximumSeconds(); dValue2 = other->maximumSeconds(); fprintf(fp, "%d double save_maximumSeconds = clpModel->maximumSeconds();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setMaximumSeconds(save_maximumSeconds);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->optimizationDirection(); dValue2 = other->optimizationDirection(); fprintf(fp, "%d double save_optimizationDirection = clpModel->optimizationDirection();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setOptimizationDirection(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setOptimizationDirection(save_optimizationDirection);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->objectiveScale(); dValue2 = other->objectiveScale(); fprintf(fp, "%d double save_objectiveScale = clpModel->objectiveScale();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setObjectiveScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setObjectiveScale(save_objectiveScale);\n", dValue1 == dValue2 ? 7 : 6); dValue1 = this->rhsScale(); dValue2 = other->rhsScale(); fprintf(fp, "%d double save_rhsScale = clpModel->rhsScale();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setRhsScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setRhsScale(save_rhsScale);\n", dValue1 == dValue2 ? 7 : 6); iValue1 = this->scalingFlag(); iValue2 = other->scalingFlag(); fprintf(fp, "%d int save_scalingFlag = clpModel->scalingFlag();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->scaling(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->scaling(save_scalingFlag);\n", iValue1 == iValue2 ? 7 : 6); dValue1 = this->getSmallElementValue(); dValue2 = other->getSmallElementValue(); fprintf(fp, "%d double save_getSmallElementValue = clpModel->getSmallElementValue();\n", dValue1 == dValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setSmallElementValue(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1); fprintf(fp, "%d clpModel->setSmallElementValue(save_getSmallElementValue);\n", dValue1 == dValue2 ? 7 : 6); iValue1 = this->logLevel(); iValue2 = other->logLevel(); fprintf(fp, "%d int save_logLevel = clpModel->logLevel();\n", iValue1 == iValue2 ? 2 : 1); fprintf(fp, "%d clpModel->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1); fprintf(fp, "%d clpModel->setLogLevel(save_logLevel);\n", iValue1 == iValue2 ? 7 : 6); } Clp-1.15.10/src/ClpQuadraticObjective.cpp0000644000076600007660000013540211552601036016561 0ustar coincoin/* $Id: ClpQuadraticObjective.cpp 1723 2011-04-17 15:07:10Z forrest $ */ // 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). #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpQuadraticObjective.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpQuadraticObjective::ClpQuadraticObjective () : ClpObjective() { type_ = 2; objective_ = NULL; quadraticObjective_ = NULL; gradient_ = NULL; numberColumns_ = 0; numberExtendedColumns_ = 0; activated_ = 0; fullMatrix_ = false; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpQuadraticObjective::ClpQuadraticObjective (const double * objective , int numberColumns, const CoinBigIndex * start, const int * column, const double * element, int numberExtendedColumns) : ClpObjective() { type_ = 2; numberColumns_ = numberColumns; if (numberExtendedColumns >= 0) numberExtendedColumns_ = CoinMax(numberColumns_, numberExtendedColumns); else numberExtendedColumns_ = numberColumns_; if (objective) { objective_ = new double [numberExtendedColumns_]; CoinMemcpyN(objective, numberColumns_, objective_); memset(objective_ + numberColumns_, 0, (numberExtendedColumns_ - numberColumns_)*sizeof(double)); } else { objective_ = new double [numberExtendedColumns_]; memset(objective_, 0, numberExtendedColumns_ * sizeof(double)); } if (start) quadraticObjective_ = new CoinPackedMatrix(true, numberColumns, numberColumns, start[numberColumns], element, column, start, NULL); else quadraticObjective_ = NULL; gradient_ = NULL; activated_ = 1; fullMatrix_ = false; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpQuadraticObjective::ClpQuadraticObjective (const ClpQuadraticObjective & rhs, int type) : ClpObjective(rhs) { numberColumns_ = rhs.numberColumns_; numberExtendedColumns_ = rhs.numberExtendedColumns_; fullMatrix_ = rhs.fullMatrix_; if (rhs.objective_) { objective_ = new double [numberExtendedColumns_]; CoinMemcpyN(rhs.objective_, numberExtendedColumns_, objective_); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double [numberExtendedColumns_]; CoinMemcpyN(rhs.gradient_, numberExtendedColumns_, gradient_); } else { gradient_ = NULL; } if (rhs.quadraticObjective_) { // see what type of matrix wanted if (type == 0) { // just copy quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); } else if (type == 1) { // expand to full symmetric fullMatrix_ = true; const int * columnQuadratic1 = rhs.quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart1 = rhs.quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength1 = rhs.quadraticObjective_->getVectorLengths(); const double * quadraticElement1 = rhs.quadraticObjective_->getElements(); CoinBigIndex * columnQuadraticStart2 = new CoinBigIndex [numberExtendedColumns_+1]; int * columnQuadraticLength2 = new int [numberExtendedColumns_]; int iColumn; int numberColumns = rhs.quadraticObjective_->getNumCols(); int numberBelow = 0; int numberAbove = 0; int numberDiagonal = 0; CoinZeroN(columnQuadraticLength2, numberExtendedColumns_); for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (CoinBigIndex j = columnQuadraticStart1[iColumn]; j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) { int jColumn = columnQuadratic1[j]; if (jColumn > iColumn) { numberBelow++; columnQuadraticLength2[jColumn]++; columnQuadraticLength2[iColumn]++; } else if (jColumn == iColumn) { numberDiagonal++; columnQuadraticLength2[iColumn]++; } else { numberAbove++; } } } if (numberAbove > 0) { if (numberAbove == numberBelow) { // already done quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); delete [] columnQuadraticStart2; delete [] columnQuadraticLength2; } else { printf("number above = %d, number below = %d, error\n", numberAbove, numberBelow); abort(); } } else { int numberElements = numberDiagonal + 2 * numberBelow; int * columnQuadratic2 = new int [numberElements]; double * quadraticElement2 = new double [numberElements]; columnQuadraticStart2[0] = 0; numberElements = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int n = columnQuadraticLength2[iColumn]; columnQuadraticLength2[iColumn] = 0; numberElements += n; columnQuadraticStart2[iColumn+1] = numberElements; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { for (CoinBigIndex j = columnQuadraticStart1[iColumn]; j < columnQuadraticStart1[iColumn] + columnQuadraticLength1[iColumn]; j++) { int jColumn = columnQuadratic1[j]; if (jColumn > iColumn) { // put in two places CoinBigIndex put = columnQuadraticLength2[jColumn] + columnQuadraticStart2[jColumn]; columnQuadraticLength2[jColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = iColumn; put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn]; columnQuadraticLength2[iColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = jColumn; } else if (jColumn == iColumn) { CoinBigIndex put = columnQuadraticLength2[iColumn] + columnQuadraticStart2[iColumn]; columnQuadraticLength2[iColumn]++; quadraticElement2[put] = quadraticElement1[j]; columnQuadratic2[put] = iColumn; } else { abort(); } } } // Now create quadraticObjective_ = new CoinPackedMatrix (true, rhs.numberExtendedColumns_, rhs.numberExtendedColumns_, numberElements, quadraticElement2, columnQuadratic2, columnQuadraticStart2, columnQuadraticLength2, 0.0, 0.0); delete [] columnQuadraticStart2; delete [] columnQuadraticLength2; delete [] columnQuadratic2; delete [] quadraticElement2; } } else { fullMatrix_ = false; abort(); // code when needed } } else { quadraticObjective_ = NULL; } } /* Subset constructor. Duplicates are allowed and order is as given. */ ClpQuadraticObjective::ClpQuadraticObjective (const ClpQuadraticObjective &rhs, int numberColumns, const int * whichColumn) : ClpObjective(rhs) { fullMatrix_ = rhs.fullMatrix_; objective_ = NULL; int extra = rhs.numberExtendedColumns_ - rhs.numberColumns_; numberColumns_ = 0; numberExtendedColumns_ = numberColumns + extra; if (numberColumns > 0) { // check valid lists int numberBad = 0; int i; for (i = 0; i < numberColumns; i++) if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_) numberBad++; if (numberBad) throw CoinError("bad column list", "subset constructor", "ClpQuadraticObjective"); numberColumns_ = numberColumns; objective_ = new double[numberExtendedColumns_]; for (i = 0; i < numberColumns_; i++) objective_[i] = rhs.objective_[whichColumn[i]]; CoinMemcpyN(rhs.objective_ + rhs.numberColumns_, (numberExtendedColumns_ - numberColumns_), objective_ + numberColumns_); if (rhs.gradient_) { gradient_ = new double[numberExtendedColumns_]; for (i = 0; i < numberColumns_; i++) gradient_[i] = rhs.gradient_[whichColumn[i]]; CoinMemcpyN(rhs.gradient_ + rhs.numberColumns_, (numberExtendedColumns_ - numberColumns_), gradient_ + numberColumns_); } else { gradient_ = NULL; } } else { gradient_ = NULL; objective_ = NULL; } if (rhs.quadraticObjective_) { quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_, numberColumns, whichColumn, numberColumns, whichColumn); } else { quadraticObjective_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpQuadraticObjective::~ClpQuadraticObjective () { delete [] objective_; delete [] gradient_; delete quadraticObjective_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpQuadraticObjective & ClpQuadraticObjective::operator=(const ClpQuadraticObjective& rhs) { if (this != &rhs) { fullMatrix_ = rhs.fullMatrix_; delete quadraticObjective_; quadraticObjective_ = NULL; delete [] objective_; delete [] gradient_; ClpObjective::operator=(rhs); numberColumns_ = rhs.numberColumns_; numberExtendedColumns_ = rhs.numberExtendedColumns_; if (rhs.objective_) { objective_ = new double [numberExtendedColumns_]; CoinMemcpyN(rhs.objective_, numberExtendedColumns_, objective_); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double [numberExtendedColumns_]; CoinMemcpyN(rhs.gradient_, numberExtendedColumns_, gradient_); } else { gradient_ = NULL; } if (rhs.quadraticObjective_) { quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); } else { quadraticObjective_ = NULL; } } return *this; } // Returns gradient double * ClpQuadraticObjective::gradient(const ClpSimplex * model, const double * solution, double & offset, bool refresh, int includeLinear) { offset = 0.0; bool scaling = false; if (model && (model->rowScale() || model->objectiveScale() != 1.0 || model->optimizationDirection() != 1.0)) scaling = true; const double * cost = NULL; if (model) cost = model->costRegion(); if (!cost) { // not in solve cost = objective_; scaling = false; } if (!scaling) { if (!quadraticObjective_ || !solution || !activated_) { return objective_; } else { if (refresh || !gradient_) { if (!gradient_) gradient_ = new double[numberExtendedColumns_]; const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); const double * quadraticElement = quadraticObjective_->getElements(); offset = 0.0; // use current linear cost region if (includeLinear == 1) CoinMemcpyN(cost, numberExtendedColumns_, gradient_); else if (includeLinear == 2) CoinMemcpyN(objective_, numberExtendedColumns_, gradient_); else memset(gradient_, 0, numberExtendedColumns_ * sizeof(double)); if (activated_) { if (!fullMatrix_) { int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { offset += valueI * valueJ * elementValue; //if (fabs(valueI*valueJ*elementValue)>1.0e-12) //printf("%d %d %g %g %g -> %g\n", // iColumn,jColumn,valueI,valueJ,elementValue, // valueI*valueJ*elementValue); double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient_[iColumn] += gradientI; gradient_[jColumn] += gradientJ; } else { offset += 0.5 * valueI * valueI * elementValue; //if (fabs(valueI*valueI*elementValue)>1.0e-12) //printf("XX %d %g %g -> %g\n", // iColumn,valueI,elementValue, // 0.5*valueI*valueI*elementValue); double gradientI = valueI * elementValue; gradient_[iColumn] += gradientI; } } } } else { // full matrix int iColumn; offset *= 2.0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex j; double value = 0.0; double current = gradient_[iColumn]; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn] * quadraticElement[j]; value += valueJ; } offset += value * solution[iColumn]; gradient_[iColumn] = current + value; } offset *= 0.5; } } } if (model) offset *= model->optimizationDirection() * model->objectiveScale(); return gradient_; } } else { // do scaling assert (solution); // for now only if half assert (!fullMatrix_); if (refresh || !gradient_) { if (!gradient_) gradient_ = new double[numberExtendedColumns_]; double direction = model->optimizationDirection() * model->objectiveScale(); // direction is actually scale out not scale in //if (direction) //direction = 1.0/direction; const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); const double * quadraticElement = quadraticObjective_->getElements(); int iColumn; const double * columnScale = model->columnScale(); // use current linear cost region (already scaled) if (includeLinear == 1) { CoinMemcpyN(model->costRegion(), numberExtendedColumns_, gradient_); } else if (includeLinear == 2) { memset(gradient_ + numberColumns_, 0, (numberExtendedColumns_ - numberColumns_)*sizeof(double)); if (!columnScale) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { gradient_[iColumn] = objective_[iColumn] * direction; } } else { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { gradient_[iColumn] = objective_[iColumn] * direction * columnScale[iColumn]; } } } else { memset(gradient_, 0, numberExtendedColumns_ * sizeof(double)); } if (!columnScale) { if (activated_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; elementValue *= direction; if (iColumn != jColumn) { offset += valueI * valueJ * elementValue; double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient_[iColumn] += gradientI; gradient_[jColumn] += gradientJ; } else { offset += 0.5 * valueI * valueI * elementValue; double gradientI = valueI * elementValue; gradient_[iColumn] += gradientI; } } } } } else { // scaling if (activated_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double scaleI = columnScale[iColumn] * direction; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; double scaleJ = columnScale[jColumn]; elementValue *= scaleI * scaleJ; if (iColumn != jColumn) { offset += valueI * valueJ * elementValue; double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient_[iColumn] += gradientI; gradient_[jColumn] += gradientJ; } else { offset += 0.5 * valueI * valueI * elementValue; double gradientI = valueI * elementValue; gradient_[iColumn] += gradientI; } } } } } } if (model) offset *= model->optimizationDirection(); return gradient_; } } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpObjective * ClpQuadraticObjective::clone() const { return new ClpQuadraticObjective(*this); } /* Subset clone. Duplicates are allowed and order is as given. */ ClpObjective * ClpQuadraticObjective::subsetClone (int numberColumns, const int * whichColumns) const { return new ClpQuadraticObjective(*this, numberColumns, whichColumns); } // Resize objective void ClpQuadraticObjective::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { int newExtended = newNumberColumns + (numberExtendedColumns_ - numberColumns_); int i; double * newArray = new double[newExtended]; if (objective_) CoinMemcpyN(objective_, CoinMin(newExtended, numberExtendedColumns_), newArray); delete [] objective_; objective_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) objective_[i] = 0.0; if (gradient_) { newArray = new double[newExtended]; if (gradient_) CoinMemcpyN(gradient_, CoinMin(newExtended, numberExtendedColumns_), newArray); delete [] gradient_; gradient_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) gradient_[i] = 0.0; } if (quadraticObjective_) { if (newNumberColumns < numberColumns_) { int * which = new int[numberColumns_-newNumberColumns]; int i; for (i = newNumberColumns; i < numberColumns_; i++) which[i-newNumberColumns] = i; quadraticObjective_->deleteRows(numberColumns_ - newNumberColumns, which); quadraticObjective_->deleteCols(numberColumns_ - newNumberColumns, which); delete [] which; } else { quadraticObjective_->setDimensions(newNumberColumns, newNumberColumns); } } numberColumns_ = newNumberColumns; numberExtendedColumns_ = newExtended; } } // Delete columns in objective void ClpQuadraticObjective::deleteSome(int numberToDelete, const int * which) { int newNumberColumns = numberColumns_ - numberToDelete; int newExtended = numberExtendedColumns_ - numberToDelete; if (objective_) { int i ; char * deleted = new char[numberColumns_]; int numberDeleted = 0; memset(deleted, 0, numberColumns_ * sizeof(char)); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } newNumberColumns = numberColumns_ - numberDeleted; newExtended = numberExtendedColumns_ - numberDeleted; double * newArray = new double[newExtended]; int put = 0; for (i = 0; i < numberColumns_; i++) { if (!deleted[i]) { newArray[put++] = objective_[i]; } } delete [] objective_; objective_ = newArray; delete [] deleted; CoinMemcpyN(objective_ + numberColumns_, (numberExtendedColumns_ - numberColumns_), objective_ + newNumberColumns); } if (gradient_) { int i ; char * deleted = new char[numberColumns_]; int numberDeleted = 0; memset(deleted, 0, numberColumns_ * sizeof(char)); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } newNumberColumns = numberColumns_ - numberDeleted; newExtended = numberExtendedColumns_ - numberDeleted; double * newArray = new double[newExtended]; int put = 0; for (i = 0; i < numberColumns_; i++) { if (!deleted[i]) { newArray[put++] = gradient_[i]; } } delete [] gradient_; gradient_ = newArray; delete [] deleted; CoinMemcpyN(gradient_ + numberColumns_, (numberExtendedColumns_ - numberColumns_), gradient_ + newNumberColumns); } numberColumns_ = newNumberColumns; numberExtendedColumns_ = newExtended; if (quadraticObjective_) { quadraticObjective_->deleteCols(numberToDelete, which); quadraticObjective_->deleteRows(numberToDelete, which); } } // Load up quadratic objective void ClpQuadraticObjective::loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start, const int * column, const double * element, int numberExtended) { fullMatrix_ = false; delete quadraticObjective_; quadraticObjective_ = new CoinPackedMatrix(true, numberColumns, numberColumns, start[numberColumns], element, column, start, NULL); numberColumns_ = numberColumns; if (numberExtended > numberExtendedColumns_) { if (objective_) { // make correct size double * newArray = new double[numberExtended]; CoinMemcpyN(objective_, numberColumns_, newArray); delete [] objective_; objective_ = newArray; memset(objective_ + numberColumns_, 0, (numberExtended - numberColumns_)*sizeof(double)); } if (gradient_) { // make correct size double * newArray = new double[numberExtended]; CoinMemcpyN(gradient_, numberColumns_, newArray); delete [] gradient_; gradient_ = newArray; memset(gradient_ + numberColumns_, 0, (numberExtended - numberColumns_)*sizeof(double)); } numberExtendedColumns_ = numberExtended; } else { numberExtendedColumns_ = numberColumns_; } } void ClpQuadraticObjective::loadQuadraticObjective ( const CoinPackedMatrix& matrix) { delete quadraticObjective_; quadraticObjective_ = new CoinPackedMatrix(matrix); } // Get rid of quadratic objective void ClpQuadraticObjective::deleteQuadraticObjective() { delete quadraticObjective_; quadraticObjective_ = NULL; } /* Returns reduced gradient.Returns an offset (to be added to current one). */ double ClpQuadraticObjective::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 ClpQuadraticObjective::stepLength(ClpSimplex * model, const double * solution, const double * change, double maximumTheta, double & currentObj, double & predictedObj, double & thetaObj) { const double * cost = model->costRegion(); bool inSolve = true; if (!cost) { // not in solve cost = objective_; inSolve = false; } double delta = 0.0; double linearCost = 0.0; int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int numberTotal = numberColumns; if (inSolve) numberTotal += numberRows; currentObj = 0.0; thetaObj = 0.0; for (int iColumn = 0; iColumn < numberTotal; iColumn++) { delta += cost[iColumn] * change[iColumn]; linearCost += cost[iColumn] * solution[iColumn]; } if (!activated_ || !quadraticObjective_) { currentObj = linearCost; thetaObj = currentObj + delta * maximumTheta; if (delta < 0.0) { return maximumTheta; } else { COIN_DETAIL_PRINT(printf("odd linear direction %g\n", delta)); return 0.0; } } assert (model); bool scaling = false; if ((model->rowScale() || model->objectiveScale() != 1.0 || model->optimizationDirection() != 1.0) && inSolve) scaling = true; const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); const double * quadraticElement = quadraticObjective_->getElements(); double a = 0.0; double b = delta; double c = 0.0; if (!scaling) { if (!fullMatrix_) { int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double changeI = change[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double changeJ = change[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { a += changeI * changeJ * elementValue; b += (changeI * valueJ + changeJ * valueI) * elementValue; c += valueI * valueJ * elementValue; } else { a += 0.5 * changeI * changeI * elementValue; b += changeI * valueI * elementValue; c += 0.5 * valueI * valueI * elementValue; } } } } else { // full matrix stored int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double changeI = change[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double changeJ = change[jColumn]; double elementValue = quadraticElement[j]; valueJ *= elementValue; a += changeI * changeJ * elementValue; b += changeI * valueJ; c += valueI * valueJ; } } a *= 0.5; c *= 0.5; } } else { // scaling // for now only if half assert (!fullMatrix_); const double * columnScale = model->columnScale(); double direction = model->optimizationDirection() * model->objectiveScale(); // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; if (!columnScale) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double changeI = change[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double changeJ = change[jColumn]; double elementValue = quadraticElement[j]; elementValue *= direction; if (iColumn != jColumn) { a += changeI * changeJ * elementValue; b += (changeI * valueJ + changeJ * valueI) * elementValue; c += valueI * valueJ * elementValue; } else { a += 0.5 * changeI * changeI * elementValue; b += changeI * valueI * elementValue; c += 0.5 * valueI * valueI * elementValue; } } } } else { // scaling for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double changeI = change[iColumn]; double scaleI = columnScale[iColumn] * direction; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double changeJ = change[jColumn]; double elementValue = quadraticElement[j]; elementValue *= scaleI * columnScale[jColumn]; if (iColumn != jColumn) { a += changeI * changeJ * elementValue; b += (changeI * valueJ + changeJ * valueI) * elementValue; c += valueI * valueJ * elementValue; } else { a += 0.5 * changeI * changeI * elementValue; b += changeI * valueI * elementValue; c += 0.5 * valueI * valueI * elementValue; } } } } } double theta; //printf("Current cost %g\n",c+linearCost); currentObj = c + linearCost; thetaObj = currentObj + a * maximumTheta * maximumTheta + b * maximumTheta; // minimize a*x*x + b*x + c if (a <= 0.0) { theta = maximumTheta; } else { theta = -0.5 * b / a; } predictedObj = currentObj + a * theta * theta + b * theta; if (b > 0.0) { if (model->messageHandler()->logLevel() & 32) printf("a %g b %g c %g => %g\n", a, b, c, theta); b = 0.0; } return CoinMin(theta, maximumTheta); } // Return objective value (without any ClpModel offset) (model may be NULL) double ClpQuadraticObjective::objectiveValue(const ClpSimplex * model, const double * solution) const { bool scaling = false; if (model && (model->rowScale() || model->objectiveScale() != 1.0)) scaling = true; const double * cost = NULL; if (model) cost = model->costRegion(); if (!cost) { // not in solve cost = objective_; scaling = false; } double linearCost = 0.0; int numberColumns = model->numberColumns(); int numberTotal = numberColumns; double currentObj = 0.0; for (int iColumn = 0; iColumn < numberTotal; iColumn++) { linearCost += cost[iColumn] * solution[iColumn]; } if (!activated_ || !quadraticObjective_) { currentObj = linearCost; return currentObj; } assert (model); const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); const double * quadraticElement = quadraticObjective_->getElements(); double c = 0.0; if (!scaling) { if (!fullMatrix_) { int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { c += valueI * valueJ * elementValue; } else { c += 0.5 * valueI * valueI * elementValue; } } } } else { // full matrix stored int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; valueJ *= elementValue; c += valueI * valueJ; } } c *= 0.5; } } else { // scaling // for now only if half assert (!fullMatrix_); const double * columnScale = model->columnScale(); double direction = model->objectiveScale(); // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; if (!columnScale) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; elementValue *= direction; if (iColumn != jColumn) { c += valueI * valueJ * elementValue; } else { c += 0.5 * valueI * valueI * elementValue; } } } } else { // scaling for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double valueI = solution[iColumn]; double scaleI = columnScale[iColumn] * direction; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = solution[jColumn]; double elementValue = quadraticElement[j]; elementValue *= scaleI * columnScale[jColumn]; if (iColumn != jColumn) { c += valueI * valueJ * elementValue; } else { c += 0.5 * valueI * valueI * elementValue; } } } } } currentObj = c + linearCost; return currentObj; } // Scale objective void ClpQuadraticObjective::reallyScale(const double * columnScale) { const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); double * quadraticElement = quadraticObjective_->getMutableElements(); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double scaleI = columnScale[iColumn]; objective_[iColumn] *= scaleI; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; quadraticElement[j] *= scaleI * columnScale[jColumn]; } } } /* Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ int ClpQuadraticObjective::markNonlinear(char * which) { int iColumn; const int * columnQuadratic = quadraticObjective_->getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticObjective_->getVectorStarts(); const int * columnQuadraticLength = quadraticObjective_->getVectorLengths(); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; which[jColumn] = 1; which[iColumn] = 1; } } int numberNonLinearColumns = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if(which[iColumn]) numberNonLinearColumns++; } return numberNonLinearColumns; } Clp-1.15.10/src/AbcSimplex.cpp0000644000076600007660000061052412252354371014411 0ustar coincoin/* $Id: AbcSimplex.cpp 2006 2013-12-12 15:40:41Z forrest $ */ // Copyright (C) 2000, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "ClpConfig.h" #include "CoinPragma.hpp" #include //#define ABC_DEBUG 2 #if SLIM_CLP==2 #define SLIM_NOIO #endif #include "CoinHelperFunctions.hpp" #include "CoinFloatEqual.hpp" #include "ClpSimplex.hpp" #include "AbcSimplex.hpp" #include "AbcSimplexDual.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcNonLinearCost.hpp" #include "CoinAbcCommon.hpp" #include "AbcMatrix.hpp" #include "CoinIndexedVector.hpp" #include "AbcDualRowDantzig.hpp" #include "AbcDualRowSteepest.hpp" #include "AbcPrimalColumnDantzig.hpp" #include "AbcPrimalColumnSteepest.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include "ClpLinearObjective.hpp" #include "CoinAbcHelperFunctions.hpp" #include "CoinModel.hpp" #include "CoinLpIO.hpp" #include #include #include #include //############################################################################# AbcSimplex::AbcSimplex (bool emptyMessages) : ClpSimplex(emptyMessages) { gutsOfDelete(0); gutsOfInitialize(0,0,true); assert (maximumAbcNumberRows_>=0); //printf("XX %x AbcSimplex constructor\n",this); } //----------------------------------------------------------------------------- AbcSimplex::~AbcSimplex () { //printf("XX %x AbcSimplex destructor\n",this); gutsOfDelete(1); } // Copy constructor. AbcSimplex::AbcSimplex(const AbcSimplex &rhs) : ClpSimplex(rhs) { //printf("XX %x AbcSimplex constructor from %x\n",this,&rhs); gutsOfDelete(0); gutsOfInitialize(numberRows_,numberColumns_,false); gutsOfCopy(rhs); assert (maximumAbcNumberRows_>=0); } #include "ClpDualRowSteepest.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpFactorization.hpp" // Copy constructor from model AbcSimplex::AbcSimplex(const ClpSimplex &rhs) : ClpSimplex(rhs) { //printf("XX %x AbcSimplex constructor from ClpSimplex\n",this); gutsOfDelete(0); gutsOfInitialize(numberRows_,numberColumns_,true); gutsOfResize(numberRows_,numberColumns_); // Set up row/column selection and factorization type ClpDualRowSteepest * pivot = dynamic_cast(rhs.dualRowPivot()); if (pivot) { AbcDualRowSteepest steep(pivot->mode()); setDualRowPivotAlgorithm(steep); } else { AbcDualRowDantzig dantzig; setDualRowPivotAlgorithm(dantzig); } ClpPrimalColumnSteepest * pivotColumn = dynamic_cast(rhs.primalColumnPivot()); if (pivotColumn) { AbcPrimalColumnSteepest steep(pivotColumn->mode()); setPrimalColumnPivotAlgorithm(steep); } else { AbcPrimalColumnDantzig dantzig; setPrimalColumnPivotAlgorithm(dantzig); } //if (rhs.factorization()->) //factorization_->forceOtherFactorization(); factorization()->synchronize(rhs.factorization(),this); //factorization_->setGoDenseThreshold(rhs.factorization()->goDenseThreshold()); //factorization_->setGoSmallThreshold(rhs.factorization()->goSmallThreshold()); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); assert (maximumAbcNumberRows_>=0); } // Assignment operator. This copies the data AbcSimplex & AbcSimplex::operator=(const AbcSimplex & rhs) { if (this != &rhs) { gutsOfDelete(1); ClpSimplex::operator=(rhs); gutsOfCopy(rhs); assert (maximumAbcNumberRows_>=0); } return *this; } // fills in perturbationSaved_ from start with 0.5+random void AbcSimplex::fillPerturbation(int start, int number) { double * array = perturbationSaved_+start; for (int i=0;i= numberRows_); //assert (maximumInternalColumns_ >= numberColumns_); // Copy all scalars CoinAbcMemcpy(reinterpret_cast(&sumNonBasicCosts_), reinterpret_cast(&rhs.sumNonBasicCosts_), (&swappedAlgorithm_-reinterpret_cast(&sumNonBasicCosts_))+1); // could add 2 so can go off end int sizeArray=2*maximumNumberTotal_+maximumAbcNumberRows_; internalStatus_ = ClpCopyOfArray(rhs.internalStatus_,sizeArray+maximumNumberTotal_); abcLower_ = ClpCopyOfArray(rhs.abcLower_, sizeArray); abcUpper_ = ClpCopyOfArray(rhs.abcUpper_, sizeArray); abcCost_ = ClpCopyOfArray(rhs.abcCost_, sizeArray+maximumNumberTotal_); abcDj_ = ClpCopyOfArray(rhs.abcDj_, sizeArray); abcSolution_ = ClpCopyOfArray(rhs.abcSolution_, sizeArray+maximumNumberTotal_); abcPerturbation_ = ClpCopyOfArray(rhs.abcPerturbation_,sizeArray); abcPivotVariable_ = ClpCopyOfArray(rhs.abcPivotVariable_,maximumAbcNumberRows_); //fromExternal_ = ClpCopyOfArray(rhs.fromExternal_,sizeArray); //toExternal_ = ClpCopyOfArray(rhs.toExternal_,sizeArray); scaleFromExternal_ = ClpCopyOfArray(rhs.scaleFromExternal_,sizeArray); offset_ = ClpCopyOfArray(rhs.offset_,sizeArray); setupPointers(maximumAbcNumberRows_,maximumAbcNumberColumns_); if (rhs.abcMatrix_) abcMatrix_ = new AbcMatrix(*rhs.abcMatrix_); else abcMatrix_ = NULL; for (int i = 0; i < ABC_NUMBER_USEFUL; i++) { usefulArray_[i] = rhs.usefulArray_[i]; } if (rhs.abcFactorization_) { setFactorization(*rhs.abcFactorization_); } else { delete abcFactorization_; abcFactorization_ = NULL; } #ifdef EARLY_FACTORIZE delete abcEarlyFactorization_; if (rhs.abcEarlyFactorization_) { abcEarlyFactorization_ = new AbcSimplexFactorization(*rhs.abcEarlyFactorization_); } else { abcEarlyFactorization_ = NULL; } #endif abcDualRowPivot_ = rhs.abcDualRowPivot_->clone(true); abcDualRowPivot_->setModel(this); abcPrimalColumnPivot_ = rhs.abcPrimalColumnPivot_->clone(true); abcPrimalColumnPivot_->setModel(this); if (rhs.abcBaseModel_) { abcBaseModel_ = new AbcSimplex(*rhs.abcBaseModel_); } else { abcBaseModel_ = NULL; } if (rhs.clpModel_) { clpModel_ = new ClpSimplex(*rhs.clpModel_); } else { clpModel_ = NULL; } abcProgress_ = rhs.abcProgress_; solveType_ = rhs.solveType_; } // type == 0 nullify, 1 also delete void AbcSimplex::gutsOfDelete(int type) { if (type) { delete [] abcLower_; delete [] abcUpper_; delete [] abcCost_; delete [] abcDj_; delete [] abcSolution_; //delete [] fromExternal_ ; //delete [] toExternal_ ; delete [] scaleFromExternal_ ; //delete [] scaleToExternal_ ; delete [] offset_ ; delete [] internalStatus_ ; delete [] abcPerturbation_ ; delete abcMatrix_ ; delete abcFactorization_; #ifdef EARLY_FACTORIZE delete abcEarlyFactorization_; #endif delete [] abcPivotVariable_; delete abcDualRowPivot_; delete abcPrimalColumnPivot_; delete abcBaseModel_; delete clpModel_; delete abcNonLinearCost_; } CoinAbcMemset0(reinterpret_cast(&scaleToExternal_), reinterpret_cast(&usefulArray_[0])-reinterpret_cast(&scaleToExternal_)); } template T * newArray(T * /*nullArray*/, int size) { if (size) { T * arrayNew = new T[size]; #ifndef NDEBUG memset(arrayNew,'A',(size)*sizeof(T)); #endif return arrayNew; } else { return NULL; } } template T * resizeArray( T * array, int oldSize1, int oldSize2, int newSize1, int newSize2,int extra) { if ((array||!oldSize1)&&(newSize1!=oldSize1||newSize2!=oldSize2)) { int newTotal=newSize1+newSize2; int oldTotal=oldSize1+oldSize2; T * arrayNew; if (newSize1>oldSize1||newSize2>oldSize2) { arrayNew = new T[2*newTotal+newSize1+extra]; #ifndef NDEBUG memset(arrayNew,'A',(2*newTotal+newSize1+extra)*sizeof(T)); #endif CoinAbcMemcpy(arrayNew,array,oldSize1); CoinAbcMemcpy(arrayNew+newSize1,array+oldSize1,oldSize2); // and second half CoinAbcMemcpy(arrayNew+newTotal,array,oldSize1+oldTotal); CoinAbcMemcpy(arrayNew+newSize1+newTotal,array+oldSize1+oldTotal,oldSize2); delete [] array; } else { arrayNew=array; for (int i=0;i(&usefulArray_[0])-&sumNonBasicCosts_)); zeroTolerance_ = 1.0e-13; bestObjectiveValue_ = -COIN_DBL_MAX; primalToleranceToGetOptimal_ = -1.0; primalTolerance_ = 1.0e-6; //dualTolerance_ = 1.0e-6; alphaAccuracy_ = -1.0; upperIn_ = -COIN_DBL_MAX; lowerOut_ = -1; valueOut_ = -1; upperOut_ = -1; dualOut_ = -1; acceptablePivot_ = 1.0e-8; //dualBound_=1.0e9; sequenceIn_ = -1; directionIn_ = -1; sequenceOut_ = -1; directionOut_ = -1; pivotRow_ = -1; lastGoodIteration_ = -100; numberPrimalInfeasibilities_ = 100; numberRefinements_=1; changeMade_ = 1; forceFactorization_ = -1; if (perturbation_<50||(perturbation_>60&&perturbation_<100)) perturbation_ = 50; lastBadIteration_ = -999999; lastFlaggedIteration_ = -999999; // doesn't seem to be used firstFree_ = -1; incomingInfeasibility_ = 1.0; allowedInfeasibility_ = 10.0; solveType_ = 1; // say simplex based life form //specialOptions_|=65536; //ClpModel::startPermanentArrays(); maximumInternalRows_ =0; maximumInternalColumns_ =0; numberRows_=numberRows; numberColumns_=numberColumns; numberTotal_=numberRows_+numberColumns_; maximumAbcNumberRows_=numberRows; maximumAbcNumberColumns_=numberColumns; maximumNumberTotal_=numberTotal_; int sizeArray=2*maximumNumberTotal_+maximumAbcNumberRows_; if (doMore) { // say Steepest pricing abcDualRowPivot_ = new AbcDualRowSteepest(); abcPrimalColumnPivot_ = new AbcPrimalColumnSteepest(); internalStatus_ = newArray(reinterpret_cast(NULL), sizeArray+maximumNumberTotal_); abcLower_ = newArray(reinterpret_cast(NULL),sizeArray); abcUpper_ = newArray(reinterpret_cast(NULL),sizeArray); abcCost_ = newArray(reinterpret_cast(NULL),sizeArray+maximumNumberTotal_); abcDj_ = newArray(reinterpret_cast(NULL),sizeArray); abcSolution_ = newArray(reinterpret_cast(NULL),sizeArray+maximumNumberTotal_); //fromExternal_ = newArray(reinterpret_cast(NULL),sizeArray); //toExternal_ = newArray(reinterpret_cast(NULL),sizeArray); scaleFromExternal_ = newArray(reinterpret_cast(NULL),sizeArray); offset_ = newArray(reinterpret_cast(NULL),sizeArray); abcPerturbation_ = newArray(reinterpret_cast(NULL),sizeArray); abcPivotVariable_ = newArray(reinterpret_cast(NULL),maximumAbcNumberRows_); // Fill perturbation array setupPointers(maximumAbcNumberRows_,maximumAbcNumberColumns_); fillPerturbation(0,maximumNumberTotal_); } // get an empty factorization so we can set tolerances etc getEmptyFactorization(); for (int i=0;imaximumAbcNumberRows_) newSize1=CoinMax(numberRows,maximumAbcNumberRows_+CoinMin(100,numberRows_/10)); int newSize2=CoinMax(numberColumns,maximumAbcNumberColumns_); numberRows_=numberRows; numberColumns_=numberColumns; numberTotal_=numberRows_+numberColumns_; //fromExternal_ = resizeArray(fromExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1); //toExternal_ = resizeArray(toExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1,0); scaleFromExternal_ = resizeArray(scaleFromExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); //scaleToExternal_ = resizeArray(scaleToExternal_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,1,0); internalStatus_ = resizeArray(internalStatus_,maximumAbcNumberRows_, maximumAbcNumberColumns_, newSize1,newSize2,numberTotal_); abcLower_ = resizeArray(abcLower_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); abcUpper_ = resizeArray(abcUpper_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); abcCost_ = resizeArray(abcCost_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,numberTotal_); abcDj_ = resizeArray(abcDj_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); abcSolution_ = resizeArray(abcSolution_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,numberTotal_); abcPerturbation_ = resizeArray(abcPerturbation_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); offset_ = resizeArray(offset_,maximumAbcNumberRows_,maximumAbcNumberColumns_,newSize1,newSize2,0); setupPointers(newSize1,newSize2); // Fill gaps in perturbation array fillPerturbation(maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_); fillPerturbation(newSize1+maximumAbcNumberColumns_,newSize2-maximumAbcNumberColumns_); // Clean gap //CoinIotaN(fromExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,maximumAbcNumberRows_); //CoinIotaN(toExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,maximumAbcNumberRows_); CoinFillN(scaleFromExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,1.0); CoinFillN(scaleToExternal_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,1.0); CoinFillN(internalStatusSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,static_cast(1)); CoinFillN(lowerSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,-COIN_DBL_MAX); CoinFillN(upperSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,COIN_DBL_MAX); CoinFillN(costSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,0.0); CoinFillN(djSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,0.0); CoinFillN(solutionSaved_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,0.0); CoinFillN(offset_+maximumAbcNumberRows_,newSize1-maximumAbcNumberRows_,0.0); maximumAbcNumberRows_=newSize1; maximumAbcNumberColumns_=newSize2; maximumNumberTotal_=newSize1+newSize2; delete [] abcPivotVariable_; abcPivotVariable_ = new int[maximumAbcNumberRows_]; for (int i=0;isetModel(this); abcMatrix_->scale(scalingFlag_ ? 0 : -1); } if ((type&DO_STATUS)!=0&&(type&DO_BASIS_AND_ORDER)==0) { // from Clp enum to Abc enum (and bound flip) unsigned char lookupToAbcSlack[6]={4,6,0/*1*/,1/*0*/,5,7}; unsigned char * COIN_RESTRICT statusAbc=internalStatus_; const unsigned char * COIN_RESTRICT statusClp=status_; int i; for (i=numberRows_-1;i>=0;i--) { unsigned char status=statusClp[i]&7; bool basicClp=status==1; bool basicAbc=(statusAbc[i]&7)==4; if (basicClp==basicAbc) statusAbc[i]=lookupToAbcSlack[status]; else break; } if (!i) { // from Clp enum to Abc enum unsigned char lookupToAbc[6]={4,6,1,0,5,7}; statusAbc+=maximumAbcNumberRows_; statusClp+=maximumAbcNumberRows_; for (i=numberColumns_-1;i>=0;i--) { unsigned char status=statusClp[i]&7; bool basicClp=status==1; bool basicAbc=(statusAbc[i]&7)==4; if (basicClp==basicAbc) statusAbc[i]=lookupToAbc[status]; else break; } if (i) type |=DO_BASIS_AND_ORDER; } else { type |=DO_BASIS_AND_ORDER; } stateOfProblem_ |= DO_STATUS; } if ((type&DO_BASIS_AND_ORDER)!=0) { permuteIn(); permuteBasis(); stateOfProblem_ |= DO_BASIS_AND_ORDER; type &= ~DO_SOLUTION; } if ((type&DO_SOLUTION)!=0) { permuteBasis(); stateOfProblem_ |= DO_SOLUTION; } if ((type&DO_JUST_BOUNDS)!=0) { stateOfProblem_ |= DO_JUST_BOUNDS; } if (!type) { // just move stuff down CoinAbcMemcpy(abcLower_,abcLower_+maximumNumberTotal_,numberTotal_); CoinAbcMemcpy(abcUpper_,abcUpper_+maximumNumberTotal_,numberTotal_); CoinAbcMemcpy(abcCost_,abcCost_+maximumNumberTotal_,numberTotal_); } } /* Sets dual values pass djs using unscaled duals type 1 - values pass type 2 - just use as infeasibility weights type 3 - as 2 but crash */ void AbcSimplex::setupDualValuesPass(const double * fakeDuals, const double * fakePrimals, int type) { // allslack basis memset(internalStatus_,6,numberRows_); // temp if (type==1) { bool allEqual=true; for (int i=0;irowLower_[i]) { allEqual=false; break; } } if (allEqual) { // just modify costs transposeTimes(-1.0,fakeDuals,objective()); return; } } // compute unscaled djs CoinAbcMemcpy(djSaved_+maximumAbcNumberRows_,objective(),numberColumns_); matrix_->transposeTimes(-1.0,fakeDuals,djSaved_+maximumAbcNumberRows_); // save fake solution assert (solution_); //solution_ = new double[numberTotal_]; CoinAbcMemset0(solution_,numberRows_); CoinAbcMemcpy(solution_+maximumAbcNumberRows_,fakePrimals,numberColumns_); // adjust for (int iSequence=maximumAbcNumberRows_;iSequencetimes(-1.0,solution_+maximumAbcNumberRows_,solution_); double direction = optimizationDirection_; const double * COIN_RESTRICT rowScale=scaleFromExternal_; const double * COIN_RESTRICT inverseRowScale=scaleToExternal_; for (int iRow=0;iRow-1.0e30) { if (thisUpper<1.0e30) { double gapUp=thisUpper-thisValue; double gapDown=thisValue-thisLower; bool goUp; if (gapUp>gapDown&&thisDj>-dualTolerance_) { goUp=false; } else if (gapUpgapDown) { badUp=gapUp*dualTolerance_; badDown=-gapDown*thisDj; } else { badUp=gapUp*thisDj; badDown=gapDown*dualTolerance_; } goUp=badDown>badUp; } if (goUp) { solution[iColumn]=upper[iColumn]; setInternalStatus(iColumn+maximumAbcNumberRows_,atUpperBound); setStatus(iColumn,ClpSimplex::atUpperBound); } else { solution[iColumn]=lower[iColumn]; setInternalStatus(iColumn+maximumAbcNumberRows_,atLowerBound); setStatus(iColumn,ClpSimplex::atLowerBound); } } else { solution[iColumn]=lower[iColumn]; setInternalStatus(iColumn+maximumAbcNumberRows_,atLowerBound); setStatus(iColumn,ClpSimplex::atLowerBound); } } else if (thisUpper<1.0e30) { solution[iColumn]=upper[iColumn]; setInternalStatus(iColumn+maximumAbcNumberRows_,atUpperBound); setStatus(iColumn,ClpSimplex::atUpperBound); } else { // free solution[iColumn]=thisValue*inverseColumnScale[iColumn]; setInternalStatus(iColumn+maximumAbcNumberRows_,isFree); setStatus(iColumn,ClpSimplex::isFree); } } switch (type) { case 1: stateOfProblem_ |= VALUES_PASS; break; case 2: stateOfProblem_ |= VALUES_PASS2; delete [] solution_; solution_=NULL; break; case 3: stateOfProblem_ |= VALUES_PASS2; break; } } //############################################################################# int AbcSimplex::computePrimals(CoinIndexedVector * arrayVector, CoinIndexedVector * previousVector) { arrayVector->clear(); previousVector->clear(); // accumulate non basic stuff double * COIN_RESTRICT array = arrayVector->denseVector(); CoinAbcScatterZeroTo(abcSolution_,abcPivotVariable_,numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, abcSolution_, array); #if 0 static int xxxxxx=0; if (xxxxxx==0) for (int i=0;iscan(0,numberRows_,zeroTolerance_); // Ftran adjusted RHS and iterate to improve accuracy double lastError = COIN_DBL_MAX; CoinIndexedVector * thisVector = arrayVector; CoinIndexedVector * lastVector = previousVector; //if (arrayVector->getNumElements()) #if 0 double largest=0.0; int iLargest=-1; for (int i=0;ilargest) { largest=array[i]; iLargest=i; } } printf("largest %g at row %d\n",array[iLargest],iLargest); #endif abcFactorization_->updateFullColumn(*thisVector); #if 0 largest=0.0; iLargest=-1; for (int i=0;ilargest) { largest=array[i]; iLargest=i; } } printf("after largest %g at row %d\n",array[iLargest],iLargest); #endif #if 0 if (xxxxxx==0) for (int i=0;i300) exit(0); #endif int numberRefinements=0; for (int iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) { int numberIn = thisVector->getNumElements(); const int * COIN_RESTRICT indexIn = thisVector->getIndices(); const double * COIN_RESTRICT arrayIn = thisVector->denseVector(); CoinAbcScatterToList(arrayIn,abcSolution_,indexIn,abcPivotVariable_,numberIn); // check Ax == b (for all) abcMatrix_->timesIncludingSlacks(-1.0, abcSolution_, solutionBasic_); #if 0 if (xxxxxx==0) for (int i=0;imaxValue) { #if 0 if (xxxxxx==0) printf("larger %.19gg at row %d\n",value,i); maxValue=value; #endif } } if (largestPrimalError_ >= lastError) { // restore CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; //goodSolution = false; break; } if (iRefine < numberRefinements_ && largestPrimalError_ > 1.0e-10) { // try and make better numberRefinements++; // save this CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; int * COIN_RESTRICT indexOut = thisVector->getIndices(); int number = 0; array = thisVector->denseVector(); thisVector->clear(); for (int iRow = 0; iRow < numberRows_; iRow++) { double value = solutionBasic_[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; solutionBasic_[iRow] = 0.0; } } thisVector->setNumElements(number); lastError = largestPrimalError_; abcFactorization_->updateFullColumn(*thisVector); double * previous = lastVector->denseVector(); number = 0; multiplier=1.0/multiplier; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = previous[iRow] + multiplier * array[iRow]; if (value) { array[iRow] = value; indexOut[number++] = iRow; } else { array[iRow] = 0.0; } } thisVector->setNumElements(number); } else { break; } } // solution as accurate as we are going to get //if (!goodSolution) { CoinAbcMemcpy(solutionBasic_,thisVector->denseVector(),numberRows_); CoinAbcScatterTo(solutionBasic_,abcSolution_,abcPivotVariable_,numberRows_); arrayVector->clear(); previousVector->clear(); return numberRefinements; } // Moves basic stuff to basic area void AbcSimplex::moveToBasic(int which) { if ((which&1)!=0) CoinAbcGatherFrom(abcSolution_,solutionBasic_,abcPivotVariable_,numberRows_); if ((which&2)!=0) CoinAbcGatherFrom(abcCost_,costBasic_,abcPivotVariable_,numberRows_); if ((which&4)!=0) CoinAbcGatherFrom(abcLower_,lowerBasic_,abcPivotVariable_,numberRows_); if ((which&8)!=0) CoinAbcGatherFrom(abcUpper_,upperBasic_,abcPivotVariable_,numberRows_); } // now dual side int AbcSimplex::computeDuals(double * givenDjs, CoinIndexedVector * arrayVector, CoinIndexedVector * previousVector) { double * COIN_RESTRICT array = arrayVector->denseVector(); int * COIN_RESTRICT index = arrayVector->getIndices(); int number = 0; if (!givenDjs) { for (int iRow = 0; iRow < numberRows_; iRow++) { double value = costBasic_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } } } else { // dual values pass - djs may not be zero for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; // make sure zero if done if (!pivoted(iPivot)) givenDjs[iPivot] = 0.0; double value = abcCost_[iPivot] - givenDjs[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } } arrayVector->setNumElements(number); // Btran basic costs and get as accurate as possible double lastError = COIN_DBL_MAX; CoinIndexedVector * thisVector = arrayVector; CoinIndexedVector * lastVector = previousVector; abcFactorization_->updateFullColumnTranspose(*thisVector); int numberRefinements=0; for (int iRefine = 0; iRefine < numberRefinements_+1; iRefine++) { // check basic reduced costs zero // put reduced cost of basic into djBasic_ CoinAbcMemcpy(djBasic_,costBasic_,numberRows_); abcMatrix_->transposeTimesBasic(-1.0,thisVector->denseVector(),djBasic_); largestDualError_ = CoinAbcMaximumAbsElement(djBasic_,numberRows_); if (largestDualError_ >= lastError) { // restore CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; break; } if (iRefine < numberRefinements_ && largestDualError_ > 1.0e-10 && !givenDjs) { numberRefinements++; // try and make better // save this CoinIndexedVector * temp = thisVector; thisVector = lastVector; lastVector = temp; array = thisVector->denseVector(); double multiplier = 131072.0; //array=djBasic_*multiplier CoinAbcMultiplyAdd(djBasic_,numberRows_,multiplier,array,0.0); lastError = largestDualError_; abcFactorization_->updateFullColumnTranspose( *thisVector); #if ABC_DEBUG thisVector->checkClean(); #endif multiplier = 1.0 / multiplier; double * COIN_RESTRICT previous = lastVector->denseVector(); // array = array*multiplier+previous CoinAbcMultiplyAdd(previous,numberRows_,1.0,array,multiplier); } else { break; } } // now look at dual solution CoinAbcMemcpy(dual_,thisVector->denseVector(),numberRows_); CoinAbcMemset0(thisVector->denseVector(),numberRows_); thisVector->setNumElements(0); if (numberRefinements) { CoinAbcMemset0(lastVector->denseVector(),numberRows_); lastVector->setNumElements(0); } CoinAbcMemcpy(abcDj_,abcCost_,numberTotal_); abcMatrix_->transposeTimesNonBasic(-1.0, dual_,abcDj_); // If necessary - override results if (givenDjs) { // restore accurate duals CoinMemcpyN(abcDj_, numberTotal_, givenDjs); } //arrayVector->clear(); //previousVector->clear(); #if ABC_DEBUG arrayVector->checkClean(); previousVector->checkClean(); #endif return numberRefinements; } /* Factorizes using current basis. solveType - 1 iterating, 0 initial, -1 external - 2 then iterating but can throw out of basis If 10 added then in primal values pass Return codes are as from AbcSimplexFactorization unless initial factorization when total number of singularities is returned. Special case is numberRows_+1 -> all slack basis. */ int AbcSimplex::internalFactorize ( int solveType) { assert (status_); bool valuesPass = false; if (solveType >= 10) { valuesPass = true; solveType -= 10; } #if 0 // Make sure everything is clean for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if(getInternalStatus(iSequence) == isFixed) { // double check fixed assert (abcUpper_[iSequence] == abcLower_[iSequence]); assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence])<100.0*primalTolerance_); } else if (getInternalStatus(iSequence) == isFree) { assert (abcUpper_[iSequence] == COIN_DBL_MAX && abcLower_[iSequence]==-COIN_DBL_MAX); } else if (getInternalStatus(iSequence) == atLowerBound) { assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence])<1000.0*primalTolerance_); } else if (getInternalStatus(iSequence) == atUpperBound) { assert (fabs(abcSolution_[iSequence]-abcUpper_[iSequence])<1000.0*primalTolerance_); } else if (getInternalStatus(iSequence) == superBasic) { assert (!valuesPass); } } #endif #if 0 //ndef NDEBUG // Make sure everything is clean double sumOutside=0.0; int numberOutside=0; //double sumOutsideLarge=0.0; int numberOutsideLarge=0; double sumInside=0.0; int numberInside=0; //double sumInsideLarge=0.0; int numberInsideLarge=0; char rowcol[] = {'R', 'C'}; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if(getInternalStatus(iSequence) == isFixed) { // double check fixed assert (abcUpper_[iSequence] == abcLower_[iSequence]); assert (fabs(abcSolution_[iSequence]-abcLower_[iSequence])1 if (handler_->logLevel()==63) printf("%c%d below by %g\n",rowcol[isColumn(iSequence)],sequenceWithin(iSequence), abcLower_[iSequence]-abcSolution_[iSequence]); #endif sumOutside-=abcSolution_[iSequence]-abcLower_[iSequence]; if (abcSolution_[iSequence]abcLower_[iSequence]) { numberInside++; sumInside+=abcSolution_[iSequence]-abcLower_[iSequence]; if (abcSolution_[iSequence]>abcLower_[iSequence]+primalTolerance_) numberInsideLarge++; } } else if (getInternalStatus(iSequence) == atUpperBound) { assert (fabs(abcSolution_[iSequence]-abcUpper_[iSequence])<1000.0*primalTolerance_); if (abcSolution_[iSequence]>abcUpper_[iSequence]) { numberOutside++; #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel()==63) printf("%c%d above by %g\n",rowcol[isColumn(iSequence)],sequenceWithin(iSequence), -(abcUpper_[iSequence]-abcSolution_[iSequence])); #endif sumOutside+=abcSolution_[iSequence]-abcUpper_[iSequence]; if (abcSolution_[iSequence]>abcUpper_[iSequence]+primalTolerance_) numberOutsideLarge++; } else if (abcSolution_[iSequence]0 if (numberInside+numberOutside) printf("%d outside summing to %g (%d large), %d inside summing to %g (%d large)\n", numberOutside,sumOutside,numberOutsideLarge, numberInside,sumInside,numberInsideLarge); #endif #endif for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status=getInternalStatus(iSequence); if (status!= basic&&status!=isFixed&&abcUpper_[iSequence] == abcLower_[iSequence]) setInternalStatus(iSequence,isFixed); } if (numberIterations_==baseIteration_&&!valuesPass) { double largeValue = this->largeValue(); double * COIN_RESTRICT solution = abcSolution_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { AbcSimplex::Status status=getInternalStatus(iSequence); if (status== superBasic) { double lower = abcLower_[iSequence]; double upper = abcUpper_[iSequence]; double value = solution[iSequence]; AbcSimplex::Status thisStatus=isFree; if (lower > -largeValue || upper < largeValue) { if (lower!=upper) { if (fabs(value - lower) < fabs(value - upper)) { thisStatus=AbcSimplex::atLowerBound; solution[iSequence] = lower; } else { thisStatus= AbcSimplex::atUpperBound; solution[iSequence] = upper; } } else { thisStatus= AbcSimplex::isFixed; solution[iSequence] = upper; } setInternalStatus(iSequence,thisStatus); } } } } int status = abcFactorization_->factorize(this, solveType, valuesPass); if (status) { handler_->message(CLP_SIMPLEX_BADFACTOR, messages_) << status << CoinMessageEol; return -1; } else if (!solveType) { // Initial basis - return number of singularities int numberSlacks = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { if (getInternalStatus(iRow) == basic) numberSlacks++; } status = CoinMax(numberSlacks - numberRows_, 0); if (status) printf("%d singularities\n",status); // special case if all slack if (numberSlacks == numberRows_) { status = numberRows_ + 1; } } return status; } // Sets objectiveValue_ from rawObjectiveValue_ void AbcSimplex::setClpSimplexObjectiveValue() { objectiveValue_ = rawObjectiveValue_/(objectiveScale_ * rhsScale_); objectiveValue_ += objectiveOffset_; } /* This does basis housekeeping and does values for in/out variables. Can also decide to re-factorize */ int AbcSimplex::housekeeping() { #define DELAYED_UPDATE #ifdef DELAYED_UPDATE if (algorithm_<0) { // modify dualout dualOut_ /= alpha_; dualOut_ *= -directionOut_; //double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound valueIn_ = upperIn_ + dualOut_; #if 0 //def ABC_DEBUG printf("In from upper dualout_ %g movement %g (old %g) valueIn_ %g using movement %g\n", dualOut_,movement_,movementOld,valueIn_,upperIn_+movement_); #endif } else { // as if from lower bound valueIn_ = lowerIn_ + dualOut_; #if 0 //def ABC_DEBUG printf("In from lower dualout_ %g movement %g (old %g) valueIn_ %g using movement %g\n", dualOut_,movement_,movementOld,valueIn_,lowerIn_+movement_); #endif } // outgoing if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } #if ABC_NORMAL_DEBUG>3 if (rawObjectiveValue_ < oldobj - 1.0e-5 && (handler_->logLevel() & 16)) printf("obj backwards %g %g\n", rawObjectiveValue_, oldobj); #endif } #endif #if 0 //ndef NDEBUG { int numberFlagged=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) numberFlagged++; } assert (numberFlagged==numberFlagged_); } #endif // save value of incoming and outgoing numberIterations_++; changeMade_++; // something has happened // incoming variable if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE1,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE1, messages_) << directionOut_ << directionIn_ << theta_ << dualOut_ << dualIn_ << alpha_ << CoinMessageEol; if (getInternalStatus(sequenceIn_) == isFree) { handler_->message(CLP_SIMPLEX_FREEIN, messages_) << sequenceIn_ << CoinMessageEol; } } // change of incoming char rowcol[] = {'R', 'C'}; if (abcUpper_[sequenceIn_] > 1.0e20 && abcLower_[sequenceIn_] < -1.0e20) progressFlag_ |= 2; // making real progress #ifndef DELAYED_UPDATE abcSolution_[sequenceIn_] = valueIn_; #endif if (abcUpper_[sequenceOut_] - abcLower_[sequenceOut_] < 1.0e-12) progressFlag_ |= 1; // making real progress if (sequenceIn_ != sequenceOut_) { if (alphaAccuracy_ > 0.0) { double value = fabs(alpha_); if (value > 1.0) alphaAccuracy_ *= value; else alphaAccuracy_ /= value; } setInternalStatus(sequenceIn_, basic); if (abcUpper_[sequenceOut_] - abcLower_[sequenceOut_] > 0) { // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueOut_ - abcLower_[sequenceOut_]) < fabs(valueOut_ - abcUpper_[sequenceOut_])) { // going to lower setInternalStatus(sequenceOut_, atLowerBound); } else { // going to upper setInternalStatus(sequenceOut_, atUpperBound); } } else { // fixed setInternalStatus(sequenceOut_, isFixed); } #ifndef DELAYED_UPDATE abcSolution_[sequenceOut_] = valueOut_; #endif #if PARTITION_ROW_COPY==1 // move in row copy abcMatrix_->inOutUseful(sequenceIn_,sequenceOut_); #endif } else { //if (objective_->type()<2) //assert (fabs(theta_)>1.0e-13); // flip from bound to bound // As Nonlinear costs may have moved bounds (to more feasible) // Redo using value if (fabs(valueIn_ - abcLower_[sequenceIn_]) < fabs(valueIn_ - abcUpper_[sequenceIn_])) { // as if from upper bound setInternalStatus(sequenceIn_, atLowerBound); } else { // as if from lower bound setInternalStatus(sequenceIn_, atUpperBound); } } setClpSimplexObjectiveValue(); if (handler_->logLevel() > 7) { //if (handler_->detail(CLP_SIMPLEX_HOUSE2,messages_)<100) { handler_->message(CLP_SIMPLEX_HOUSE2, messages_) << numberIterations_ << objectiveValue() << rowcol[isColumn(sequenceIn_)] << sequenceWithin(sequenceIn_) << rowcol[isColumn(sequenceOut_)] << sequenceWithin(sequenceOut_); handler_->printing(algorithm_ < 0) << dualOut_ << theta_; handler_->printing(algorithm_ > 0) << dualIn_ << theta_; handler_->message() << CoinMessageEol; } #if 0 if (numberIterations_ > 10000) printf(" it %d %g %c%d %c%d\n" , numberIterations_, objectiveValue() , rowcol[isColumn(sequenceIn_)], sequenceWithin(sequenceIn_) , rowcol[isColumn(sequenceOut_)], sequenceWithin(sequenceOut_)); #endif if (hitMaximumIterations()) return 2; // check for small cycles int in = sequenceIn_; int out = sequenceOut_; int cycle = abcProgress_.cycle(in, out, directionIn_, directionOut_); if (cycle > 0 ) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() >= 63) printf("Cycle of %d\n", cycle); #endif // reset abcProgress_.startCheck(); double random = randomNumberGenerator_.randomDouble(); int extra = static_cast (9.999 * random); int off[] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 4}; if (abcFactorization_->pivots() > cycle) { forceFactorization_ = CoinMax(1, cycle - off[extra]); } else { // need to reject something int iSequence; if (algorithm_<0) { iSequence = sequenceIn_; } else { /* should be better if don't reject incoming as it is in basis */ iSequence = sequenceOut_; // so can't happen immediately again sequenceOut_=-1; } char x = isColumn(iSequence) ? 'C' : 'R'; if (handler_->logLevel() >= 63) handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(iSequence) << CoinMessageEol; setFlagged(iSequence); //printf("flagging %d\n",iSequence); } return 1; } int invertNow=0; // only time to re-factorize if one before real time // this is so user won't be surprised that maximumPivots has exact meaning int numberPivots = abcFactorization_->pivots(); if (algorithm_<0) numberPivots++; // allow for update not done int maximumPivots = abcFactorization_->maximumPivots(); int numberDense = 0; //abcFactorization_->numberDense(); bool dontInvert = ((specialOptions_ & 16384) != 0 && numberIterations_ * 3 > 2 * maximumIterations()); if (numberPivots == maximumPivots || maximumPivots < 2) { // If dense then increase if (maximumPivots > 100 && numberDense > 1.5 * maximumPivots) { abcFactorization_->maximumPivots(numberDense); } //printf("ZZ maxpivots %d its %d\n",numberPivots,maximumPivots); return 1; } else if ((abcFactorization_->timeToRefactorize() && !dontInvert) ||invertNow) { //printf("ZZ time invertNow %s its %d\n",invertNow ? "yes":"no",numberPivots); return 1; } else if (forceFactorization_ > 0 && #ifndef DELAYED_UPDATE abcFactorization_->pivots() #else abcFactorization_->pivots()+1 #endif >= forceFactorization_) { // relax forceFactorization_ = (3 + 5 * forceFactorization_) / 4; if (forceFactorization_ > abcFactorization_->maximumPivots()) forceFactorization_ = -1; //off //printf("ZZ forceFactor %d its %d\n",forceFactorization_,numberPivots); return 1; } else if (numberIterations_ > 1000 + 10 * (numberRows_ + (numberColumns_ >> 2))) { // A bit worried problem may be cycling - lets factorize at random intervals for a short period int numberTooManyIterations = numberIterations_ - 10 * (numberRows_ + (numberColumns_ >> 2)); double random = randomNumberGenerator_.randomDouble(); int window = numberTooManyIterations%5000; if (window<2*maximumPivots) random = 0.2*random+0.8; // randomly re-factorize but not too soon else random=1.0; // switch off if not in window of opportunity int maxNumber = (forceFactorization_ < 0) ? maximumPivots : CoinMin(forceFactorization_, maximumPivots); if (abcFactorization_->pivots() >= random * maxNumber) { //printf("ZZ cycling a %d\n",numberPivots); return 1; } else if (numberIterations_ > 1000000 + 10 * (numberRows_ + (numberColumns_ >> 2)) && numberIterations_ < 1000010 + 10 * (numberRows_ + (numberColumns_ >> 2))) { //printf("ZZ cycling b %d\n",numberPivots); return 1; } else { // carry on iterating return 0; } } else { // carry on iterating return 0; } } // Swaps primal stuff void AbcSimplex::swapPrimalStuff() { if (sequenceOut_<0) return; assert (sequenceIn_>=0); abcSolution_[sequenceOut_] = valueOut_; abcSolution_[sequenceIn_] = valueIn_; solutionBasic_[pivotRow_]=valueIn_; if (algorithm_<0) { // and set bounds correctly static_cast (this)->originalBound(sequenceIn_); static_cast (this)->changeBound(sequenceOut_); } else { #if ABC_NORMAL_DEBUG>2 if (handler_->logLevel()==63) printf("Code swapPrimalStuff for primal\n"); #endif } if (pivotRow_>=0) { // may be flip in primal lowerBasic_[pivotRow_]=abcLower_[sequenceIn_]; upperBasic_[pivotRow_]=abcUpper_[sequenceIn_]; costBasic_[pivotRow_]=abcCost_[sequenceIn_]; abcPivotVariable_[pivotRow_] = sequenceIn_; } } // Swaps dual stuff void AbcSimplex::swapDualStuff(int lastSequenceOut,int lastDirectionOut) { // outgoing // set dj to zero unless values pass if (lastSequenceOut>=0) { if ((stateOfProblem_&VALUES_PASS)==0) { if (lastDirectionOut > 0) { abcDj_[lastSequenceOut] = theta_; } else { abcDj_[lastSequenceOut] = -theta_; } } else { if (lastDirectionOut > 0) { abcDj_[lastSequenceOut] -= theta_; } else { abcDj_[lastSequenceOut] += theta_; } } } if (sequenceIn_>=0) { abcDj_[sequenceIn_]=0.0; //costBasic_[pivotRow_]=abcCost_[sequenceIn_]; } } static void solveMany(int number,ClpSimplex ** simplex) { for (int i=0;idual(0); simplex[number-1]->dual(0); cilk_sync; } void AbcSimplex::crash (int type) { int i; for (i=0;igotRowCopy()) abcMatrix_->createRowCopy(); //const double * element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex * columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts(); const int * row = abcMatrix_->getPackedMatrix()->getIndices(); //const double * elementByRow = abcMatrix_->rowElements(); const CoinBigIndex * rowStart = abcMatrix_->rowStart(); const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); const int * column = abcMatrix_->rowColumns(); int * blockStart = usefulArray_[0].getIndices(); int * columnBlock = blockStart+numberRows_; int * nextColumn = usefulArray_[1].getIndices(); int * blockCount = nextColumn+numberColumns_; int direction[2]={-1,1}; int bestBreak=-1; double bestValue=0.0; int iPass=0; int halfway=(numberRows_+1)/2; int firstMaster=-1; int lastMaster=-2; int numberBlocks=0; int largestRows=0; int largestColumns=0; int numberEmpty=0; int numberMaster=0; int numberEmptyColumns=0; int numberMasterColumns=0; while (iPass<2) { int increment=direction[iPass]; int start= increment>0 ? 0 : numberRows_-1; int stop=increment>0 ? numberRows_ : -1; numberBlocks=0; int thisBestBreak=-1; double thisBestValue=COIN_DBL_MAX; int numberRowsDone=0; int numberMarkedColumns=0; int maximumBlockSize=0; for (int i=0;i=0) { // column marked if (iBlock<0) { // put row in that block iBlock=whichColumnBlock; } else if (iBlock!=whichColumnBlock) { // merge blockCount[iBlock]+=blockCount[whichColumnBlock]; blockCount[whichColumnBlock]=0; int jColumn=blockStart[whichColumnBlock]; #ifndef NDEBUG int iiColumn=iColumn; #endif while (jColumn>=0) { assert (columnBlock[jColumn]==whichColumnBlock); columnBlock[jColumn]=iBlock; #ifndef NDEBUG if (jColumn==iiColumn) iiColumn=-1; #endif iColumn=jColumn; jColumn=nextColumn[jColumn]; } #ifndef NDEBUG assert (iiColumn==-1); #endif nextColumn[iColumn]=blockStart[iBlock]; blockStart[iBlock]=blockStart[whichColumnBlock]; blockStart[whichColumnBlock]=-1; } } } int n=numberMarkedColumns; if (iBlock<0) { //new block if (rowEnd[iRow]>rowStart[iRow]) { numberBlocks++; iBlock=numberBlocks; int jColumn=column[rowStart[iRow]]-maximumAbcNumberRows_; columnBlock[jColumn]=iBlock; blockStart[iBlock]=jColumn; numberMarkedColumns++; for (CoinBigIndex j=rowStart[iRow]+1;j=0) maximumBlockSize=CoinMax(maximumBlockSize,blockCount[iBlock]); numberRowsDone++; if (thisBestValue*numberRowsDone > maximumBlockSize&&numberRowsDone>halfway) { thisBestBreak=iRow; thisBestValue=static_cast(maximumBlockSize)/ static_cast(numberRowsDone); } } if (thisBestBreak==stop) thisBestValue=COIN_DBL_MAX; iPass++; if (iPass==1) { bestBreak=thisBestBreak; bestValue=thisBestValue; } else { if (bestValue=0) { blockCount[iBlock]++; } else { if (iBlock==-2) numberMaster++; else numberEmpty++; } } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iBlock=columnBlock[iColumn]; if (iBlock>=0) { nextColumn[iBlock]++; } else { if (columnStart[iColumn+1]>columnStart[iColumn]) numberMasterColumns++; else numberEmptyColumns++; } } for (int i=0;ilargestRows+largestColumns) { largestRows=blockCount[i]; largestColumns=nextColumn[i]; } } useful=true; if (numberMaster>halfway||largestRows*3>numberRows_) useful=false; } if (useful) { #if ABC_NORMAL_DEBUG>0 if (logLevel()>=2) printf("%d master rows %d <= < %d\n",lastMaster-firstMaster, firstMaster,lastMaster); printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n", useful ? "**Useful" : "NoGood", numberBlocks,largestRows,largestColumns,numberMaster,numberEmpty,numberRows_, numberMasterColumns,numberEmptyColumns,numberColumns_); if (logLevel()>=2) { for (int i=0;iminSize2 or sum >minSize1; int n=0; for (int i=0;i0&&i=0;i--) { int originalBlock=nextColumn[i]; if (blockCount[originalBlock]>0) n--; blockCount[originalBlock]=n; } assert (!n); for (int iRow = 0; iRow < numberRows_; iRow++) { int iBlock=blockStart[iRow]; if (iBlock>=0) blockStart[iRow]=blockCount[iBlock]; } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iBlock=columnBlock[iColumn]; if (iBlock>=0) columnBlock[iColumn]=blockCount[iBlock]; } // stick to Clp for now ClpSimplex ** simplex = new ClpSimplex * [numberBlocks]; for (int iBlock=0;iBlocksetSpecialOptions(simplex[iBlock]->specialOptions()&(~65536)); if (logLevel()<2) simplex[iBlock]->setLogLevel(0); } solveMany(numberBlocks,simplex); int numberBasic=numberMaster; int numberStructurals=0; for (int i=0;istatusArray()+ simplex[iBlock]->numberColumns(); double * COIN_RESTRICT solutionSaved=solutionSaved_; double * COIN_RESTRICT lowerSaved=lowerSaved_; double * COIN_RESTRICT upperSaved=upperSaved_; for (int iRow=0;iRow(lookupToAbcSlack[status]); if (status!=ClpSimplex::basic) { double lowerValue=lowerSaved[iRow]; double upperValue=upperSaved[iRow]; if (lowerValue==-COIN_DBL_MAX) { if(upperValue==COIN_DBL_MAX) { // free abcStatus=isFree; } else { abcStatus=atUpperBound; } } else if (upperValue==COIN_DBL_MAX) { abcStatus=atLowerBound; } else if (lowerValue==upperValue) { abcStatus=isFixed; } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iRow]=lowerValue; break; case atUpperBound: solutionSaved[iRow]=upperValue; break; default: break; } } else { // basic abcPivotVariable_[numberBasic++]=iRow; } internalStatus_[iRow]=abcStatus; } } // from Clp enum to Abc enum unsigned char lookupToAbc[6]={4,6,1,0,5,7}; unsigned char * COIN_RESTRICT putStatus=internalStatus_+maximumAbcNumberRows_; getStatus = simplex[iBlock]->statusArray(); solutionSaved+= maximumAbcNumberRows_; lowerSaved+= maximumAbcNumberRows_; upperSaved+= maximumAbcNumberRows_; int numberSaved=numberBasic; for (int iColumn=0;iColumn(lookupToAbc[status]); if (status!=ClpSimplex::basic) { double lowerValue=lowerSaved[iColumn]; double upperValue=upperSaved[iColumn]; if (lowerValue==-COIN_DBL_MAX) { if(upperValue==COIN_DBL_MAX) { // free abcStatus=isFree; } else { abcStatus=atUpperBound; } } else if (upperValue==COIN_DBL_MAX) { abcStatus=atLowerBound; } else if (lowerValue==upperValue) { abcStatus=isFixed; } else if (abcStatus==isFree) { abcStatus=superBasic; } switch (abcStatus) { case isFixed: case atLowerBound: solutionSaved[iColumn]=lowerValue; break; case atUpperBound: solutionSaved[iColumn]=upperValue; break; default: break; } } else { // basic if (numberBasic0 printf("%d structurals put into basis\n",numberStructurals); #endif if (numberBasicn2); n2=abcPivotVariable_[i]; } #endif delete [] simplex; return; } else { // try another type=2; } } if (type==1) { const double * linearObjective = abcCost_+maximumAbcNumberRows_; double gamma=0.0; int numberTotal=numberRows_+numberColumns_; double * q = new double [numberTotal]; double * v = q+numberColumns_; int * which = new int [numberTotal+3*numberRows_]; int * ii = which+numberColumns_; int * r = ii+numberRows_; int * pivoted = r+numberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { gamma=CoinMax(gamma,linearObjective[iColumn]); } for (int iRow = 0; iRow < numberRows_; iRow++) { double lowerBound = abcLower_[iRow]; double upperBound = abcUpper_[iRow]; pivoted[iRow]=-1; ii[iRow]=0; r[iRow]=0; v[iRow]=COIN_DBL_MAX; if (lowerBound==upperBound) continue; if (lowerBound<=0.0&&upperBound>=0.0) { pivoted[iRow]=iRow; ii[iRow]=1; r[iRow]=1; } } int nPossible=0; int lastPossible=0; double cMaxDiv; if (gamma) cMaxDiv=1.0/(1000.0*gamma); else cMaxDiv=1.0; const double * columnLower = abcLower_+maximumAbcNumberRows_; const double * columnUpper = abcUpper_+maximumAbcNumberRows_; for (int iPass=0;iPass<3;iPass++) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double lowerBound = columnLower[iColumn]; double upperBound = columnUpper[iColumn]; if (lowerBound==upperBound) continue; double qValue; if (lowerBound > -1.0e20 ) { if (upperBound < 1.0e20) { // both qValue=lowerBound-upperBound; if (iPass!=2) qValue=COIN_DBL_MAX; } else { // just lower qValue=lowerBound; if (iPass!=1) qValue=COIN_DBL_MAX; } } else { if (upperBound < 1.0e20) { // just upper qValue=-upperBound; if (iPass!=1) qValue=COIN_DBL_MAX; } else { // free qValue=0.0; if (iPass!=0) qValue=COIN_DBL_MAX; } } if (qValue!=COIN_DBL_MAX) { which[nPossible]=iColumn; q[nPossible++]=qValue+linearObjective[iColumn]*cMaxDiv;; } } CoinSort_2(q+lastPossible,q+nPossible,which+lastPossible); lastPossible=nPossible; } const double * element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex * columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts(); //const int * columnLength = abcMatrix_->getPackedMatrix()->getVectorLengths(); const int * row = abcMatrix_->getPackedMatrix()->getIndices(); int nPut=0; for (int i=0;i0.01*v[iRow]) { canTake=false; } else if (!ii[iRow]&&alpha>alternativeAlpha) { alternativeAlpha=alpha; jRow=iRow; } if (!r[iRow]&&alpha>maxAlpha) { maxAlpha=alpha; kRow=iRow; } } // only really works if scaled if (maxAlpha>0.99) { pivoted[kRow]=iColumn+maximumAbcNumberRows_; v[kRow]=maxAlpha; ii[kRow]=1; for (CoinBigIndex j=columnStart[iColumn];j=0) { pivoted[jRow]=iColumn+maximumAbcNumberRows_; v[jRow]=maxAlpha; ii[jRow]=1; for (CoinBigIndex j=columnStart[iColumn];j=0&&iSequence0 printf("%d put into basis\n",nPut); #endif delete [] q; delete [] which; } else if (type==2) { //return; int numberBad=0; CoinAbcMemcpy(abcDj_,abcCost_,numberTotal_); // Work on savedSolution and current int iVector=getAvailableArray(); #define ALLOW_BAD_DJS #ifdef ALLOW_BAD_DJS double * modDj = usefulArray_[iVector].denseVector(); #endif for (int iSequence=maximumAbcNumberRows_;iSequencedualTolerance_) { double costThru=dj*(abcUpper_[iSequence]-abcLower_[iSequence]); if (costThrugotRowCopy()) abcMatrix_->createRowCopy(); //const double * element = abcMatrix_->getPackedMatrix()->getElements(); const CoinBigIndex * columnStart = abcMatrix_->getPackedMatrix()->getVectorStarts()-maximumAbcNumberRows_; const int * row = abcMatrix_->getPackedMatrix()->getIndices(); const double * elementByRow = abcMatrix_->rowElements(); const CoinBigIndex * rowStart = abcMatrix_->rowStart(); const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); const int * column = abcMatrix_->rowColumns(); CoinAbcMemset0(solutionBasic_,numberRows_); CoinAbcMemcpy(lowerBasic_,abcLower_,numberRows_); CoinAbcMemcpy(upperBasic_,abcUpper_,numberRows_); abcMatrix_->timesIncludingSlacks(-1.0,solutionSaved_,solutionBasic_); const double multiplier[] = { 1.0, -1.0}; int nBasic=0; int * index=usefulArray_[iVector].getIndices(); int iVector2=getAvailableArray(); int * index2=usefulArray_[iVector2].getIndices(); double * sort =usefulArray_[iVector2].denseVector(); int average = CoinMax(5,rowEnd[numberRows_-1]/(8*numberRows_)); int nPossible=0; if (numberRows_>10000) { // allow more for (int iRow=0;iRowupperValue+primalTolerance_) { infeasibility=upperValue-solutionValue; } int length=rowEnd[iRow]-rowStart[iRow]; if (infeasibility) index2[nPossible++]=length; } std::sort(index2,index2+nPossible); // see how much we need to get numberRows/10 or nPossible/3 average=CoinMax(average,index2[CoinMin(numberRows_/10,nPossible/3)]); nPossible=0; } for (int iRow=0;iRowupperValue+primalTolerance_) { infeasibility=upperValue-solutionValue; } int length=rowEnd[iRow]-rowStart[iRow]; if (infeasibility&&lengthupperValue+primalTolerance_) { infeasibility=upperValue-solutionValue; } assert (infeasibility); double direction = infeasibility >0 ? 1.0 : -1.0; infeasibility *= direction; int whichColumn=-1; double upperTheta=1.0e30; int whichColumn2=-1; double upperTheta2=1.0e30; double costThru=0.0; int nThru=0; for (CoinBigIndex j=rowStart[iRow];j=maximumAbcNumberRows_); double dj = abcDj_[iSequence]; double tableauValue=-elementByRow[j]*direction; unsigned char iStatus=internalStatus_[iSequence]&7; if ((iStatus&4)==0) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = dj * mult; assert (oldValue>-1.0e-2); double value = oldValue - upperTheta * alpha; if (value < 0.0) { upperTheta2=upperTheta; whichColumn2=whichColumn; costThru=alpha*(abcUpper_[iSequence]-abcLower_[iSequence]); nThru=0; upperTheta = oldValue / alpha; whichColumn=iSequence; } else if (oldValue-upperTheta2*alpha<0.0) { costThru+=alpha*(abcUpper_[iSequence]-abcLower_[iSequence]); index[nThru++]=iSequence; } } else if (iStatus<6) { upperTheta=-1.0; upperTheta2=elementByRow[j]; whichColumn=iSequence; break; } } if (whichColumn<0) continue; if (upperTheta!=-1.0) { assert (upperTheta>=0.0); if (costThru=0) { index[nThru++]=whichColumn; for (int i=0;i-1.0e-2); dj = CoinMax(dj,0.0); #ifdef ALLOW_BAD_DJS if (numberBad&&modDj[iSequence]) { double bad=modDj[iSequence]; if (dj+bad>=0.0) { numberBad--; modDj[iSequence]=0.0; dj += bad; } else { modDj[iSequence]+=dj; dj =0.0; } } #endif } else { assert (dj<1.0e-2); dj = CoinMin(dj,0.0); #ifdef ALLOW_BAD_DJS if (numberBad&&modDj[iSequence]) { double bad=modDj[iSequence]; if (dj+bad<=0.0) { numberBad--; modDj[iSequence]=0.0; dj += bad; } else { modDj[iSequence]+=dj; dj =0.0; } } #endif } } else if (iStatus<6) { assert (fabs(dj)<1.0e-4); dj = 0.0; } abcDj_[iSequence]=dj; } // do basis if (direction>0.0) { if (upperBasic_[iRow]>lowerBasic_[iRow]) setInternalStatus(iRow,atLowerBound); else setInternalStatus(iRow,isFixed); solutionSaved_[iRow]=abcLower_[iRow]; abcSolution_[iRow]=abcLower_[iRow]; } else { if (upperBasic_[iRow]>lowerBasic_[iRow]) setInternalStatus(iRow,atUpperBound); else setInternalStatus(iRow,isFixed); solutionSaved_[iRow]=abcUpper_[iRow]; abcSolution_[iRow]=abcUpper_[iRow]; } setInternalStatus(whichColumn,basic); abcPivotVariable_[iRow]=whichColumn; nBasic++; // mark rows for (CoinBigIndex j=columnStart[whichColumn];j0 printf("dual crash put %d in basis\n",nBasic); #endif } else { assert ((stateOfProblem_&VALUES_PASS2)!=0); // The idea is to put as many likely variables into basis as possible int n=0; int iVector=getAvailableArray(); int * index=usefulArray_[iVector].getIndices(); double * array = usefulArray_[iVector].denseVector(); int iVector2=getAvailableArray(); int * index2=usefulArray_[iVector].getIndices(); for (int iSequence=0;iSequence=-1.0e-3); gapUp=CoinMax(gapUp,0.0); double gapDown=CoinMin(1.0e3,value-lower); assert (gapDown>=-1.0e-3); gapDown=CoinMax(gapDown,0.0); double measure = (CoinMin(gapUp,gapDown)+1.0e-6)/(fabs(dj)+1.0e-6); if (gapUp-dualTolerance_) { // set to lb setInternalStatus(iSequence,atLowerBound); solutionSaved_[iSequence]=abcLower_[iSequence]; abcSolution_[iSequence]=abcLower_[iSequence]; } else if (upper>lower) { // set to nearest if (gapUpgetPackedMatrix()->getVectorStarts()- maximumAbcNumberRows_; //const int * columnLength = abcMatrix_->getPackedMatrix()->getVectorLengths(); const int * row = abcMatrix_->getPackedMatrix()->getIndices(); if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); //const CoinBigIndex * rowStart = abcMatrix_->rowStart(); //const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); for (int i=0;igotRowCopy()) abcMatrix_->createRowCopy(); const CoinBigIndex * rowStart = abcMatrix_->rowStart(); const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); if (!index2[iRow]) { int length=rowEnd[iRow]-rowStart[iRow]; if (length=0) { numberIn++; for (CoinBigIndex j=columnStart[iSequence];j-dualTolerance_) { // set to lb setInternalStatus(bestRow,atLowerBound); solutionSaved_[bestRow]=abcLower_[bestRow]; abcSolution_[bestRow]=abcLower_[bestRow]; } else if (upper>lower) { // set to nearest if (gapUp0 printf("Idiot crash put %d in basis\n",numberIn); #endif setAvailableArray(iVector); setAvailableArray(iVector2); delete [] solution_; solution_=NULL; } } /* Puts more stuff in basis 1 bit set - do even if basis exists 2 bit set - don't bother staying triangular */ void AbcSimplex::putStuffInBasis(int type) { int i; for (i=0;igotRowCopy()) abcMatrix_->createRowCopy(); const double * elementByRow = abcMatrix_->rowElements(); const CoinBigIndex * rowStart = abcMatrix_->rowStart(); const CoinBigIndex * rowEnd = abcMatrix_->rowEnd(); const int * column = abcMatrix_->rowColumns(); for (int i=0;iabcLower_[iRow]||getInternalStatus(iRow)!=basic) { mustRowOut[iRow]=-2; continue; } int chooseColumn[2]={-1,-1}; for (CoinBigIndex j=rowStart[iRow];j0.0) { if (chooseColumn[0]==-1) chooseColumn[0]=iColumn; else chooseColumn[0]=-2; } else { if (chooseColumn[1]==-1) chooseColumn[1]=iColumn; else chooseColumn[1]=-2; } } for (int iTry=0;iTry<2;iTry++) { int jColumn=chooseColumn[iTry]; if (jColumn>=0&&getInternalStatus(jColumn)!=basic) { // see if has to be basic double lowerValue=-abcUpper_[iRow]; // check swap double upperValue=-abcLower_[iRow]; int lowerInf=0; int upperInf=0; double alpha=0.0; for (CoinBigIndex j=rowStart[iRow];j-1.0e20) lowerValue -= abcLower_[iColumn]*elementByRow[j]; else lowerInf ++; if (abcUpper_[iColumn]<1.0e20) upperValue -= abcUpper_[iColumn]*elementByRow[j]; else upperInf ++; } else { alpha=elementByRow[j]; } } // find values column must lie between (signs again) if (upperInf) upperValue=COIN_DBL_MAX; else upperValue /=alpha; if (lowerInf) lowerValue=-COIN_DBL_MAX; else lowerValue /=alpha; if (iTry) { // swap double temp=lowerValue; lowerValue=upperValue; upperValue=temp; } if (lowerValue>abcLower_[jColumn]+10.0*primalTolerance_&& upperValue=0) { // choose one ??? //printf("Column %d already selected on row %d now on %d\n", // jColumn,mustRowOut[jColumn],iRow); continue; } mustRowOut[jColumn]=iRow; mustRowOut[iRow]=jColumn; } } } } if (nPossible) { #if ABC_NORMAL_DEBUG>0 printf("%d possible candidates\n",nPossible); #endif if ((type&2)==0) { // triangular int iVector2=getAvailableArray(); int * COIN_RESTRICT counts = usefulArray_[iVector2].getIndices(); CoinAbcMemset0(counts,numberRows_); for (int iRow=0;iRowgetPackedMatrix()->getVectorStarts() -maximumAbcNumberRows_; const int * row = abcMatrix_->getPackedMatrix()->getIndices(); for (int iRow=0;iRow=0) { setInternalStatus(iRow,isFixed); solutionSaved_[iRow]=abcLower_[iRow]; setInternalStatus(iColumn,basic); for (CoinBigIndex j=columnStart[iColumn];j=0) { setInternalStatus(iRow,isFixed); solutionSaved_[iRow]=abcLower_[iRow]; setInternalStatus(iColumn,basic); } } } // redo pivot array int numberBasic=0; for (int iSequence=0;iSequence upperBasic[iRow]) { infeasibility = solutionBasic[iRow] - upperBasic[iRow]; } else if (solutionBasic[iRow] < lowerBasic[iRow]) { infeasibility = lowerBasic[iRow] - solutionBasic[iRow]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_ ++; } } } else { for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double infeasibility = 0.0; if (abcSolution_[iSequence] > abcUpper_[iSequence]) { infeasibility = abcSolution_[iSequence] - abcUpper_[iSequence]; } else if (abcSolution_[iSequence] < abcLower_[iSequence]) { infeasibility = abcLower_[iSequence] - abcSolution_[iSequence]; } if (infeasibility > primalTolerance) { //assert (getInternalStatus(iSequence)==basic); sumPrimalInfeasibilities_ += infeasibility - primalTolerance_; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance; numberPrimalInfeasibilities_ ++; } } } } void AbcSimplex::checkDualSolution() { sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; int firstFreePrimal = -1; int firstFreeDual = -1; int numberSuperBasicWithDj = 0; bestPossibleImprovement_ = 0.0; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, largestDualError_); // allow tolerance at least slightly bigger than standard double relaxedTolerance = currentDualTolerance_ + error; // allow bigger tolerance for possible improvement double possTolerance = 5.0 * relaxedTolerance; sumOfRelaxedDualInfeasibilities_ = 0.0; int numberNeedToMove=0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double distanceUp = abcUpper_[iSequence] - abcSolution_[iSequence]; double distanceDown = abcSolution_[iSequence] - abcLower_[iSequence]; double value = abcDj_[iSequence]; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown <= primalTolerance_) { // should not be negative if (value < 0.0) { value = - value; if (value > currentDualTolerance_) { sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } } else { // free value=fabs(value); if (value > 1.0 * relaxedTolerance) { numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; } if (value > currentDualTolerance_||getInternalStatus(iSequence)!=AbcSimplex::isFree) { numberNeedToMove++; if (firstFreePrimal < 0) firstFreePrimal = iSequence; sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > 0.0) { if (value > currentDualTolerance_) { sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } } } } numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_-numberSuperBasicWithDj; if (algorithm_ < 0 && firstFreeDual >= 0) { // dual firstFree_ = firstFreeDual; } else if (numberSuperBasicWithDj||numberNeedToMove) { //(abcProgress_.lastIterationNumber(0) <= 0)) { firstFree_ = firstFreePrimal; if (!sumDualInfeasibilities_) sumDualInfeasibilities_=1.0e-8; } } /* This sets sum and number of infeasibilities (Dual and Primal) */ void AbcSimplex::checkBothSolutions() { // old way checkPrimalSolution(true); checkDualSolution(); } /* Unpacks one column of the matrix into indexed array */ void AbcSimplex::unpack(CoinIndexedVector & rowArray, int sequence) const { abcMatrix_->unpack(rowArray,sequence); } // Sets row pivot choice algorithm in dual void AbcSimplex::setDualRowPivotAlgorithm(AbcDualRowPivot & choice) { delete abcDualRowPivot_; abcDualRowPivot_ = choice.clone(true); abcDualRowPivot_->setModel(this); } // Sets column pivot choice algorithm in primal void AbcSimplex::setPrimalColumnPivotAlgorithm(AbcPrimalColumnPivot & choice) { delete abcPrimalColumnPivot_; abcPrimalColumnPivot_ = choice.clone(true); abcPrimalColumnPivot_->setModel(this); } void AbcSimplex::setFactorization( AbcSimplexFactorization & factorization) { if (abcFactorization_) abcFactorization_->setFactorization(factorization); else abcFactorization_ = new AbcSimplexFactorization(factorization, numberRows_); } // Swaps factorization AbcSimplexFactorization * AbcSimplex::swapFactorization( AbcSimplexFactorization * factorization) { AbcSimplexFactorization * swap = abcFactorization_; abcFactorization_ = factorization; return swap; } /* Tightens primal bounds to make dual faster. Unless fixed, bounds are slightly looser than they could be. This is to make dual go faster and is probably not needed with a presolve. Returns non-zero if problem infeasible */ int AbcSimplex::tightenPrimalBounds() { int tightenType=1; if (maximumIterations()>=1000000&&maximumIterations()<1000010) tightenType=maximumIterations()-1000000; if (!tightenType) return 0; if (integerType_) { #if ABC_NORMAL_DEBUG>0 printf("Redo tighten to relax by 1 for integers (and don't be shocked by infeasibility)\n"); #endif return 0; } // This needs to work on scaled matrix - then replace // Get a row copy in standard format CoinPackedMatrix copy; copy.setExtraGap(0.0); copy.setExtraMajor(0.0); copy.reverseOrderedCopyOf(*abcMatrix_->matrix()); // get matrix data pointers const int * COIN_RESTRICT column = copy.getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = copy.getVectorStarts(); const int * COIN_RESTRICT rowLength = copy.getVectorLengths(); const double * COIN_RESTRICT element = copy.getElements(); int numberChanged = 1, iPass = 0; double large = largeValue(); // treat bounds > this as infinite #ifndef NDEBUG double large2 = 1.0e10 * large; #endif int numberInfeasible = 0; int totalTightened = 0; double tolerance = primalTolerance(); // A copy of bounds is up at top translate(0); // move down #define MAXPASS 10 // Loop round seeing if we can tighten bounds // Would be faster to have a stack of possible rows // and we put altered rows back on stack int numberCheck = -1; // temp swap signs so can use existing code double * COIN_RESTRICT rowLower=abcLower_; double * COIN_RESTRICT rowUpper=abcUpper_; for (int iRow=0;iRow(usefulArray_[whichArray[2]].getIndices()); // -1 no infinite, -2 more than one infinite >=0 column int * COIN_RESTRICT whichInfiniteDown = usefulArray_[whichArray[3]].getIndices(); int * COIN_RESTRICT whichInfiniteUp = usefulArray_[whichArray[3]].getIndices(); int numberToDoNext=0; for (int iRow=0;iRow -large || rowUpper[iRow] < large) { changedListNext[numberToDoNext++]=iRow; whichInfiniteDown[iRow]=-1; whichInfiniteUp[iRow]=-1; } else { minRhs[iRow]=-COIN_DBL_MAX; maxRhs[iRow]=COIN_DBL_MAX; whichInfiniteDown[iRow]=-2; whichInfiniteUp[iRow]=-2; } } const int * COIN_RESTRICT row = abcMatrix_->matrix()->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = abcMatrix_->matrix()->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = abcMatrix_->matrix()->getElements(); double * COIN_RESTRICT columnLower=abcLower_+maximumAbcNumberRows_; double * COIN_RESTRICT columnUpper=abcUpper_+maximumAbcNumberRows_; while(numberChanged > numberCheck) { int numberToDo=numberToDoNext; numberToDoNext=0; int * COIN_RESTRICT temp=changedList; changedList=changedListNext; changedListNext=temp; CoinAbcMemset0(changed,numberRows_); numberChanged = 0; // Bounds tightened this pass if (iPass == MAXPASS) break; iPass++; for (int k=0;k 0.0) { if (columnUpper[iColumn] >= large) { firstInfiniteUpper=iColumn; ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { firstInfiniteLower=iColumn; ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { firstInfiniteLower=iColumn; ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { firstInfiniteUpper=iColumn; ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * 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; minRhs[iRow]=infiniteLower ? -COIN_DBL_MAX : maximumDown; maxRhs[iRow]=infiniteUpper ? COIN_DBL_MAX : maximumUp; if (infiniteLower==0) whichInfiniteDown[iRow]=-1; else if (infiniteLower==1) whichInfiniteDown[iRow]=firstInfiniteLower; else whichInfiniteDown[iRow]=-2; if (infiniteUpper==0) whichInfiniteUp[iRow]=-1; else if (infiniteUpper==1) whichInfiniteUp[iRow]=firstInfiniteUpper; else whichInfiniteUp[iRow]=-2; if (maxUp <= rowUpper[iRow] + tolerance && maxDown >= rowLower[iRow] - tolerance) { // Row is redundant - make totally free // NO - can't do this for postsolve // rowLower[iRow]=-COIN_DBL_MAX; // rowUpper[iRow]=COIN_DBL_MAX; //printf("Redundant row in presolveX %d\n",iRow); } else { if (maxUp < rowLower[iRow] - 100.0 * tolerance || maxDown > rowUpper[iRow] + 100.0 * tolerance) { // problem is infeasible - exit at once numberInfeasible++; break; } double lower = rowLower[iRow]; double upper = rowUpper[iRow]; for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; double nowLower = columnLower[iColumn]; double nowUpper = columnUpper[iColumn]; 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 numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower[iColumn] = newBound; for (CoinBigIndex j1=columnStart[iColumn];j1 - 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 numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper[iColumn] = newBound; for (CoinBigIndex j1=columnStart[iColumn];j1 large) { now = 0.0; infiniteUpper--; } else { now = nowUpper; } maximumUp += (newBound - now) * value; nowUpper = newBound; } } } 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 numberChanged++; // check infeasible (relaxed) if (nowLower > newBound) { if (newBound - nowLower < -100.0 * tolerance) numberInfeasible++; else newBound = nowLower; } columnUpper[iColumn] = newBound; for (CoinBigIndex j1=columnStart[iColumn];j1 large) { now = 0.0; infiniteLower--; } else { now = nowUpper; } maximumDown += (newBound - now) * value; nowUpper = newBound; } } 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 numberChanged++; // check infeasible (relaxed) if (nowUpper < newBound) { if (nowUpper - newBound < -100.0 * tolerance) numberInfeasible++; else newBound = nowUpper; } columnLower[iColumn] = newBound; for (CoinBigIndex j1=columnStart[iColumn];j1matrix()->getElements(); for (int iColumn=0;iColumn> 4; if (numberInfeasible) break; } const double * COIN_RESTRICT saveLower = abcLower_+maximumNumberTotal_+maximumAbcNumberRows_; const double * COIN_RESTRICT saveUpper = abcUpper_+maximumNumberTotal_+maximumAbcNumberRows_; if (!numberInfeasible) { handler_->message(CLP_SIMPLEX_BOUNDTIGHTEN, messages_) << totalTightened << CoinMessageEol; int numberLowerChanged=0; int numberUpperChanged=0; if (!integerType_) { // Set bounds slightly loose // tighten rows as well //#define PRINT_TIGHTEN_PROGRESS 0 for (int iRow = 0; iRow < numberRows_; iRow++) { assert (maxRhs[iRow]>=rowLower[iRow]); assert (minRhs[iRow]<=rowUpper[iRow]); rowLower[iRow]=CoinMax(rowLower[iRow],minRhs[iRow]); rowUpper[iRow]=CoinMin(rowUpper[iRow],maxRhs[iRow]); #if PRINT_TIGHTEN_PROGRESS>3 if (handler_->logLevel()>5) printf("Row %d min %g max %g lower %g upper %g\n", iRow,minRhs[iRow],maxRhs[iRow],rowLower[iRow],rowUpper[iRow]); #endif } #if 0 double useTolerance = 1.0e-4; double multiplier = 100.0; // To do this we need to compute min and max JUST for no costs? const double * COIN_RESTRICT cost = abcCost_+maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (saveUpper[iColumn] > saveLower[iColumn] + useTolerance) { double awayFromLower=0.0; double awayFromUpper=0.0; //double gap=columnUpper[iColumn]-columnLower[iColumn]; for (CoinBigIndex j=columnStart[iColumn];j3 if (handler_->logLevel()>5) printf("row %d element %g\n",iRow,value); #endif if (value>0.0) { if (minRhs[iRow]+value*awayFromLower-1.0e10&&awayFromLower<1.0e10) awayFromLower = CoinMax(awayFromLower,(rowLower[iRow]-minRhs[iRow])/value); else awayFromLower=COIN_DBL_MAX; } if (maxRhs[iRow]-value*awayFromUpper>rowUpper[iRow]) { if (maxRhs[iRow]<1.0e10&&awayFromUpper<1.0e10) awayFromUpper = CoinMax(awayFromUpper,(maxRhs[iRow]-rowUpper[iRow])/value); else awayFromUpper=COIN_DBL_MAX; } } else { if (maxRhs[iRow]+value*awayFromLower>rowUpper[iRow]) { if (maxRhs[iRow]<1.0e10&&awayFromLower<1.0e10) awayFromLower = CoinMax(awayFromLower,(rowUpper[iRow]-maxRhs[iRow])/value); else awayFromLower=COIN_DBL_MAX; } if (minRhs[iRow]-value*awayFromUpper-1.0e10&&awayFromUpper<1.0e10) awayFromUpper = CoinMin(awayFromUpper,(minRhs[iRow]-rowLower[iRow])/value); else awayFromUpper=COIN_DBL_MAX; } } } // Might have to go as high as double upper = CoinMin(columnLower[iColumn]+awayFromLower,columnUpper[iColumn]); // and as low as double lower = CoinMax(columnUpper[iColumn]-awayFromUpper,columnLower[iColumn]); // but be sensible double gap=0.999*(CoinMin(columnUpper[iColumn]-columnLower[iColumn],1.0e10)); if (awayFromLower>gap||awayFromUpper>gap) { if (fabs(columnUpper[iColumn]-upper)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS>1 printf("YYchange upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); #endif upper=columnUpper[iColumn]; } if (fabs(columnLower[iColumn]-lower)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS>1 printf("YYchange lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif lower=columnLower[iColumn]; } } if (lower>upper) { #if PRINT_TIGHTEN_PROGRESS printf("XXchange upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); printf("XXchange lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif lower=columnLower[iColumn]; upper=columnUpper[iColumn]; } //upper=CoinMax(upper,0.0); //upper=CoinMax(upper,0.0); if (cost[iColumn]>=0.0&&awayFromLower<1.0e10&&columnLower[iColumn]>-1.0e10) { // doesn't want to be too positive if (fabs(columnUpper[iColumn]-upper)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS>2 if (handler_->logLevel()>1) printf("change upper bound on %d from %g (original %g) to %g (awayFromLower %g) - cost %g\n",iColumn, columnUpper[iColumn],saveUpper[iColumn],upper,awayFromLower,cost[iColumn]); #endif double difference=columnUpper[iColumn]-upper; for (CoinBigIndex j=columnStart[iColumn];j0.0) { assert (difference*value>=0.0); maxRhs[iRow]-=difference*value; } else { assert (difference*value<=0.0); minRhs[iRow]-=difference*value; } } columnUpper[iColumn]=upper; numberUpperChanged++; } } if (cost[iColumn]<=0.0&&awayFromUpper<1.0e10&&columnUpper[iColumn]<1.0e10) { // doesn't want to be too negative if (fabs(columnLower[iColumn]-lower)>1.0e-5) { #if PRINT_TIGHTEN_PROGRESS>2 if (handler_->logLevel()>1) printf("change lower bound on %d from %g (original %g) to %g (awayFromUpper %g) - cost %g\n",iColumn, columnLower[iColumn],saveLower[iColumn],lower,awayFromUpper,cost[iColumn]); #endif double difference=columnLower[iColumn]-lower; for (CoinBigIndex j=columnStart[iColumn];j0.0) { assert (difference*value<=0.0); minRhs[iRow]-=difference*value; } else { assert (difference*value>=0.0); maxRhs[iRow]-=difference*value; } } columnLower[iColumn]=lower; numberLowerChanged++; } } // Make large bounds stay infinite if (saveUpper[iColumn] > 1.0e30 && columnUpper[iColumn] > 1.0e10) { columnUpper[iColumn] = COIN_DBL_MAX; } if (saveLower[iColumn] < -1.0e30 && columnLower[iColumn] < -1.0e10) { columnLower[iColumn] = -COIN_DBL_MAX; } if (columnUpper[iColumn] - columnLower[iColumn] < useTolerance + 1.0e-8) { // relax enough so will have correct dj columnLower[iColumn] = CoinMax(saveLower[iColumn], columnLower[iColumn] - multiplier * useTolerance); columnUpper[iColumn] = CoinMin(saveUpper[iColumn], columnUpper[iColumn] + multiplier * useTolerance); } else { if (columnUpper[iColumn] < saveUpper[iColumn]) { // relax a bit columnUpper[iColumn] = CoinMin(columnUpper[iColumn] + multiplier * useTolerance, saveUpper[iColumn]); } if (columnLower[iColumn] > saveLower[iColumn]) { // relax a bit columnLower[iColumn] = CoinMax(columnLower[iColumn] - multiplier * useTolerance, saveLower[iColumn]); } } if (0) { // debug // tighten rows as well for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowLower[iRow] > -large || rowUpper[iRow] < large) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error double maxUp = maximumUp+1.0e-8 * fabs(maximumUp); double maxDown = maximumDown-1.0e-8 * fabs(maximumDown); double rLower=rowLower[iRow]; double rUpper=rowUpper[iRow]; if (!infiniteUpper&&maxUp < rUpper - tolerance) { if (rUpper!=COIN_DBL_MAX||maximumUp<1.0e5) rUpper=maximumUp; } if (!infiniteLower&&maxDown > rLower + tolerance) { if (rLower!=-COIN_DBL_MAX||maximumDown>-1.0e5) rLower=maximumDown; } if (infiniteUpper) maxUp=COIN_DBL_MAX; if (fabs(maxUp-maxRhs[iRow])>1.0e-3*(1.0+fabs(maxUp))) printf("bad Maxup row %d maxUp %g maxRhs %g\n",iRow,maxUp,maxRhs[iRow]); maxRhs[iRow]=maxUp; if (infiniteLower) maxDown=-COIN_DBL_MAX; if (fabs(maxDown-minRhs[iRow])>1.0e-3*(1.0+fabs(maxDown))) printf("bad Maxdown row %d maxDown %g minRhs %g\n",iRow,maxDown,minRhs[iRow]); minRhs[iRow]=maxDown; assert(rLower<=rUpper); } } // end debug } } } if (tightenType>1) { // relax for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { // relax enough so will have correct dj double lower=saveLower[iColumn]; double upper=saveUpper[iColumn]; columnLower[iColumn] = CoinMax(lower,columnLower[iColumn] - multiplier); columnUpper[iColumn] = CoinMin(upper,columnUpper[iColumn] + multiplier); } } #endif } else { #if ABC_NORMAL_DEBUG>0 printf("Redo tighten to relax by 1 for integers\n"); #endif } #if ABC_NORMAL_DEBUG>0 printf("Tighten - phase1 %d bounds changed, phase2 %d lower, %d upper\n", totalTightened,numberLowerChanged,numberUpperChanged); #endif if (integerType_) { const double * columnScale=scaleToExternal_+maximumAbcNumberRows_; const double * inverseColumnScale=scaleFromExternal_+maximumAbcNumberRows_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (integerType_[iColumn]) { double value; double lower = columnLower[iColumn]*inverseColumnScale[iColumn]; double upper = columnUpper[iColumn]*inverseColumnScale[iColumn]; value = floor(lower + 0.5); if (fabs(value - lower) > primalTolerance_) value = ceil(lower); columnLower_[iColumn] = value; columnLower[iColumn]=value*columnScale[iColumn]; value = floor(upper + 0.5); if (fabs(value - upper) > primalTolerance_) value = floor(upper); columnUpper_[iColumn] = value; columnUpper[iColumn]=value*columnScale[iColumn]; if (columnLower_[iColumn] > columnUpper_[iColumn]) numberInfeasible++; } } if (numberInfeasible) { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } } } else { handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_) << numberInfeasible << CoinMessageEol; // restore column bounds CoinMemcpyN(saveLower, numberColumns_, columnLower_); CoinMemcpyN(saveUpper, numberColumns_, columnUpper_); } if (!numberInfeasible) { // tighten rows as well for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowLower[iRow] > -large || rowUpper[iRow] < large) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = element[j]; int iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= large) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -large) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error double maxUp = maximumUp+1.0e-8 * fabs(maximumUp); double maxDown = maximumDown-1.0e-8 * fabs(maximumDown); if (!infiniteUpper&&maxUp < rowUpper[iRow] - tolerance) { if (rowUpper[iRow]!=COIN_DBL_MAX||maximumUp<1.0e5) rowUpper[iRow]=maximumUp; } if (!infiniteLower&&maxDown > rowLower[iRow] + tolerance) { if (rowLower[iRow]!=-COIN_DBL_MAX||maximumDown>-1.0e5) rowLower[iRow]=maximumDown; } assert(rowLower[iRow]<=rowUpper[iRow]); if(rowUpper[iRow]-rowLower[iRow]<1.0e-12) { if (fabs(rowLower[iRow])>fabs(rowUpper[iRow])) rowLower[iRow]=rowUpper[iRow]; else rowUpper[iRow]=rowLower[iRow]; } } } // flip back for (int iRow=0;iRowabcUpper_[i+maximumNumberTotal_]+1.0e-5) printf ("above %d %g %g\n",i, abcSolution_[i+maximumNumberTotal_],abcUpper_[i+maximumNumberTotal_]); if (abcSolution_[i+maximumNumberTotal_]>8)&7; if (crashState&&crashState<4) { switch (crashState) { case 1: crash(1000.0,1); break; case 2: crash(abcSimplex_->dualBound(),0); break; case 3: crash(0.0,3); break; } } // this and abcSimplex_ are approximately same pointer if ((abcState_&CLP_ABC_FULL_DONE)==0) { abcSimplex_->gutsOfResize(numberRows_,numberColumns_); abcSimplex_->translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); //abcSimplex_->permuteIn(); int maximumPivotsAbc=CoinMin(abcSimplex_->factorization()->maximumPivots(),numberColumns_+200); abcSimplex_->factorization()->maximumPivots(maximumPivotsAbc); if (numberColumns_) abcSimplex_->tightenPrimalBounds(); } if ((abcSimplex_->stateOfProblem()&VALUES_PASS2)!=0) { if (solution_) crashState=6; } if (crashState&&crashState>3) { abcSimplex_->crash(crashState-2); } if (crashState&&crashState<4) { abcSimplex_->putStuffInBasis(1+2); } int returnCode = abcSimplex_->doAbcDual(); //set to force crossover test returnCode=1; abcSimplex_->permuteOut(ROW_PRIMAL_OK|ROW_DUAL_OK|COLUMN_PRIMAL_OK|COLUMN_DUAL_OK|ALL_STATUS_OK); if (returnCode) { // fix as this model is all messed up e.g. scaling scalingFlag_ = abs(scalingFlag_); //delete [] rowScale_; //delete [] columnScale_; rowScale_ = NULL; columnScale_ = NULL; #if 0 delete [] savedRowScale_; delete [] savedColumnScale_; savedRowScale_ = NULL; savedColumnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; #endif if (perturbation_==50) perturbation_=51; //perturbation_=100; #if ABC_NORMAL_DEBUG>0 printf("Bad exit with status of %d\n",problemStatus_); #endif //problemStatus_=10; int status=problemStatus_; //problemStatus_=-1; if (status!=10) { dual(); // Do ClpSimplexDual } else { moreSpecialOptions_ |= 256; primal(1); } } else { // double check objective //printf("%g %g\n",objectiveValue(),abcSimplex_->objectiveValue()); perturbation_=100; moreSpecialOptions_ |= 256; //primal(1); } return returnCode; } } #endif #include "AbcSimplexPrimal.hpp" // Do dual (return 1 if cleanup needed) int AbcSimplex::doAbcDual() { if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert (!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJHF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ algorithm_=-1; baseIteration_=numberIterations_; if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); #ifdef EARLY_FACTORIZE if (maximumIterations()>1000000&&maximumIterations()<1000999) { numberEarly_=maximumIterations()-1000000; #if ABC_NORMAL_DEBUG>0 printf("Setting numberEarly_ to %d\n",numberEarly_); #endif numberEarly_+=numberEarly_<<16; } #endif minimumThetaMovement_=1.0e-10; if (fabs(infeasibilityCost_-1.0e10)<1.1e9 &&fabs(infeasibilityCost_-1.0e10)>1.0e5&&false) { minimumThetaMovement_=1.0e-3/fabs(infeasibilityCost_-1.0e10); printf("trying minimum theta movement of %g\n",minimumThetaMovement_); infeasibilityCost_=1.0e10; } int savePerturbation=perturbation_; static_cast (this)->dual(); minimumThetaMovement_=1.0e-10; if ((specialOptions_&2048)!=0 && problemStatus_==10 && !numberPrimalInfeasibilities_ && sumDualInfeasibilities_ < 1000.0* dualTolerance_) problemStatus_ = 0; // ignore onStopped(); // set secondary status if stopped if (problemStatus_==1&&numberFlagged_) { problemStatus_=10; static_cast (this)->unflag(); } if (perturbation_<101) { //printf("Perturbed djs?\n"); double * save=abcCost_; abcCost_=costSaved_; computeInternalObjectiveValue(); abcCost_=save; } int totalNumberIterations=numberIterations_; if (problemStatus_ == 10 && (moreSpecialOptions_&32768)!=0 &&sumDualInfeasibilities_ < 0.1) { problemStatus_=0; } #ifndef TRY_ABC_GUS if (problemStatus_==10) { int savePerturbation=perturbation_; perturbation_=100; copyFromSaved(2); minimumThetaMovement_=1.0e-12; baseIteration_=numberIterations_; static_cast (this)->primal(0); totalNumberIterations+=numberIterations_-baseIteration_; perturbation_=savePerturbation; } #else int iPass=0; while (problemStatus_==10&&minimumThetaMovement_>0.99999e-12) { iPass++; if (initialSumInfeasibilities_>=0.0) { if (savePerturbation>=100) { perturbation_=100; } else { if (savePerturbation==50) perturbation_=CoinMax(51,HEAVY_PERTURBATION-4-iPass); //smaller else perturbation_=CoinMax(51,savePerturbation-1-iPass); //smaller } } else { perturbation_=savePerturbation; abcFactorization_->setPivots(100000); // force factorization initialSumInfeasibilities_=1.23456789e-5; // clean pivots int numberBasic=0; int * pivot=pivotVariable(); for (int i=0;i3) moreSpecialOptions_ |= 256; if (iPass>2) perturbation_=101; baseIteration_=numberIterations_; static_cast (this)->primal(0); totalNumberIterations+=numberIterations_-baseIteration_; if (problemStatus_==10) { // reduce minimumThetaMovement_*=1.0e-1; copyFromSaved(14); baseIteration_=numberIterations_; static_cast (this)->dual(); totalNumberIterations+=numberIterations_-baseIteration_; } perturbation_=savePerturbation; } #endif numberIterations_=totalNumberIterations; return (problemStatus_<0||problemStatus_>3) ? 1 : 0; } int AbcSimplex::dual () { if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); assert (!numberFlagged_); baseIteration_=numberIterations_; //double savedPivotTolerance = abcFactorization_->pivotTolerance(); if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert (!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ minimumThetaMovement_=1.0e-12; int returnCode = static_cast (this)->dual(); if ((specialOptions_ & 2048) != 0 && problemStatus_ == 10 && !numberPrimalInfeasibilities_ && sumDualInfeasibilities_ < 1000.0 * dualTolerance_ && perturbation_ >= 100) problemStatus_ = 0; // ignore if (problemStatus_ == 10) { #if 1 //ABC_NORMAL_DEBUG>0 printf("return and use ClpSimplexPrimal\n"); abort(); #else //printf("Cleaning up with primal\n"); //lastAlgorithm=1; int savePerturbation = perturbation_; int saveLog = handler_->logLevel(); //handler_->setLogLevel(63); perturbation_ = 101; bool denseFactorization = initialDenseFactorization(); // It will be safe to allow dense setInitialDenseFactorization(true); // Allow for catastrophe int saveMax = intParam_[ClpMaxNumIteration]; if (numberIterations_) { // normal if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_) intParam_[ClpMaxNumIteration] = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_; } else { // Not normal allow more baseIteration_ += 2 * (numberRows_ + numberColumns_); } // check which algorithms allowed int dummy; if (problemStatus_ == 10 && saveObjective == objective_) startFinishOptions |= 2; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; minimumThetaMovement_=1.0e-12; returnCode = static_cast (this)->primal(1, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; if (saveObjective != objective_) { // We changed objective to see if infeasible delete objective_; objective_ = saveObjective; if (!problemStatus_) { // carry on returnCode = static_cast (this)->primal(1, startFinishOptions); } } if (problemStatus_ == 3 && numberIterations_ < saveMax) { // flatten solution and try again for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic) { setInternalStatus(iSequence, superBasic); // but put to bound if close if (fabs(rowActivity_[iSequence] - rowLower_[iSequence]) <= primalTolerance_) { abcSolution_[iSequence] = abcLower_[iSequence]; setInternalStatus(iSequence, atLowerBound); } else if (fabs(rowActivity_[iSequence] - rowUpper_[iSequence]) <= primalTolerance_) { abcSolution_[iSequence] = abcUpper_[iSequence]; setInternalStatus(iSequence, atUpperBound); } } } problemStatus_ = -1; intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_, saveMax); perturbation_ = savePerturbation; baseIteration_ = numberIterations_; // Say second call moreSpecialOptions_ |= 256; returnCode = static_cast (this)->primal(0, startFinishOptions); // Say not second call moreSpecialOptions_ &= ~256; baseIteration_ = 0; computeObjectiveValue(); // can't rely on djs either memset(reducedCost_, 0, numberColumns_ * sizeof(double)); } intParam_[ClpMaxNumIteration] = saveMax; setInitialDenseFactorization(denseFactorization); perturbation_ = savePerturbation; if (problemStatus_ == 10) { if (!numberPrimalInfeasibilities_) problemStatus_ = 0; else problemStatus_ = 4; } handler_->setLogLevel(saveLog); #endif } onStopped(); // set secondary status if stopped return returnCode; } #ifdef ABC_INHERIT // primal // Returns 0 if primal can be skipped int ClpSimplex::doAbcPrimal(int ifValuesPass) { if ((abcState_&CLP_ABC_WANTED)==0) { return 1; // not wanted } else { assert (abcSimplex_); if (ifValuesPass) abcSimplex_->setStateOfProblem(abcSimplex_->stateOfProblem()|VALUES_PASS); int crashState=(abcState_>>8)&7; if (crashState&&crashState<4) { switch (crashState) { case 1: crash(1000.0,1); break; case 2: crash(abcSimplex_->dualBound(),0); break; case 3: crash(0.0,3); break; } } // this and abcSimplex_ are approximately same pointer if ((abcState_&CLP_ABC_FULL_DONE)==0) { abcSimplex_->gutsOfResize(numberRows_,numberColumns_); abcSimplex_->translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); //abcSimplex_->permuteIn(); int maximumPivotsAbc=CoinMin(abcSimplex_->factorization()->maximumPivots(),numberColumns_+200); abcSimplex_->factorization()->maximumPivots(maximumPivotsAbc); abcSimplex_->copyFromSaved(1); } if ((abcSimplex_->stateOfProblem()&VALUES_PASS2)!=0) { if (solution_) crashState=6; } if (crashState&&crashState>3) { abcSimplex_->crash(crashState-2); } if (crashState&&crashState<4) { abcSimplex_->putStuffInBasis(1+2); } int returnCode = abcSimplex_->doAbcPrimal(ifValuesPass); //set to force crossover test returnCode=1; abcSimplex_->permuteOut(ROW_PRIMAL_OK|ROW_DUAL_OK|COLUMN_PRIMAL_OK|COLUMN_DUAL_OK|ALL_STATUS_OK); if (returnCode) { // fix as this model is all messed up e.g. scaling scalingFlag_ = abs(scalingFlag_); //delete [] rowScale_; //delete [] columnScale_; rowScale_ = NULL; columnScale_ = NULL; #if 0 delete [] savedRowScale_; delete [] savedColumnScale_; savedRowScale_ = NULL; savedColumnScale_ = NULL; inverseRowScale_ = NULL; inverseColumnScale_ = NULL; #endif if (perturbation_==50) perturbation_=51; //perturbation_=100; #if ABC_NORMAL_DEBUG>0 if (problemStatus_) printf("Bad exit with status of %d\n",problemStatus_); #endif //problemStatus_=10; int status=problemStatus_; // should not be using for (int i = 0; i < 6; i++) { if (rowArray_[i]) rowArray_[i]->clear(); if (columnArray_[i]) columnArray_[i]->clear(); } //problemStatus_=-1; if (status!=3&&status!=0) { if (status!=10) { primal(); // Do ClpSimplexPrimal } else { moreSpecialOptions_ |= 256; dual(); } } } else { // double check objective //printf("%g %g\n",objectiveValue(),abcSimplex_->objectiveValue()); } numberIterations_=abcSimplex_->numberIterations(); return returnCode; } } #endif // Do primal (return 1 if cleanup needed) int AbcSimplex::doAbcPrimal(int ifValuesPass) { if (objective_) { objective_->setActivated(0); } else { // create dummy stuff assert (!numberColumns_); if (!numberRows_) problemStatus_ = 0; // say optimal return 0; } /* Note use of "down casting". The only class the user sees is AbcSimplex. Classes AbcSimplexDual, AbcSimplexPrimal, (AbcSimplexNonlinear) and AbcSimplexOther all exist and inherit from AbcSimplex but have no additional data and have no destructor or (non-default) constructor. This is to stop classes becoming too unwieldy and so I (JJHF) can use e.g. "perturb" in primal and dual. As far as I can see this is perfectly safe. */ algorithm_=-1; int savePerturbation=perturbation_; baseIteration_=numberIterations_; if (!abcMatrix_->gotRowCopy()) abcMatrix_->createRowCopy(); #ifdef EARLY_FACTORIZE if (maximumIterations()>1000000&&maximumIterations()<1000999) { numberEarly_=maximumIterations()-1000000; #if ABC_NORMAL_DEBUG>0 printf("Setting numberEarly_ to %d\n",numberEarly_); #endif numberEarly_+=numberEarly_<<16; } #endif // add values pass options minimumThetaMovement_=1.0e-12; if ((specialOptions_&8192)!=0) minimumThetaMovement_=1.0e-15; int returnCode=static_cast (this)->primal(ifValuesPass); stateOfProblem_ &= ~VALUES_PASS; #ifndef TRY_ABC_GUS if (returnCode==10) { copyFromSaved(14); int savePerturbation=perturbation_; perturbation_=51; minimumThetaMovement_=1.0e-12; returnCode=static_cast (this)->dual(); perturbation_=savePerturbation; } #else minimumThetaMovement_=1.0e-12; int iPass=0; while (problemStatus_==10&&minimumThetaMovement_>1.0e-15) { iPass++; if (minimumThetaMovement_==1.0e-12) perturbation_=CoinMin(savePerturbation,55); else perturbation_=100; copyFromSaved(14); // reduce ? // Say second call // Say second call if (iPass>3) moreSpecialOptions_ |= 256; if (iPass>2) perturbation_=101; baseIteration_=numberIterations_; if ((specialOptions_&8192)==0) static_cast (this)->dual(); baseIteration_=numberIterations_; if (problemStatus_==10) { if (initialSumInfeasibilities_>=0.0) { if (savePerturbation>=100) { perturbation_=100; } else { if (savePerturbation==50) perturbation_=CoinMax(51,HEAVY_PERTURBATION-4-iPass); //smaller else perturbation_=CoinMax(51,savePerturbation-1-iPass); //smaller } } else { specialOptions_ |= 8192; // stop going to dual perturbation_=savePerturbation; abcFactorization_->setPivots(100000); // force factorization initialSumInfeasibilities_=1.23456789e-5; // clean pivots int numberBasic=0; int * pivot=pivotVariable(); for (int i=0;i2) perturbation_=100; copyFromSaved(14); baseIteration_=numberIterations_; static_cast (this)->primal(0); } minimumThetaMovement_*=0.5; perturbation_=savePerturbation; } #endif return returnCode; } /* Sets up all slack basis and resets solution to as it was after initial load or readMps */ void AbcSimplex::allSlackBasis() { // set column status to one nearest zero CoinFillN(internalStatus_,numberRows_,static_cast(basic)); const double * COIN_RESTRICT lower = abcLower_; const double * COIN_RESTRICT upper = abcUpper_; double * COIN_RESTRICT solution = abcSolution_; // But set value to zero if lb <0.0 and ub>0.0 for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { if (lower[i] >= 0.0) { solution[i] = lower[i]; setInternalStatus(i, atLowerBound); } else if (upper[i] <= 0.0) { solution[i] = upper[i]; setInternalStatus(i, atUpperBound); } else if (lower[i] < -1.0e20 && upper[i] > 1.0e20) { // free solution[i] = 0.0; setInternalStatus(i, isFree); } else if (fabs(lower[i]) < fabs(upper[i])) { solution[i] = 0.0; setInternalStatus(i, atLowerBound); } else { solution[i] = 0.0; setInternalStatus(i, atUpperBound); } } } #if 0 //ndef SLIM_NOIO // Read an mps file from the given filename int AbcSimplex::readMps(const char *filename, bool keepNames, bool ignoreErrors) { int status = ClpSimplex::readMps(filename, keepNames, ignoreErrors); ClpSimplex * thisModel=this; gutsOfResize(thisModel->numberRows(),thisModel->numberColumns()); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); return status; } // Read GMPL files from the given filenames int AbcSimplex::readGMPL(const char *filename, const char * dataName, bool keepNames) { int status = ClpSimplex::readGMPL(filename, dataName, keepNames); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); return status; } // Read file in LP format from file with name filename. int AbcSimplex::readLp(const char *filename, const double epsilon ) { FILE *fp = fopen(filename, "r"); if(!fp) { printf("### ERROR: AbcSimplex::readLp(): Unable to open file %s for reading\n", filename); return(1); } CoinLpIO m; m.readLp(fp, epsilon); fclose(fp); // set problem name setStrParam(ClpProbName, m.getProblemName()); // no errors loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); if (m.integerColumns()) { integerType_ = new char[numberColumns_]; CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_); } else { integerType_ = NULL; } translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); unsigned int maxLength = 0; int iRow; rowNames_ = std::vector (); columnNames_ = std::vector (); rowNames_.reserve(numberRows_); for (iRow = 0; iRow < numberRows_; iRow++) { const char * name = m.rowName(iRow); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); rowNames_.push_back(name); } else { rowNames_.push_back(""); } } int iColumn; columnNames_.reserve(numberColumns_); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { const char * name = m.columnName(iColumn); if (name) { maxLength = CoinMax(maxLength, static_cast (strlen(name))); columnNames_.push_back(name); } else { columnNames_.push_back(""); } } lengthNames_ = static_cast (maxLength); return 0; } #endif // Factorization frequency int AbcSimplex::factorizationFrequency() const { if (abcFactorization_) return abcFactorization_->maximumPivots(); else return -1; } void AbcSimplex::setFactorizationFrequency(int value) { if (abcFactorization_) abcFactorization_->maximumPivots(value); } /* Get a clean factorization - i.e. throw out singularities may do more later */ int AbcSimplex::cleanFactorization(int ifValuesPass) { int status = internalFactorize(ifValuesPass ? 10 : 0); if (status < 0) { return 1; // some error } else { firstFree_=0; return 0; } } // Save data ClpDataSave AbcSimplex::saveData() { ClpDataSave saved; saved.dualBound_ = dualBound_; saved.infeasibilityCost_ = infeasibilityCost_; saved.pivotTolerance_ = abcFactorization_->pivotTolerance(); saved.zeroFactorizationTolerance_ = abcFactorization_->zeroTolerance(); saved.zeroSimplexTolerance_ = zeroTolerance_; saved.perturbation_ = perturbation_; saved.forceFactorization_ = forceFactorization_; saved.acceptablePivot_ = acceptablePivot_; saved.objectiveScale_ = objectiveScale_; // Progress indicator abcProgress_.fillFromModel (this); return saved; } // Restore data void AbcSimplex::restoreData(ClpDataSave saved) { //abcFactorization_->sparseThreshold(saved.sparseThreshold_); abcFactorization_->pivotTolerance(saved.pivotTolerance_); abcFactorization_->zeroTolerance(saved.zeroFactorizationTolerance_); zeroTolerance_ = saved.zeroSimplexTolerance_; perturbation_ = saved.perturbation_; infeasibilityCost_ = saved.infeasibilityCost_; dualBound_ = saved.dualBound_; forceFactorization_ = saved.forceFactorization_; objectiveScale_ = saved.objectiveScale_; acceptablePivot_ = saved.acceptablePivot_; } // To flag a variable void AbcSimplex::setFlagged( int sequence) { assert (sequence>=0&&sequence=0) { internalStatus_[sequence] |= 64; // use for real disaster lastFlaggedIteration_ = numberIterations_; numberFlagged_++; } } #ifndef NDEBUG // For errors to make sure print to screen // only called in debug mode static void indexError(int index, std::string methodName) { std::cerr << "Illegal index " << index << " in AbcSimplex::" << methodName << std::endl; throw CoinError("Illegal index", methodName, "AbcSimplex"); } #endif // After modifying first copy refreshes second copy and marks as updated void AbcSimplex::refreshCosts() { whatsChanged_ &= ~OBJECTIVE_SAME; CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_); } void AbcSimplex::refreshLower(unsigned int type) { if (type) whatsChanged_ &= type; CoinAbcMemcpy(abcLower_,lowerSaved_,numberTotal_); } void AbcSimplex::refreshUpper(unsigned int type) { if (type) whatsChanged_ &= type; CoinAbcMemcpy(abcUpper_,upperSaved_,numberTotal_); } /* Set an objective function coefficient */ void AbcSimplex::setObjectiveCoefficient( int elementIndex, double elementValue ) { #ifndef NDEBUG if (elementIndex < 0 || elementIndex >= numberColumns_) { indexError(elementIndex, "setObjectiveCoefficient"); } #endif if (objective()[elementIndex] != elementValue) { objective()[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~OBJECTIVE_SAME; double direction = optimizationDirection_ * objectiveScale_; costSaved_[elementIndex+maximumAbcNumberRows_] = direction * elementValue * columnUseScale_[elementIndex+maximumAbcNumberRows_]; } } /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void AbcSimplex::setRowLower( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (rowLower_[elementIndex] != elementValue) { rowLower_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_LOWER_SAME; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex] = elementValue * rhsScale_ * rowUseScale_[elementIndex]; } } } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void AbcSimplex::setRowUpper( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (rowUpper_[elementIndex] != elementValue) { rowUpper_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_UPPER_SAME; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex] = COIN_DBL_MAX; } else { upperSaved_[elementIndex] = elementValue * rhsScale_ * rowUseScale_[elementIndex]; } } } /* Set a single row lower and upper bound */ void AbcSimplex::setRowBounds( int elementIndex, double lowerValue, double upperValue ) { #ifndef NDEBUG int n = numberRows_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setRowBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[elementIndex] != lowerValue) { rowLower_[elementIndex] = lowerValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_LOWER_SAME; if (rowLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex] = lowerValue * rhsScale_ * rowUseScale_[elementIndex]; } } if (rowUpper_[elementIndex] != upperValue) { rowUpper_[elementIndex] = upperValue; // work arrays exist - update as well whatsChanged_ &= ~ROW_UPPER_SAME; if (rowUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex] = COIN_DBL_MAX; } else { upperSaved_[elementIndex] = upperValue * rhsScale_ * rowUseScale_[elementIndex]; } } } void AbcSimplex::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #ifndef NDEBUG int n = numberRows_; #endif int numberChanged = 0; const int * saveFirst = indexFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; #ifndef NDEBUG if (iRow < 0 || iRow >= n) { indexError(iRow, "setRowSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (rowLower_[iRow] != lowerValue) { rowLower_[iRow] = lowerValue; whatsChanged_ &= ~ROW_LOWER_SAME; numberChanged++; } if (rowUpper_[iRow] != upperValue) { rowUpper_[iRow] = upperValue; whatsChanged_ &= ~ROW_UPPER_SAME; numberChanged++; } } if (numberChanged) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iRow = *indexFirst++; if (rowLower_[iRow] == -COIN_DBL_MAX) { lowerSaved_[iRow] = -COIN_DBL_MAX; } else { lowerSaved_[iRow] = rowLower_[iRow] * rhsScale_ * rowUseScale_[iRow]; } if (rowUpper_[iRow] == COIN_DBL_MAX) { upperSaved_[iRow] = COIN_DBL_MAX; } else { upperSaved_[iRow] = rowUpper_[iRow] * rhsScale_ * rowUseScale_[iRow]; } } } } //----------------------------------------------------------------------------- /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void AbcSimplex::setColumnLower( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnLower"); } #endif if (elementValue < -1.0e27) elementValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != elementValue) { columnLower_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_LOWER_SAME; double value; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { value = -COIN_DBL_MAX; } else { value = elementValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } lowerSaved_[elementIndex+maximumAbcNumberRows_] = value; } } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void AbcSimplex::setColumnUpper( int elementIndex, double elementValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnUpper"); } #endif if (elementValue > 1.0e27) elementValue = COIN_DBL_MAX; if (columnUpper_[elementIndex] != elementValue) { columnUpper_[elementIndex] = elementValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_UPPER_SAME; double value; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { value = COIN_DBL_MAX; } else { value = elementValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } upperSaved_[elementIndex+maximumAbcNumberRows_] = value; } } /* Set a single column lower and upper bound */ void AbcSimplex::setColumnBounds( int elementIndex, double lowerValue, double upperValue ) { #ifndef NDEBUG int n = numberColumns_; if (elementIndex < 0 || elementIndex >= n) { indexError(elementIndex, "setColumnBounds"); } #endif if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (columnLower_[elementIndex] != lowerValue) { columnLower_[elementIndex] = lowerValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_LOWER_SAME; if (columnLower_[elementIndex] == -COIN_DBL_MAX) { lowerSaved_[elementIndex+maximumAbcNumberRows_] = -COIN_DBL_MAX; } else { lowerSaved_[elementIndex+maximumAbcNumberRows_] = lowerValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } } if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; if (columnUpper_[elementIndex] != upperValue) { columnUpper_[elementIndex] = upperValue; // work arrays exist - update as well whatsChanged_ &= ~COLUMN_UPPER_SAME; if (columnUpper_[elementIndex] == COIN_DBL_MAX) { upperSaved_[elementIndex+maximumAbcNumberRows_] = COIN_DBL_MAX; } else { upperSaved_[elementIndex+maximumAbcNumberRows_] = upperValue * rhsScale_ * inverseColumnUseScale_[elementIndex]; } } } void AbcSimplex::setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { #ifndef NDEBUG int n = numberColumns_; #endif int numberChanged = 0; const int * saveFirst = indexFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; #ifndef NDEBUG if (iColumn < 0 || iColumn >= n) { indexError(iColumn, "setColumnSetBounds"); } #endif double lowerValue = *boundList++; double upperValue = *boundList++; if (lowerValue < -1.0e27) lowerValue = -COIN_DBL_MAX; if (upperValue > 1.0e27) upperValue = COIN_DBL_MAX; //CoinAssert (upperValue>=lowerValue); if (columnLower_[iColumn] != lowerValue) { columnLower_[iColumn] = lowerValue; whatsChanged_ &= ~COLUMN_LOWER_SAME; numberChanged++; } if (columnUpper_[iColumn] != upperValue) { columnUpper_[iColumn] = upperValue; whatsChanged_ &= ~COLUMN_UPPER_SAME; numberChanged++; } } if (numberChanged) { indexFirst = saveFirst; while (indexFirst != indexLast) { const int iColumn = *indexFirst++; if (columnLower_[iColumn] == -COIN_DBL_MAX) { lowerSaved_[iColumn+maximumAbcNumberRows_] = -COIN_DBL_MAX; } else { lowerSaved_[iColumn+maximumAbcNumberRows_] = columnLower_[iColumn] * rhsScale_ * inverseColumnUseScale_[iColumn]; } if (columnUpper_[iColumn] == COIN_DBL_MAX) { upperSaved_[iColumn+maximumAbcNumberRows_] = COIN_DBL_MAX; } else { upperSaved_[iColumn+maximumAbcNumberRows_] = columnUpper_[iColumn] * rhsScale_ * inverseColumnUseScale_[iColumn]; } } } } #ifndef SLIM_CLP #include "CoinWarmStartBasis.hpp" // Returns a basis (to be deleted by user) CoinWarmStartBasis * AbcSimplex::getBasis() const { CoinWarmStartBasis * basis = new CoinWarmStartBasis(); basis->setSize(numberColumns_, numberRows_); unsigned char lookup[8]={2,3,255,255,0,0,1,3}; for (int iRow = 0; iRow < numberRows_; iRow++) { int iStatus = getInternalStatus(iRow); iStatus = lookup[iStatus]; basis->setArtifStatus(iRow, static_cast (iStatus)); } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { int iStatus = getInternalStatus(iColumn+maximumAbcNumberRows_); iStatus = lookup[iStatus]; basis->setStructStatus(iColumn, static_cast (iStatus)); } return basis; } #endif // Compute objective value from solution void AbcSimplex::computeObjectiveValue(bool useInternalArrays) { const double * obj = objective(); if (!useInternalArrays) { objectiveValue_ = 0.0; for (int iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = columnActivity_[iSequence]; objectiveValue_ += value * obj[iSequence]; } // But remember direction as we are using external objective objectiveValue_ *= optimizationDirection_; } else { rawObjectiveValue_ = 0.0; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double value = abcSolution_[iSequence]; rawObjectiveValue_ += value * abcCost_[iSequence]; } setClpSimplexObjectiveValue(); } } // Compute minimization objective value from internal solution double AbcSimplex::computeInternalObjectiveValue() { rawObjectiveValue_ = 0.0; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double value = abcSolution_[iSequence]; rawObjectiveValue_ += value * abcCost_[iSequence]; } setClpSimplexObjectiveValue(); return objectiveValue_-dblParam_[ClpObjOffset]; } // If user left factorization frequency then compute void AbcSimplex::defaultFactorizationFrequency() { if (factorizationFrequency() == 200) { // User did not touch preset const int cutoff1 = 10000; const int cutoff2 = 100000; const int base = 75; const int freq0 = 50; const int freq1 = 150; const int maximum = 10000; int frequency; if (numberRows_ < cutoff1) frequency = base + numberRows_ / freq0; else frequency = base + cutoff1 / freq0 + (numberRows_ - cutoff1) / freq1; setFactorizationFrequency(CoinMin(maximum, frequency)); } } // Gets clean and emptyish factorization AbcSimplexFactorization * AbcSimplex::getEmptyFactorization() { if ((specialOptions_ & 65536) == 0) { assert (!abcFactorization_); abcFactorization_ = new AbcSimplexFactorization(); } else if (!abcFactorization_) { abcFactorization_ = new AbcSimplexFactorization(); } return abcFactorization_; } // Resizes rim part of model void AbcSimplex::resize (int newNumberRows, int newNumberColumns) { assert (maximumAbcNumberRows_>=0); // save int numberRows=numberRows_; int numberColumns=numberColumns_; ClpSimplex::resize(newNumberRows, newNumberColumns); // back out numberRows_=numberRows; numberColumns_=numberColumns; gutsOfResize(newNumberRows,newNumberColumns); } // Return true if the objective limit test can be relied upon bool AbcSimplex::isObjectiveLimitTestValid() const { if (problemStatus_ == 0) { return true; } else if (problemStatus_ == 1) { // ok if dual return (algorithm_ < 0); } else if (problemStatus_ == 2) { // ok if primal return (algorithm_ > 0); } else { return false; } } /* Permutes in from ClpModel data - assumes scale factors done and AbcMatrix exists but is in original order (including slacks) For now just add basicArray at end == But could partition into normal (i.e. reasonable lower/upper) abnormal - free, odd bounds fixed == sets a valid pivotVariable Slacks always shifted by offset Fixed variables always shifted by offset Recode to allow row objective so can use pi from idiot etc */ void AbcSimplex::permuteIn() { // for now only if maximumAbcNumberRows_==numberRows_ //assert(maximumAbcNumberRows_==numberRows_); numberTotal_=maximumAbcNumberRows_+numberColumns_; double direction = optimizationDirection_; // all this could use cilk // move primal stuff to end const double * COIN_RESTRICT rowScale=scaleFromExternal_; const double * COIN_RESTRICT inverseRowScale=scaleToExternal_; const double * COIN_RESTRICT columnScale=scaleToExternal_+maximumAbcNumberRows_; const double * COIN_RESTRICT inverseColumnScale=scaleFromExternal_+maximumAbcNumberRows_; double * COIN_RESTRICT offsetRhs=offsetRhs_; double * COIN_RESTRICT saveLower=lowerSaved_+maximumAbcNumberRows_; double * COIN_RESTRICT saveUpper=upperSaved_+maximumAbcNumberRows_; double * COIN_RESTRICT saveCost=costSaved_+maximumAbcNumberRows_; double * COIN_RESTRICT saveSolution=solutionSaved_+maximumAbcNumberRows_; CoinAbcMemset0(offsetRhs,maximumAbcNumberRows_); const double * COIN_RESTRICT objective=this->objective(); objectiveOffset_=0.0; double * COIN_RESTRICT offset=offset_+maximumAbcNumberRows_; const int * COIN_RESTRICT row = abcMatrix_->matrix()->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = abcMatrix_->matrix()->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = abcMatrix_->matrix()->getElements(); largestGap_=1.0e-12; for (int iColumn=0;iColumnupperValue2) thisOffset=upperValue; else thisOffset=lowerValue; } offset[iColumn]=thisOffset; objectiveOffset_ += thisOffset*objective[iColumn]*optimizationDirection_; double scaledOffset = thisOffset*scale; for (CoinBigIndex j=columnStart[iColumn];j-1.0e30) lowerValue*=scale; saveLower[iColumn]=lowerValue; upperValue-=thisOffset; if (upperValue<1.0e30) upperValue*=scale; saveUpper[iColumn]=upperValue; largestGap_=CoinMax(largestGap_,upperValue-lowerValue); saveSolution[iColumn]=scale*(columnActivity_[iColumn]-thisOffset); saveCost[iColumn]=objective[iColumn]*direction*columnScale[iColumn]; } CoinAbcMemset0(offset_,maximumAbcNumberRows_); saveLower-=maximumAbcNumberRows_; saveUpper-=maximumAbcNumberRows_; saveCost-=maximumAbcNumberRows_; saveSolution-=maximumAbcNumberRows_; for (int iRow=0;iRow-1.0e30) lowerValue=lowerValue*scale+thisOffset; saveLower[iRow]=lowerValue; if (upperValue<1.0e30) upperValue=upperValue*scale+thisOffset; saveUpper[iRow]=upperValue; largestGap_=CoinMax(largestGap_,upperValue-lowerValue); saveCost[iRow]=0.0; dual_[iRow]*=direction*inverseRowScale[iRow]; saveSolution[iRow]=0.0; // not necessary } dualBound_=CoinMin(dualBound_,largestGap_); // Compute rhsScale_ and objectiveScale_ double minValue=COIN_DBL_MAX; double maxValue=0.0; CoinAbcMinMaxAbsNormalValues(costSaved_+maximumAbcNumberRows_,numberTotal_-maximumAbcNumberRows_,minValue,maxValue); // scale to 1000.0 ? if (minValue&&false) { objectiveScale_= 1000.0/sqrt(minValue*maxValue); objectiveScale_=CoinMin(1.0,1000.0/maxValue); #ifndef NDEBUG double smallestNormal=COIN_DBL_MAX; double smallestAny=COIN_DBL_MAX; double largestAny=0.0; for (int i=0;i1.0e-8) smallestNormal=CoinMin(smallestNormal,value); smallestAny=CoinMin(smallestAny,value); largestAny=CoinMax(largestAny,value); } } printf("objectiveScale_ %g min_used %g (min_reasonable %g, min_any %g) max_used %g (max_any %g)\n", objectiveScale_,minValue,smallestNormal,smallestAny,maxValue,largestAny); #endif } else { //objectiveScale_=1.0; } CoinAbcScale(costSaved_,objectiveScale_,numberTotal_); minValue=COIN_DBL_MAX; maxValue=0.0; CoinAbcMinMaxAbsNormalValues(lowerSaved_,numberTotal_,minValue,maxValue); CoinAbcMinMaxAbsNormalValues(upperSaved_,numberTotal_,minValue,maxValue); // scale to 100.0 ? if (minValue&&false) { rhsScale_= 100.0/sqrt(minValue*maxValue); #ifndef NDEBUG double smallestNormal=COIN_DBL_MAX; double smallestAny=COIN_DBL_MAX; double largestAny=0.0; for (int i=0;i1.0e-8) smallestNormal=CoinMin(smallestNormal,value); smallestAny=CoinMin(smallestAny,value); largestAny=CoinMax(largestAny,value); } } for (int i=0;i1.0e-8) smallestNormal=CoinMin(smallestNormal,value); smallestAny=CoinMin(smallestAny,value); largestAny=CoinMax(largestAny,value); } } printf("rhsScale_ %g min_used %g (min_reasonable %g, min_any %g) max_used %g (max_any %g)\n", rhsScale_,minValue,smallestNormal,smallestAny,maxValue,largestAny); #endif } else { rhsScale_=1.0; } CoinAbcScaleNormalValues(lowerSaved_,rhsScale_,1.0e-13,numberTotal_); CoinAbcScaleNormalValues(upperSaved_,rhsScale_,1.0e-13,numberTotal_); // copy CoinAbcMemcpy(abcLower_,abcLower_+maximumNumberTotal_,numberTotal_); CoinAbcMemcpy(abcUpper_,abcUpper_+maximumNumberTotal_,numberTotal_); CoinAbcMemcpy(abcSolution_,abcSolution_+maximumNumberTotal_,numberTotal_); CoinAbcMemcpy(abcCost_,abcCost_+maximumNumberTotal_,numberTotal_); } void AbcSimplex::permuteBasis() { assert (abcPivotVariable_||(!numberRows_&&!numberColumns_)); int numberBasic=0; // from Clp enum to Abc enum (and bound flip) unsigned char lookupToAbcSlack[6]={4,6,0/*1*/,1/*0*/,5,7}; unsigned char * COIN_RESTRICT getStatus = status_+numberColumns_; double * COIN_RESTRICT solutionSaved=solutionSaved_; double * COIN_RESTRICT lowerSaved=lowerSaved_; double * COIN_RESTRICT upperSaved=upperSaved_; bool ordinaryVariables=true; bool valuesPass=(stateOfProblem_&VALUES_PASS)!=0; if (valuesPass) { // get solution CoinAbcMemset0(abcSolution_,numberRows_); abcMatrix_->timesIncludingSlacks(-1.0,abcSolution_,abcSolution_); //double * temp = new double[numberRows_]; //memset(temp,0,numberRows_*sizeof(double)); //matrix_->times(1.0,columnActivity_,temp); CoinAbcMemcpy(solutionSaved_,abcSolution_,numberRows_); int n=0; for (int i=0;iupperSaved_[i]+1.0e-5) n++; else if (solutionSaved_[i]0 if (n) printf("%d infeasibilities\n",n); #endif } // dual at present does not like superbasic for (int iRow=0;iRow(lookupToAbcSlack[status]); if (status!=ClpSimplex::basic) { double lowerValue=lowerSaved[iRow]; double upperValue=upperSaved[iRow]; if (lowerValue==-COIN_DBL_MAX) { if(upperValue==COIN_DBL_MAX) { // free abcStatus=isFree; ordinaryVariables=false; } else { abcStatus=atUpperBound; } } else if (upperValue==COIN_DBL_MAX) { abcStatus=atLowerBound; } else if (lowerValue==upperValue) { abcStatus=isFixed; } else if (abcStatus==isFixed) { double value=solutionSaved[iRow]; if (value-lowerValuelowerValue+primalTolerance_&&value(lookupToAbc[status]); if (status!=ClpSimplex::basic) { double lowerValue=lowerSaved[iColumn]; double upperValue=upperSaved[iColumn]; if (lowerValue==-COIN_DBL_MAX) { if(upperValue==COIN_DBL_MAX) { // free abcStatus=isFree; ordinaryVariables=false; } else { abcStatus=atUpperBound; } } else if (upperValue==COIN_DBL_MAX) { abcStatus=atLowerBound; } else if (lowerValue==upperValue) { abcStatus=isFixed; } else if (abcStatus==isFixed) { double value=solutionSaved[iColumn]; if (value-lowerValuelowerValue+primalTolerance_) { if(value -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } double value = (offsetRhs[i]-valueScaled * scaleR) * scaleFactor; putSolution[i]=value; if (value < rowLower[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > rowUpper[i] + primalTolerance_) numberPrimalUnscaled++; } } if ((whatsWanted&COLUMN_PRIMAL_OK)!=0&&(stateOfProblem_&COLUMN_PRIMAL_OK)==0) { stateOfProblem_ |= COLUMN_PRIMAL_OK; // Collect infeasibilities if (!filledInSolution) { filledInSolution=true; CoinAbcScatterTo(solutionBasic_,abcSolution_,abcPivotVariable_,numberRows_); CoinAbcScatterZeroTo(abcDj_,abcPivotVariable_,numberRows_); } // Collect infeasibilities double * COIN_RESTRICT putSolution = columnActivity_-maximumAbcNumberRows_; const double * COIN_RESTRICT columnLower=columnLower_-maximumAbcNumberRows_; const double * COIN_RESTRICT columnUpper=columnUpper_-maximumAbcNumberRows_; for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { double scaleFactor = columnScale[i]; double valueScaled = abcSolution_[i]; double lowerScaled = abcLower_[i]; double upperScaled = abcUpper_[i]; if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) { if (valueScaled < lowerScaled - primalTolerance_ || valueScaled > upperScaled + primalTolerance_) numberPrimalScaled++; else upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled)); } double value = (valueScaled * scaleR) * scaleFactor+offset_[i]; putSolution[i]=value; if (value < columnLower[i] - primalTolerance_) numberPrimalUnscaled++; else if (value > columnUpper[i] + primalTolerance_) numberPrimalUnscaled++; } } if ((whatsWanted&COLUMN_DUAL_OK)!=0&&(stateOfProblem_&COLUMN_DUAL_OK)==0) { // Get fixed djs CoinAbcMemcpy(abcDj_,abcCost_,numberTotal_); abcMatrix_->transposeTimesAll( dual_,abcDj_); stateOfProblem_ |= COLUMN_DUAL_OK; // Collect infeasibilities double * COIN_RESTRICT putDj=reducedCost_-maximumAbcNumberRows_; for (int i = maximumAbcNumberRows_; i < numberTotal_; i++) { double scaleFactor = inverseColumnScale[i]; double valueDual = abcDj_[i]; double value=abcSolution_[i]; bool aboveLower= value>abcLower_[i]+primalTolerance_; bool belowUpper= value dualTolerance_) numberDualScaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualScaled++; valueDual *= scaleFactor * scaleC; putDj[i]=valueDual; if (aboveLower&& valueDual > dualTolerance_) numberDualUnscaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualUnscaled++; } } if ((whatsWanted&ROW_DUAL_OK)!=0&&(stateOfProblem_&ROW_DUAL_OK)==0) { stateOfProblem_ |= ROW_DUAL_OK; // Collect infeasibilities for (int i = 0; i < numberRows_; i++) { double scaleFactor = rowScale[i]; double valueDual = abcDj_[i]; // ? +- and direction double value=abcSolution_[i]; bool aboveLower= value>abcLower_[i]+primalTolerance_; bool belowUpper= value dualTolerance_) numberDualScaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualScaled++; valueDual *= scaleFactor * scaleC; dual_[i]=-(valueDual-abcCost_[i]); // sign if (aboveLower&& valueDual > dualTolerance_) numberDualUnscaled++; if (belowUpper && valueDual < -dualTolerance_) numberDualUnscaled++; } } // do after djs if (!problemStatus_ && (!secondaryStatus_||secondaryStatus_==2||secondaryStatus_==3)) { // See if we need to set secondary status if (numberPrimalUnscaled) { if (numberDualUnscaled||secondaryStatus_==3) secondaryStatus_ = 4; else secondaryStatus_ = 2; } else if (numberDualUnscaled) { if (secondaryStatus_==0) secondaryStatus_ = 3; else secondaryStatus_ = 4; } } if (problemStatus_ == 2) { for (int i = 0; i < numberColumns_; i++) { ray_[i] *= columnScale[i]; } } else if (problemStatus_ == 1 && ray_) { for (int i = 0; i < numberRows_; i++) { ray_[i] *= rowScale[i]; } } } #if ABC_DEBUG>1 // For debug - moves solution back to external and computes stuff void AbcSimplex::checkMoveBack(bool checkDuals) { stateOfProblem_ &= ~(ROW_PRIMAL_OK|ROW_DUAL_OK|COLUMN_PRIMAL_OK|COLUMN_DUAL_OK|ALL_STATUS_OK); permuteOut(ROW_PRIMAL_OK|ROW_DUAL_OK|COLUMN_PRIMAL_OK|COLUMN_DUAL_OK|ALL_STATUS_OK); ClpSimplex::computeObjectiveValue(false); #if ABC_NORMAL_DEBUG>0 printf("Check objective %g\n",objectiveValue()-objectiveOffset_); #endif double * region = new double [numberRows_+numberColumns_]; CoinAbcMemset0(region,numberRows_); ClpModel::times(1.0,columnActivity_,region); int numberInf; double sumInf; numberInf=0; sumInf=0.0; for (int i=0;icolumnUpper_[i]+1.0e-7) { numberInf++; sumInf+=columnActivity_[i]-columnUpper_[i]; } else if (columnActivity_[i]0 if (numberInf) printf("Check column infeasibilities %d sum %g\n",numberInf,sumInf); #endif numberInf=0; sumInf=0.0; for (int i=0;irowUpper_[i]+1.0e-7) { numberInf++; sumInf+=rowActivity_[i]-rowUpper_[i]; } else if (rowActivity_[i]0 if (numberInf) printf("Check row infeasibilities %d sum %g\n",numberInf,sumInf); #endif CoinAbcMemcpy(region,objective(),numberColumns_); ClpModel::transposeTimes(-1.0,dual_,region); numberInf=0; sumInf=0.0; for (int i=0;icolumnLower_[i]) { if (getColumnStatus(i)==ClpSimplex::atLowerBound) { if (region[i]<-1.0e-7) { numberInf++; sumInf-=region[i]; } } else if (getColumnStatus(i)==ClpSimplex::atUpperBound) { if (region[i]>1.0e-7) { numberInf++; sumInf+=region[i]; } } } } #if ABC_NORMAL_DEBUG>0 if (numberInf) printf("Check column dj infeasibilities %d sum %g\n",numberInf,sumInf); #endif if (checkDuals) { numberInf=0; sumInf=0.0; for (int i=0;irowLower_[i]) { if (getRowStatus(i)==ClpSimplex::atLowerBound) { if (dual_[i]<-1.0e-7) { numberInf++; sumInf-=region[i]; } } else if (getRowStatus(i)==ClpSimplex::atUpperBound) { if (dual_[i]>1.0e-7) { numberInf++; sumInf+=region[i]; } } } } #if ABC_NORMAL_DEBUG>0 if (numberInf) printf("Check row dual infeasibilities %d sum %g\n",numberInf,sumInf); #endif } delete [] region; } #if 0 void xxxxxx(const char * where) { printf("xxxxx %s\n",where); } #endif // For debug - checks solutionBasic void AbcSimplex::checkSolutionBasic() const { //work space int whichArray[2]; for (int i=0;i<2;i++) whichArray[i]=getAvailableArray(); CoinIndexedVector * arrayVector = &usefulArray_[whichArray[0]]; double * solution = usefulArray_[whichArray[1]].denseVector(); CoinAbcMemcpy(solution,abcSolution_,numberTotal_); // accumulate non basic stuff double * array = arrayVector->denseVector(); CoinAbcScatterZeroTo(solution,abcPivotVariable_,numberRows_); abcMatrix_->timesIncludingSlacks(-1.0, solution, array); //arrayVector->scan(0,numberRows_,zeroTolerance_); // Ftran adjusted RHS //if (arrayVector->getNumElements()) abcFactorization_->updateFullColumn(*arrayVector); CoinAbcScatterTo(array,solution,abcPivotVariable_,numberRows_); double largestDifference=0.0; int whichDifference=-1; for (int i=0;i1.0e-5&&numberRows_<100) printf("solutionBasic difference is %g on row %d solutionBasic_ %g computed %g\n", difference,i,solutionBasic_[i],array[i]); if (difference>largestDifference) { largestDifference=difference; whichDifference=i; } } if (largestDifference>1.0e-9) printf("Debug largest solutionBasic difference is %g on row %d solutionBasic_ %g computed %g\n", largestDifference,whichDifference,solutionBasic_[whichDifference],array[whichDifference]); arrayVector->clear(); CoinAbcMemset0(solution,numberTotal_); for (int i=0;i<2;i++) setAvailableArray(whichArray[i]); } // For debug - summarizes dj situation void AbcSimplex::checkDjs(int type) const { if (type) { //work space int whichArrays[2]; for (int i=0;i<2;i++) whichArrays[i]=getAvailableArray(); CoinIndexedVector * arrayVector = &usefulArray_[whichArrays[0]]; double * array = arrayVector->denseVector(); int * index = arrayVector->getIndices(); int number = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { double value = costBasic_[iRow]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector->setNumElements(number); // Btran basic costs abcFactorization_->updateFullColumnTranspose(*arrayVector); double largestDifference=0.0; int whichDifference=-1; if (type==2) { for (int i=0;ilargestDifference) { largestDifference=difference; whichDifference=i; } } if (largestDifference>1.0e-9) printf("Debug largest dual difference is %g on row %d dual_ %g computed %g\n", largestDifference,whichDifference,dual_[whichDifference],array[whichDifference]); } // now look at djs double * djs=usefulArray_[whichArrays[1]].denseVector(); CoinAbcMemcpy(djs,abcCost_,numberTotal_); abcMatrix_->transposeTimesNonBasic(-1.0, array,djs); largestDifference=0.0; whichDifference=-1; for (int i=0;i1.0e-5&&numberTotal_<200) printf("Debug dj difference is %g on column %d abcDj_ %g computed %g\n", difference,i,abcDj_[i],djs[i]); if (difference>largestDifference) { largestDifference=difference; whichDifference=i; } break; } } if (largestDifference>1.0e-9) printf("Debug largest dj difference is %g on column %d abcDj_ %g computed %g\n", largestDifference,whichDifference,abcDj_[whichDifference],djs[whichDifference]); CoinAbcMemset0(djs,numberTotal_); arrayVector->clear(); for (int i=0;i<2;i++) setAvailableArray(whichArrays[i]); } int state[8]={0,0,0,0,0,0,0,0}; int badT[8]={0,0,0,0,0,0,0,0}; //int badP[8]={0,0,0,0,0,0,0,0}; int numberInfeasibilities=0; for (int i=0;icurrentDualTolerance_) badT[iStatus]++; //if(fabs(djValue)>perturbationValue) //badP[iStatus]++; break; case AbcSimplex::isFixed: break; case isFree: case superBasic: if(fabs(djValue)>currentDualTolerance_) badT[iStatus]++; //if(fabs(djValue)>perturbationValue) //badP[iStatus]++; break; case atUpperBound: if (fabs(value - upperValue) > primalTolerance_) numberInfeasibilities++; if(djValue>currentDualTolerance_) badT[iStatus]++; //if(djValue>perturbationValue) //badP[iStatus]++; break; case atLowerBound: if (fabs(value - lowerValue) > primalTolerance_) numberInfeasibilities++; if(-djValue>currentDualTolerance_) badT[iStatus]++; //if(-djValue>perturbationValue) //badP[iStatus]++; break; } } if (numberInfeasibilities) printf("Debug %d variables away from bound when should be\n",numberInfeasibilities); int numberBad=0; for (int i=0;i<8;i++) { numberBad += badT[i]/*+badP[i]*/; } if (numberBad) { const char * type[]={"atLowerBound", "atUpperBound", "??", "??", "isFree", "superBasic", "basic", "isFixed"}; for (int i=0;i<8;i++) { if (state[i]) printf("Debug - %s %d total %d bad with tolerance %d bad with perturbation\n", type[i],state[i],badT[i],0/*badP[i]*/); } } } #else // For debug - moves solution back to external and computes stuff void AbcSimplex::checkMoveBack(bool ) { } // For debug - checks solutionBasic void AbcSimplex::checkSolutionBasic() const { } // For debug - summarizes dj situation void AbcSimplex::checkDjs(int) const { } #endif #ifndef EARLY_FACTORIZE #define ABC_NUMBER_USEFUL_NORMAL ABC_NUMBER_USEFUL #else #define ABC_NUMBER_USEFUL_NORMAL ABC_NUMBER_USEFUL-1 #endif static double * elAddress[ABC_NUMBER_USEFUL_NORMAL]; // For debug - prints summary of arrays which are out of kilter void AbcSimplex::checkArrays(int ignoreEmpty) const { if (!numberIterations_||!elAddress[0]) { for (int i=0;imaximumPivots(data.maximumPivots_); } // Loads tolerances etc void ClpSimplex::unloadTolerancesEtc(AbcTolerancesEtc & data) { data.zeroTolerance_ = zeroTolerance_; data.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_; data.largeValue_ = largeValue_; data.alphaAccuracy_ = alphaAccuracy_; data.dualBound_ = dualBound_; data.dualTolerance_ = dualTolerance_; data.primalTolerance_ = primalTolerance_; data.infeasibilityCost_ = infeasibilityCost_; data.incomingInfeasibility_ = incomingInfeasibility_; data.allowedInfeasibility_ = allowedInfeasibility_; data.baseIteration_ = baseIteration_; data.numberRefinements_ = numberRefinements_; data.forceFactorization_ = forceFactorization_; data.perturbation_ = perturbation_; data.dontFactorizePivots_ = dontFactorizePivots_; /// For factorization data.maximumPivots_ = abcFactorization_->maximumPivots(); } // Loads tolerances etc void AbcSimplex::loadTolerancesEtc(const AbcTolerancesEtc & data) { zeroTolerance_ = data.zeroTolerance_; primalToleranceToGetOptimal_ = data.primalToleranceToGetOptimal_; largeValue_ = data.largeValue_; alphaAccuracy_ = data.alphaAccuracy_; dualBound_ = data.dualBound_; dualTolerance_ = data.dualTolerance_; primalTolerance_ = data.primalTolerance_; infeasibilityCost_ = data.infeasibilityCost_; incomingInfeasibility_ = data.incomingInfeasibility_; allowedInfeasibility_ = data.allowedInfeasibility_; baseIteration_ = data.baseIteration_; numberRefinements_ = data.numberRefinements_; forceFactorization_ = data.forceFactorization_; perturbation_ = data.perturbation_; dontFactorizePivots_ = data.dontFactorizePivots_; /// For factorization abcFactorization_->maximumPivots(data.maximumPivots_); } // Loads tolerances etc void AbcSimplex::unloadTolerancesEtc(AbcTolerancesEtc & data) { data.zeroTolerance_ = zeroTolerance_; data.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_; data.largeValue_ = largeValue_; data.alphaAccuracy_ = alphaAccuracy_; data.dualBound_ = dualBound_; data.dualTolerance_ = dualTolerance_; data.primalTolerance_ = primalTolerance_; data.infeasibilityCost_ = infeasibilityCost_; data.incomingInfeasibility_ = incomingInfeasibility_; data.allowedInfeasibility_ = allowedInfeasibility_; data.baseIteration_ = baseIteration_; data.numberRefinements_ = numberRefinements_; data.forceFactorization_ = forceFactorization_; data.perturbation_ = perturbation_; data.dontFactorizePivots_ = dontFactorizePivots_; /// For factorization data.maximumPivots_ = abcFactorization_->maximumPivots(); } #endif // Swaps two variables (for now just updates basic list) and sets status void AbcSimplex::swap(int pivotRow,int nonBasicPosition,Status newStatus) { // set status setInternalStatus(nonBasicPosition,newStatus); solutionBasic_[pivotRow]=abcSolution_[nonBasicPosition]; lowerBasic_[pivotRow]=abcLower_[nonBasicPosition]; upperBasic_[pivotRow]=abcUpper_[nonBasicPosition]; costBasic_[pivotRow]=abcCost_[nonBasicPosition]; } // Swaps two variables (for now just updates basic list) void AbcSimplex::swap(int pivotRow,int nonBasicPosition) { solutionBasic_[pivotRow]=abcSolution_[nonBasicPosition]; lowerBasic_[pivotRow]=lowerSaved_[nonBasicPosition]; upperBasic_[pivotRow]=upperSaved_[nonBasicPosition]; costBasic_[pivotRow]=abcCost_[nonBasicPosition]; } // Move status and solution to ClpSimplex void AbcSimplex::moveStatusToClp(ClpSimplex * clpModel) { assert (clpModel); if (algorithm_<0) clpModel->setObjectiveValue(clpObjectiveValue()); else clpModel->setObjectiveValue(objectiveValue()); clpModel->setProblemStatus(problemStatus_); clpModel->setSecondaryStatus(secondaryStatus_); clpModel->setNumberIterations(numberIterations_); clpModel->setSumDualInfeasibilities(sumDualInfeasibilities_); clpModel->setSumOfRelaxedDualInfeasibilities(sumOfRelaxedDualInfeasibilities_); clpModel->setNumberDualInfeasibilities(numberDualInfeasibilities_); clpModel->setSumPrimalInfeasibilities(sumPrimalInfeasibilities_); clpModel->setSumOfRelaxedPrimalInfeasibilities(sumOfRelaxedPrimalInfeasibilities_); clpModel->setNumberPrimalInfeasibilities(numberPrimalInfeasibilities_); permuteOut(ROW_PRIMAL_OK|ROW_DUAL_OK|COLUMN_PRIMAL_OK|COLUMN_DUAL_OK|ALL_STATUS_OK); CoinAbcMemcpy(clpModel->primalColumnSolution(),primalColumnSolution(),numberColumns_); CoinAbcMemcpy(clpModel->dualColumnSolution(),dualColumnSolution(),numberColumns_); CoinAbcMemcpy(clpModel->primalRowSolution(),primalRowSolution(),numberRows_); CoinAbcMemcpy(clpModel->dualRowSolution(),dualRowSolution(),numberRows_); CoinAbcMemcpy(clpModel->statusArray(),statusArray(),numberTotal_); } // Move status and solution from ClpSimplex void AbcSimplex::moveStatusFromClp(ClpSimplex * clpModel) { assert (clpModel); problemStatus_=clpModel->problemStatus(); secondaryStatus_=clpModel->secondaryStatus(); numberIterations_=clpModel->numberIterations(); sumDualInfeasibilities_ = clpModel->sumDualInfeasibilities(); sumOfRelaxedDualInfeasibilities_ = clpModel->sumOfRelaxedDualInfeasibilities(); numberDualInfeasibilities_ = clpModel->numberDualInfeasibilities(); sumPrimalInfeasibilities_ = clpModel->sumPrimalInfeasibilities(); sumOfRelaxedPrimalInfeasibilities_ = clpModel->sumOfRelaxedPrimalInfeasibilities(); numberPrimalInfeasibilities_ = clpModel->numberPrimalInfeasibilities(); CoinAbcMemcpy(primalColumnSolution(),clpModel->primalColumnSolution(),numberColumns_); CoinAbcMemcpy(dualColumnSolution(),clpModel->dualColumnSolution(),numberColumns_); CoinAbcMemcpy(primalRowSolution(),clpModel->primalRowSolution(),numberRows_); CoinAbcMemcpy(dualRowSolution(),clpModel->dualRowSolution(),numberRows_); CoinAbcMemcpy(statusArray(),clpModel->statusArray(),numberTotal_); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); } // Clears an array and says available (-1 does all) void AbcSimplex::clearArrays(int which) { if (which>=0) { if (usefulArray_[which].getNumElements()) usefulArray_[which].clear(); int check=1<abcSimplex(); #else AbcSimplex * model; return -1; #endif double objective; if (model_->algorithm() < 0) { objective = model_->rawObjectiveValue(); objective -= model_->bestPossibleImprovement(); } else { objective = model->abcNonLinearCost()->feasibleReportCost(); } double infeasibility; double realInfeasibility = 0.0; int numberInfeasibilities; int iterationNumber = model->numberIterations(); //numberTimesFlagged_ = 0; if (model->algorithm() < 0) { // dual infeasibility = model->sumPrimalInfeasibilities(); numberInfeasibilities = model->numberPrimalInfeasibilities(); } else { //primal infeasibility = model->sumDualInfeasibilities(); realInfeasibility = model->abcNonLinearCost()->sumInfeasibilities(); numberInfeasibilities = model->numberDualInfeasibilities(); } int i; int numberMatched = 0; int matched = 0; int nsame = 0; for (i = 0; i < CLP_PROGRESS; i++) { bool matchedOnObjective = objective == objective_[i]; bool matchedOnInfeasibility = infeasibility == infeasibility_[i]; bool matchedOnInfeasibilities = (numberInfeasibilities == numberInfeasibilities_[i]); if (matchedOnObjective && matchedOnInfeasibility && matchedOnInfeasibilities) { matched |= (1 << i); // Check not same iteration if (iterationNumber != iterationNumber_[i]) { numberMatched++; #if ABC_NORMAL_DEBUG>0 // here mainly to get over compiler bug? if (model->messageHandler()->logLevel() > 10) printf("%d %d %d %d %d loop check\n", i, numberMatched, matchedOnObjective, matchedOnInfeasibility, matchedOnInfeasibilities); #endif } else { // stuck but code should notice nsame++; } } if (i) { objective_[i-1] = objective_[i]; infeasibility_[i-1] = infeasibility_[i]; realInfeasibility_[i-1] = realInfeasibility_[i]; numberInfeasibilities_[i-1] = numberInfeasibilities_[i]; iterationNumber_[i-1] = iterationNumber_[i]; } } objective_[CLP_PROGRESS-1] = objective; infeasibility_[CLP_PROGRESS-1] = infeasibility; realInfeasibility_[CLP_PROGRESS-1] = realInfeasibility; numberInfeasibilities_[CLP_PROGRESS-1] = numberInfeasibilities; iterationNumber_[CLP_PROGRESS-1] = iterationNumber; if (nsame == CLP_PROGRESS) numberMatched = CLP_PROGRESS; // really stuck if (model->progressFlag()) numberMatched = 0; numberTimes_++; if (numberTimes_ < 10) numberMatched = 0; // skip if just last time as may be checking something if (matched == (1 << (CLP_PROGRESS - 1))) numberMatched = 0; if (numberMatched) { model->messageHandler()->message(CLP_POSSIBLELOOP, model->messages()) << numberMatched << matched << numberTimes_ << CoinMessageEol; printf("loop detected %d times out of %d\n",numberBadTimes_,numberTimes_); numberBadTimes_++; if (numberBadTimes_ < 10) { // make factorize every iteration model->forceFactorization(1); if (numberBadTimes_ < 2) { startCheck(); // clear other loop check if (model->algorithm() < 0) { // dual - change tolerance model->setCurrentDualTolerance(model->currentDualTolerance() * 1.05); // if infeasible increase dual bound if (model->currentDualBound() < 1.0e17) { model->setDualBound(model->currentDualBound() * 1.1); static_cast(model)->bounceTolerances(100); } } else { abort(); // primal - change tolerance if (numberBadTimes_ > 3) model->setCurrentPrimalTolerance(model->currentPrimalTolerance() * 1.05); // if infeasible increase infeasibility cost //if (model->nonLinearCost()->numberInfeasibilities() && // model->infeasibilityCost() < 1.0e17) { // model->setInfeasibilityCost(model->infeasibilityCost() * 1.1); //} } } else { // flag int iSequence; if (model->algorithm() < 0) { // dual if (model->currentDualBound() > 1.0e14) model->setDualBound(1.0e14); iSequence = in_[CLP_CYCLE-1]; } else { // primal if (model->infeasibilityCost() > 1.0e14) model->setInfeasibilityCost(1.0e14); iSequence = out_[CLP_CYCLE-1]; } if (iSequence >= 0) { char x = model->isColumn(iSequence) ? 'C' : 'R'; if (model->messageHandler()->logLevel() >= 63) model->messageHandler()->message(CLP_SIMPLEX_FLAG, model->messages()) << x << model->sequenceWithin(iSequence) << CoinMessageEol; // if Gub then needs to be sequenceIn_ int save = model->sequenceIn(); model->setSequenceIn(iSequence); model->setFlagged(iSequence); model->setLastBadIteration(model->numberIterations()); model->setSequenceIn(save); //printf("flagging %d from loop\n",iSequence); startCheck(); } else { // Give up #if ABC_NORMAL_DEBUG>0 if (model->messageHandler()->logLevel() >= 63) printf("***** All flagged?\n"); #endif return 4; } // reset numberBadTimes_ = 2; } return -2; } else { // look at solution and maybe declare victory if (infeasibility < 1.0e-4) { return 0; } else { model->messageHandler()->message(CLP_LOOP, model->messages()) << CoinMessageEol; #ifndef NDEBUG printf("debug loop AbcSimplex A\n"); abort(); #endif return 3; } } } return -1; } #if 0 void AbcSimplex::loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpSimplex::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); translate(DO_SCALE_AND_MATRIX|DO_BASIS_AND_ORDER|DO_STATUS|DO_SOLUTION); } #endif // For debug - check pivotVariable consistent void AbcSimplex::checkConsistentPivots() const { unsigned char * copyStatus = CoinCopyOfArray(internalStatus_,numberTotal_); int nBad=0; for (int i=0;i=0&&knumberTotal();i++) { if (this->getInternalStatus(i)!=AbcSimplex::basic) printf("%d status %d primal %g dual %g lb %g ub %g\n", i,this->getInternalStatus(i),this->solutionRegion()[i], this->djRegion()[i],this->lowerRegion()[i],this->upperRegion()[i]); } for (int i=0;inumberRows();i++) { printf("%d %g <= %g <= %g -pivot %d cost %g\n", i,this->lowerBasic()[i],this->solutionBasic()[i], this->upperBasic()[i],this->pivotVariable()[i],this->costBasic()[i]); } printf("XXend\n"); } #if ABC_PARALLEL==1 // so thread can find out which one it is int AbcSimplex::whichThread() const { pthread_t thisThread=pthread_self(); int whichThread; for (whichThread=0;whichThread //############################################################################# class CoinIndexedVector; /** Primal Column Pivot Steepest Edge Algorithm Class See Forrest-Goldfarb paper for algorithm */ class AbcPrimalColumnSteepest : public AbcPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none. The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row Parts of operation split out into separate functions for profiling and speed */ virtual int pivotColumn(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1); /// Just update djs void justDjs(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1); /// Update djs doing partial pricing (dantzig) int partialPricing(CoinIndexedVector * updates, int numberWanted, int numberLook); /// Update djs, weights for Devex using djs void djsAndDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1); /// Update djs, weights for Devex using pivot row void djsAndDevex2(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1); /// Update weights for Devex void justDevex(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1); /** Does steepest work type - 0 - just djs 1 - just steepest 2 - both using scaleFactor 3 - both using extra array */ int doSteepestWork(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1, int type); /// Updates weights - part 1 - also checks accuracy virtual void updateWeights(CoinIndexedVector * input); /// Checks accuracy - just for debug void checkAccuracy(int sequence, double relativeTolerance, CoinIndexedVector * rowArray1); /// Initialize weights void initializeWeights(); /** Save weights - this may initialize weights as well mode is - 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights 5) at end of values pass (so need initialization) */ virtual void saveWeights(AbcSimplex * model, int mode); /// Gets rid of last update virtual void unrollWeights(); /// Gets rid of all arrays virtual void clearArrays(); /// Returns true if would not find any column virtual bool looksOptimal() const; /// Called when maximum pivots changes virtual void maximumPivotsChanged(); //@} /**@name gets and sets */ //@{ /// Mode inline int mode() const { return mode_; } //@} /** enums for persistence */ enum Persistence { normal = 0x00, // create (if necessary) and destroy keep = 0x01 // create (if necessary) and leave }; ///@name Constructors and destructors //@{ /** Default Constructor 0 is exact devex, 1 full steepest, 2 is partial exact devex 3 switches between 0 and 2 depending on factorization 4 starts as partial dantzig/devex but then may switch between 0 and 2. By partial exact devex is meant that the weights are updated as normal but only part of the nonbasic variables are scanned. This can be faster on very easy problems. */ AbcPrimalColumnSteepest(int mode = 3); /// Copy constructor AbcPrimalColumnSteepest(const AbcPrimalColumnSteepest & rhs); /// Assignment operator AbcPrimalColumnSteepest & operator=(const AbcPrimalColumnSteepest& rhs); /// Destructor virtual ~AbcPrimalColumnSteepest (); /// Clone virtual AbcPrimalColumnPivot * clone(bool copyData = true) const; //@} ///@name Private functions to deal with devex /** reference would be faster using AbcSimplex's status_, but I prefer to keep modularity. */ inline bool reference(int i) const { return ((reference_[i>>5] >> (i & 31)) & 1) != 0; } inline void setReference(int i, bool trueFalse) { unsigned int & value = reference_[i>>5]; int bit = i & 31; if (trueFalse) value |= (1 << bit); else value &= ~(1 << bit); } /// Set/ get persistence inline void setPersistence(Persistence life) { persistence_ = life; } inline Persistence persistence() const { return persistence_ ; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data // Update weight double devex_; /// weight array double * weights_; /// square of infeasibility array (just for infeasible columns) CoinIndexedVector * infeasible_; /// alternate weight array (so we can unroll) CoinIndexedVector * alternateWeights_; /// save weight array (so we can use checkpoint) double * savedWeights_; // Array for exact devex to say what is in reference framework unsigned int * reference_; /** Status 0) Normal -1) Needs initialization 1) Weights are stored by sequence number */ int state_; /** 0 is exact devex, 1 full steepest, 2 is partial exact devex 3 switches between 0 and 2 depending on factorization 4 starts as partial dantzig/devex but then may switch between 0 and 2. 5 is always partial dantzig By partial exact devex is meant that the weights are updated as normal but only part of the nonbasic variables are scanned. This can be faster on very easy problems. New dubious option is >=10 which does mini-sprint */ int mode_; /// Life of weights Persistence persistence_; /// Number of times switched from partial dantzig to 0/2 int numberSwitched_; // This is pivot row (or pivot sequence round re-factorization) int pivotSequence_; // This is saved pivot sequence int savedPivotSequence_; // This is saved outgoing variable int savedSequenceOut_; // Iteration when last rectified int lastRectified_; // Size of factorization at invert (used to decide algorithm) int sizeFactorization_; //@} }; #endif Clp-1.15.10/src/ClpPrimalColumnPivot.cpp0000644000076600007660000000444411510657452016445 0ustar coincoin/* $Id: ClpPrimalColumnPivot.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpPrimalColumnPivot.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPrimalColumnPivot::ClpPrimalColumnPivot () : model_(NULL), type_(-1), looksOptimal_(false) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPrimalColumnPivot::ClpPrimalColumnPivot (const ClpPrimalColumnPivot & source) : model_(source.model_), type_(source.type_), looksOptimal_(source.looksOptimal_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPrimalColumnPivot::~ClpPrimalColumnPivot () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPrimalColumnPivot & ClpPrimalColumnPivot::operator=(const ClpPrimalColumnPivot& rhs) { if (this != &rhs) { type_ = rhs.type_; model_ = rhs.model_; looksOptimal_ = rhs.looksOptimal_; } return *this; } void ClpPrimalColumnPivot::saveWeights(ClpSimplex * model, int ) { model_ = model; } // checks accuracy and may re-initialize (may be empty) void ClpPrimalColumnPivot::updateWeights(CoinIndexedVector *) { } // Gets rid of all arrays void ClpPrimalColumnPivot::clearArrays() { } /* Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ int ClpPrimalColumnPivot::numberSprintColumns(int & ) const { return 0; } // Switch off sprint idea void ClpPrimalColumnPivot::switchOffSprint() { } Clp-1.15.10/src/ClpCholeskyUfl.cpp0000644000076600007660000004022211552601036015234 0ustar coincoin/* $Id: ClpCholeskyUfl.cpp 1723 2011-04-17 15:07:10Z 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 "ClpConfig.h" extern "C" { #ifndef COIN_HAS_CHOLMOD #ifndef COIN_HAS_AMD #error "Need to have AMD or CHOLMOD to compile ClpCholeskyUfl." #else #include "amd.h" #endif #else #include "cholmod.h" #endif } #include "CoinPragma.hpp" #include "ClpCholeskyUfl.hpp" #include "ClpMessage.hpp" #include "ClpInterior.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyUfl::ClpCholeskyUfl (int denseThreshold) : ClpCholeskyBase(denseThreshold) { type_ = 14; L_ = NULL; c_ = NULL; #ifdef COIN_HAS_CHOLMOD c_ = (cholmod_common*) malloc(sizeof(cholmod_common)); cholmod_start (c_) ; // Can't use supernodal as may not be positive definite c_->supernodal = 0; #endif } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyUfl::ClpCholeskyUfl (const ClpCholeskyUfl & rhs) : ClpCholeskyBase(rhs) { abort(); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyUfl::~ClpCholeskyUfl () { #ifdef COIN_HAS_CHOLMOD cholmod_free_factor (&L_, c_) ; cholmod_finish (c_) ; free(c_); #endif } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyUfl & ClpCholeskyUfl::operator=(const ClpCholeskyUfl& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); abort(); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyUfl::clone() const { return new ClpCholeskyUfl(*this); } #ifndef COIN_HAS_CHOLMOD /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyUfl::order(ClpInterior * model) { int iRow; model_ = model; if (preOrder(false, true, doKKT_)) return -1; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; double Control[AMD_CONTROL]; double Info[AMD_INFO]; amd_defaults(Control); //amd_control(Control); int returnCode = amd_order(numberRows_, choleskyStart_, choleskyRow_, permute_, Control, Info); delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; //amd_info(Info); if (returnCode != AMD_OK) { std::cout << "AMD ordering failed" << std::endl; return 1; } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[permute_[iRow]] = iRow; } return 0; } #else /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyUfl::order(ClpInterior * model) { numberRows_ = model->numberRows(); if (doKKT_) { numberRows_ += numberRows_ + model->numberColumns(); printf("finish coding UFL KKT!\n"); abort(); } rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); // Space for starts choleskyStart_ = new CoinBigIndex[numberRows_+1]; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; cholmod_sparse A ; A.nrow = numberRows_; A.ncol = numberRows_; A.nzmax = choleskyStart_[numberRows_]; A.p = choleskyStart_; A.i = choleskyRow_; A.x = NULL; A.stype = -1; A.itype = CHOLMOD_INT; A.xtype = CHOLMOD_PATTERN; A.dtype = CHOLMOD_DOUBLE; A.sorted = 1; A.packed = 1; c_->nmethods = 9; c_->postorder = true; //c_->dbound=1.0e-20; L_ = cholmod_analyze (&A, c_) ; if (c_->status) { COIN_DETAIL_PRINT(std::cout << "CHOLMOD ordering failed" << std::endl); return 1; } else { COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", c_->lnz, c_->fl)); } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } return 0; } #endif /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyUfl::symbolic() { #ifdef COIN_HAS_CHOLMOD return 0; #else return ClpCholeskyBase::symbolic(); #endif } #ifdef COIN_HAS_CHOLMOD /* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyUfl::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; //double smallest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = 0.0; perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = sqrt(perturbation);; perturbation = 1.0; } double delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactor_ + choleskyStart_[iRow]; int * which = choleskyRow_ + choleskyStart_[iRow]; int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } } int j; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_); largest2 *= 1.0e-20; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStart_[iRow]; double diagonal = sparseFactor_[start]; if (diagonal > largest2) { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); } else { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); rowsDropped[iRow] = 2; numberDroppedBefore++; } } } delete [] work; cholmod_sparse A ; A.nrow = numberRows_; A.ncol = numberRows_; A.nzmax = choleskyStart_[numberRows_]; A.p = choleskyStart_; A.i = choleskyRow_; A.x = sparseFactor_; A.stype = -1; A.itype = CHOLMOD_INT; A.xtype = CHOLMOD_REAL; A.dtype = CHOLMOD_DOUBLE; A.sorted = 1; A.packed = 1; cholmod_factorize (&A, L_, c_) ; /* factorize */ choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier //int oldDropped=numberRowsDropped_; if (newDropped || numberRowsDropped_) { //std::cout <<"Rank "<oldDropped) //std::cout<<" ( "<x); x = cholmod_solve (CHOLMOD_A, L_, b, c_) ; CoinMemcpyN((double *) x->x, numberRows_, region); cholmod_free_dense (&x, c_) ; cholmod_free_dense (&b, c_) ; } #else void ClpCholeskyUfl::solve (double * region) { ClpCholeskyBase::solve(region); } #endif Clp-1.15.10/src/AbcCommon.hpp0000644000076600007660000000250012101105055014174 0ustar coincoin/* $Id: AbcCommon.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2003, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef AbcCommon_H #define AbcCommon_H #include "ClpConfig.h" /* 0 - off 1 - build Abc serial but no inherit code 2 - build Abc serial and inherit code 3 - build Abc cilk parallel but no inherit code 4 - build Abc cilk parallel and inherit code */ #ifdef CLP_HAS_ABC #if CLP_HAS_ABC==1 #ifndef ABC_PARALLEL #define ABC_PARALLEL 0 #endif #ifndef ABC_USE_HOMEGROWN_LAPACK #define ABC_USE_HOMEGROWN_LAPACK 2 #endif #elif CLP_HAS_ABC==2 #ifndef ABC_PARALLEL #define ABC_PARALLEL 0 #endif #ifndef ABC_USE_HOMEGROWN_LAPACK #define ABC_USE_HOMEGROWN_LAPACK 2 #endif #ifndef ABC_INHERIT #define ABC_INHERIT #endif #elif CLP_HAS_ABC==3 #ifndef ABC_PARALLEL #define ABC_PARALLEL 2 #endif #ifndef ABC_USE_HOMEGROWN_LAPACK #define ABC_USE_HOMEGROWN_LAPACK 2 #endif #elif CLP_HAS_ABC==4 #ifndef ABC_PARALLEL #define ABC_PARALLEL 2 #endif #ifndef ABC_USE_HOMEGROWN_LAPACK #define ABC_USE_HOMEGROWN_LAPACK 2 #endif #ifndef ABC_INHERIT #define ABC_INHERIT #endif #else #error "Valid values for CLP_HAS_ABC are 0-4" #endif #endif #endif Clp-1.15.10/src/CoinAbcSmallFactorization3.cpp0000644000076600007660000000103012101105055017435 0ustar coincoin/* $Id: CoinAbcSmallFactorization3.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization3.cpp" #endif Clp-1.15.10/src/config_clp_default.h0000644000076600007660000000110712377500504015624 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 CLP_VERSION "1.15.10" /* Major Version number of project */ #define CLP_VERSION_MAJOR 1 /* Minor Version number of project */ #define CLP_VERSION_MINOR 15 /* Release Version number of project */ #define CLP_VERSION_RELEASE 10 Clp-1.15.10/src/CbcOrClpParam.cpp0000644000076600007660000051400512254115334014763 0ustar coincoin/* $Id: CbcOrClpParam.cpp 2011 2013-12-17 18:41:32Z 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). #include "CoinPragma.hpp" #include "CoinTime.hpp" #include "CbcOrClpParam.hpp" #include #include #include #ifdef COIN_HAS_CBC #ifdef COIN_HAS_CLP #include "OsiClpSolverInterface.hpp" #include "ClpSimplex.hpp" #endif #include "CbcModel.hpp" #endif #include "CoinHelperFunctions.hpp" #ifdef COIN_HAS_CLP #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #endif #if COIN_INT_MAX==0 #undef COIN_INT_MAX #define COIN_INT_MAX 2147483647 #endif #ifdef COIN_HAS_READLINE #include #include #endif #ifdef COIN_HAS_CBC // from CoinSolve static char coin_prompt[] = "Coin:"; #else static char coin_prompt[] = "Clp:"; #endif #ifdef CLP_CILK #ifndef CBC_THREAD #define CBC_THREAD #endif #endif #if defined(COIN_HAS_WSMP) && ! defined(USE_EKKWSSMP) #ifndef CBC_THREAD #define CBC_THREAD #endif #endif #include "ClpConfig.h" #ifdef CLP_HAS_ABC #include "AbcCommon.hpp" #endif static bool doPrinting = true; std::string afterEquals = ""; static char printArray[200]; void setCbcOrClpPrinting(bool yesNo) { doPrinting = yesNo; } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- CbcOrClpParam::CbcOrClpParam () : 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), display_(0), intValue_(-1), doubleValue_(-1.0), stringValue_(""), whereUsed_(7) { } // Other constructors CbcOrClpParam::CbcOrClpParam (std::string name, std::string help, double lower, double upper, CbcOrClpParameterType type, int display) : type_(type), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1), display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_(""), whereUsed_(7) { lowerDoubleValue_ = lower; upperDoubleValue_ = upper; gutsOfConstructor(); } CbcOrClpParam::CbcOrClpParam (std::string name, std::string help, int lower, int upper, CbcOrClpParameterType type, int display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1), display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_(""), whereUsed_(7) { gutsOfConstructor(); lowerIntValue_ = lower; upperIntValue_ = upper; } // Other strings will be added by append CbcOrClpParam::CbcOrClpParam (std::string name, std::string help, std::string firstValue, CbcOrClpParameterType type, int whereUsed, int display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(0), display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_(""), whereUsed_(whereUsed) { gutsOfConstructor(); definedKeyWords_.push_back(firstValue); } // Action CbcOrClpParam::CbcOrClpParam (std::string name, std::string help, CbcOrClpParameterType type, int whereUsed, int display) : type_(type), lowerDoubleValue_(0.0), upperDoubleValue_(0.0), lowerIntValue_(0), upperIntValue_(0), definedKeyWords_(), name_(name), shortHelp_(help), longHelp_(), action_(type), currentKeyWord_(-1), display_(display), intValue_(-1), doubleValue_(-1.0), stringValue_("") { whereUsed_ = whereUsed; gutsOfConstructor(); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- CbcOrClpParam::CbcOrClpParam (const CbcOrClpParam & 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_; display_ = rhs.display_; intValue_ = rhs.intValue_; doubleValue_ = rhs.doubleValue_; stringValue_ = rhs.stringValue_; whereUsed_ = rhs.whereUsed_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- CbcOrClpParam::~CbcOrClpParam () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- CbcOrClpParam & CbcOrClpParam::operator=(const CbcOrClpParam & 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_; display_ = rhs.display_; intValue_ = rhs.intValue_; doubleValue_ = rhs.doubleValue_; stringValue_ = rhs.stringValue_; whereUsed_ = rhs.whereUsed_; } return *this; } void CbcOrClpParam::gutsOfConstructor() { std::string::size_type shriekPos = name_.find('!'); lengthName_ = static_cast(name_.length()); if ( shriekPos == std::string::npos ) { //does not contain '!' lengthMatch_ = lengthName_; } else { lengthMatch_ = static_cast(shriekPos); name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1); lengthName_--; } } // Returns length of name for printing int CbcOrClpParam::lengthMatchName ( ) const { if (lengthName_ == lengthMatch_) return lengthName_; else return lengthName_ + 2; } // Insert string (only valid for keywords) void CbcOrClpParam::append(std::string keyWord) { definedKeyWords_.push_back(keyWord); } int CbcOrClpParam::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 CbcOrClpParam::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 CbcOrClpParam::parameterOption ( std::string check ) const { int numberItems = static_cast(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('!'); size_t length1 = thisOne.length(); size_t 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 && length2 <= check.length()) { 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 CbcOrClpParam::printOptions ( ) const { std::cout << "= 0 && currentKeyWord_ < static_cast(definedKeyWords_.size())); std::string current = definedKeyWords_[currentKeyWord_]; std::string::size_type shriekPos = current.find('!'); if ( shriekPos != std::string::npos ) { //contains '!' current = current.substr(0, shriekPos) + "(" + current.substr(shriekPos + 1) + ")"; } std::cout << ";\n\tcurrent " << current << ">" << std::endl; } // Print action and string void CbcOrClpParam::printString() const { if (name_ == "directory") std::cout << "Current working directory is " << stringValue_ << std::endl; else if (name_.substr(0, 6) == "printM") std::cout << "Current value of printMask is " << stringValue_ << std::endl; else std::cout << "Current default (if $ as parameter) for " << name_ << " is " << stringValue_ << std::endl; } void CoinReadPrintit(const char * input) { int length = static_cast(strlen(input)); char temp[101]; int i; int n = 0; for (i = 0; i < length; i++) { if (input[i] == '\n') { temp[n] = '\0'; std::cout << temp << std::endl; n = 0; } else if (n >= 65 && input[i] == ' ') { temp[n] = '\0'; std::cout << temp << std::endl; n = 0; } else if (n || input[i] != ' ') { temp[n++] = input[i]; } } if (n) { temp[n] = '\0'; std::cout << temp << std::endl; } } // Print Long help void CbcOrClpParam::printLongHelp() const { if (type_ >= 1 && type_ < 400) { CoinReadPrintit(longHelp_.c_str()); if (type_ < CLP_PARAM_INT_SOLVERLOGLEVEL) { printf("\n", lowerDoubleValue_, upperDoubleValue_, doubleValue_); assert (upperDoubleValue_ > lowerDoubleValue_); } else if (type_ < CLP_PARAM_STR_DIRECTION) { printf("\n", lowerIntValue_, upperIntValue_, intValue_); assert (upperIntValue_ > lowerIntValue_); } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) { printOptions(); } } } #ifdef COIN_HAS_CBC int CbcOrClpParam::setDoubleParameter (OsiSolverInterface * model, double value) { int returnCode; setDoubleParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets double parameter and returns printable string and error code const char * CbcOrClpParam::setDoubleParameterWithMessage ( OsiSolverInterface * model, double value , int & returnCode) { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { sprintf(printArray, "%g was provided for %s - valid range is %g to %g", value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; returnCode = 1; } else { double oldValue = doubleValue_; doubleValue_ = value; 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: break; } sprintf(printArray, "%s was changed from %g to %g", name_.c_str(), oldValue, value); returnCode = 0; } return printArray; } #endif #ifdef COIN_HAS_CLP int CbcOrClpParam::setDoubleParameter (ClpSimplex * model, double value) { int returnCode; setDoubleParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets int parameter and returns printable string and error code const char * CbcOrClpParam::setDoubleParameterWithMessage ( ClpSimplex * model, double value , int & returnCode) { double oldValue = doubleValue_; if (value < lowerDoubleValue_ || value > upperDoubleValue_) { sprintf(printArray, "%g was provided for %s - valid range is %g to %g", value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); returnCode = 1; } else { sprintf(printArray, "%s was changed from %g to %g", name_.c_str(), oldValue, value); returnCode = 0; doubleValue_ = value; switch (type_) { case CLP_PARAM_DBL_DUALTOLERANCE: model->setDualTolerance(value); break; case CLP_PARAM_DBL_PRIMALTOLERANCE: model->setPrimalTolerance(value); break; case CLP_PARAM_DBL_ZEROTOLERANCE: model->setSmallElementValue(value); break; case CLP_PARAM_DBL_DUALBOUND: model->setDualBound(value); break; case CLP_PARAM_DBL_PRIMALWEIGHT: model->setInfeasibilityCost(value); break; #ifndef COIN_HAS_CBC case CLP_PARAM_DBL_TIMELIMIT: model->setMaximumSeconds(value); break; #endif case CLP_PARAM_DBL_OBJSCALE: model->setObjectiveScale(value); break; case CLP_PARAM_DBL_RHSSCALE: model->setRhsScale(value); break; case CLP_PARAM_DBL_PRESOLVETOLERANCE: model->setDblParam(ClpPresolveTolerance, value); break; default: break; } } return printArray; } double CbcOrClpParam::doubleParameter (ClpSimplex * model) const { double value; switch (type_) { #ifndef COIN_HAS_CBC case CLP_PARAM_DBL_DUALTOLERANCE: value = model->dualTolerance(); break; case CLP_PARAM_DBL_PRIMALTOLERANCE: value = model->primalTolerance(); break; #endif case CLP_PARAM_DBL_ZEROTOLERANCE: value = model->getSmallElementValue(); break; case CLP_PARAM_DBL_DUALBOUND: value = model->dualBound(); break; case CLP_PARAM_DBL_PRIMALWEIGHT: value = model->infeasibilityCost(); break; #ifndef COIN_HAS_CBC case CLP_PARAM_DBL_TIMELIMIT: value = model->maximumSeconds(); break; #endif case CLP_PARAM_DBL_OBJSCALE: value = model->objectiveScale(); break; case CLP_PARAM_DBL_RHSSCALE: value = model->rhsScale(); break; default: value = doubleValue_; break; } return value; } int CbcOrClpParam::setIntParameter (ClpSimplex * model, int value) { int returnCode; setIntParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets int parameter and returns printable string and error code const char * CbcOrClpParam::setIntParameterWithMessage ( ClpSimplex * model, int value , int & returnCode) { int oldValue = intValue_; if (value < lowerIntValue_ || value > upperIntValue_) { sprintf(printArray, "%d was provided for %s - valid range is %d to %d", value, name_.c_str(), lowerIntValue_, upperIntValue_); returnCode = 1; } else { intValue_ = value; sprintf(printArray, "%s was changed from %d to %d", name_.c_str(), oldValue, value); returnCode = 0; switch (type_) { case CLP_PARAM_INT_SOLVERLOGLEVEL: model->setLogLevel(value); if (value > 2) model->factorization()->messageLevel(8); else model->factorization()->messageLevel(0); break; case CLP_PARAM_INT_MAXFACTOR: model->factorization()->maximumPivots(value); break; case CLP_PARAM_INT_PERTVALUE: model->setPerturbation(value); break; case CLP_PARAM_INT_MAXITERATION: model->setMaximumIterations(value); break; case CLP_PARAM_INT_SPECIALOPTIONS: model->setSpecialOptions(value); break; case CLP_PARAM_INT_RANDOMSEED: { if (value==0) { double time = fabs(CoinGetTimeOfDay()); while (time>=COIN_INT_MAX) time *= 0.5; value = static_cast(time); sprintf(printArray, "using time of day %s was changed from %d to %d", name_.c_str(), oldValue, value); } model->setRandomSeed(value); } break; case CLP_PARAM_INT_MORESPECIALOPTIONS: model->setMoreSpecialOptions(value); break; #ifndef COIN_HAS_CBC #ifdef CBC_THREAD case CBC_PARAM_INT_THREADS: model->setNumberThreads(value); break; #endif #endif default: break; } } return printArray; } int CbcOrClpParam::intParameter (ClpSimplex * model) const { int value; switch (type_) { #ifndef COIN_HAS_CBC case CLP_PARAM_INT_SOLVERLOGLEVEL: value = model->logLevel(); break; #endif case CLP_PARAM_INT_MAXFACTOR: value = model->factorization()->maximumPivots(); break; break; case CLP_PARAM_INT_PERTVALUE: value = model->perturbation(); break; case CLP_PARAM_INT_MAXITERATION: value = model->maximumIterations(); break; case CLP_PARAM_INT_SPECIALOPTIONS: value = model->specialOptions(); break; case CLP_PARAM_INT_RANDOMSEED: value = model->randomNumberGenerator()->getSeed(); break; case CLP_PARAM_INT_MORESPECIALOPTIONS: value = model->moreSpecialOptions(); break; #ifndef COIN_HAS_CBC #ifdef CBC_THREAD case CBC_PARAM_INT_THREADS: value = model->numberThreads(); break; #endif #endif default: value = intValue_; break; } return value; } #endif int CbcOrClpParam::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; } } #ifdef COIN_HAS_CBC double CbcOrClpParam::doubleParameter (OsiSolverInterface * #ifndef NDEBUG model #endif ) const { double value = 0.0; switch (type_) { case CLP_PARAM_DBL_DUALTOLERANCE: assert(model->getDblParam(OsiDualTolerance, value)); break; case CLP_PARAM_DBL_PRIMALTOLERANCE: assert(model->getDblParam(OsiPrimalTolerance, value)); break; default: return doubleValue_; break; } return value; } int CbcOrClpParam::setIntParameter (OsiSolverInterface * model, int value) { int returnCode; setIntParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets int parameter and returns printable string and error code const char * CbcOrClpParam::setIntParameterWithMessage ( OsiSolverInterface * model, int value , int & returnCode) { if (value < lowerIntValue_ || value > upperIntValue_) { sprintf(printArray, "%d was provided for %s - valid range is %d to %d", value, name_.c_str(), lowerIntValue_, upperIntValue_); returnCode = 1; } else { int oldValue = intValue_; intValue_ = oldValue; switch (type_) { case CLP_PARAM_INT_SOLVERLOGLEVEL: model->messageHandler()->setLogLevel(value); break; default: break; } sprintf(printArray, "%s was changed from %d to %d", name_.c_str(), oldValue, value); returnCode = 0; } return printArray; } int CbcOrClpParam::intParameter (OsiSolverInterface * model) const { int value = 0; switch (type_) { case CLP_PARAM_INT_SOLVERLOGLEVEL: value = model->messageHandler()->logLevel(); break; default: value = intValue_; break; } return value; } int CbcOrClpParam::setDoubleParameter (CbcModel &model, double value) { int returnCode; setDoubleParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets double parameter and returns printable string and error code const char * CbcOrClpParam::setDoubleParameterWithMessage ( CbcModel & model, double value , int & returnCode) { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { sprintf(printArray, "%g was provided for %s - valid range is %g to %g", value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); returnCode = 1; } else { double oldValue = doubleValue_; doubleValue_ = value; 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 CBC_PARAM_DBL_GAPRATIO: oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap); model.setDblParam(CbcModel::CbcAllowableFractionGap, value); break; case CBC_PARAM_DBL_CUTOFF: oldValue = model.getCutoff(); model.setCutoff(value); break; case CBC_PARAM_DBL_TIMELIMIT_BAB: oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds) ; { //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver()); //ClpSimplex * lpSolver = clpSolver->getModelPtr(); //lpSolver->setMaximumSeconds(value); 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: break; } sprintf(printArray, "%s was changed from %g to %g", name_.c_str(), oldValue, value); returnCode = 0; } return printArray; } double CbcOrClpParam::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); break; case CBC_PARAM_DBL_ALLOWABLEGAP: value = model.getDblParam(CbcModel::CbcAllowableGap); break; case CBC_PARAM_DBL_GAPRATIO: value = model.getDblParam(CbcModel::CbcAllowableFractionGap); break; case CBC_PARAM_DBL_CUTOFF: value = model.getCutoff(); break; case CBC_PARAM_DBL_TIMELIMIT_BAB: value = model.getDblParam(CbcModel::CbcMaximumSeconds) ; break ; case CLP_PARAM_DBL_DUALTOLERANCE: case CLP_PARAM_DBL_PRIMALTOLERANCE: value = doubleParameter(model.solver()); break; default: value = doubleValue_; break; } return value; } int CbcOrClpParam::setIntParameter (CbcModel &model, int value) { int returnCode; setIntParameterWithMessage(model, value, returnCode); if (doPrinting && strlen(printArray)) std::cout << printArray << std::endl; return returnCode; } // Sets int parameter and returns printable string and error code const char * CbcOrClpParam::setIntParameterWithMessage ( CbcModel & model, int value , int & returnCode) { if (value < lowerIntValue_ || value > upperIntValue_) { sprintf(printArray, "%d was provided for %s - valid range is %d to %d", value, name_.c_str(), lowerIntValue_, upperIntValue_); returnCode = 1; } else { int oldValue = intValue_; intValue_ = value; switch (type_) { case CLP_PARAM_INT_LOGLEVEL: oldValue = model.messageHandler()->logLevel(); model.messageHandler()->setLogLevel(CoinAbs(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_MAXSOLS: oldValue = model.getIntParam(CbcModel::CbcMaxNumSol); model.setIntParam(CbcModel::CbcMaxNumSol, value); break; case CBC_PARAM_INT_MAXSAVEDSOLS: oldValue = model.maximumSavedSolutions(); model.setMaximumSavedSolutions(value); break; case CBC_PARAM_INT_STRONGBRANCHING: oldValue = model.numberStrong(); model.setNumberStrong(value); break; case CBC_PARAM_INT_NUMBERBEFORE: oldValue = model.numberBeforeTrust(); model.setNumberBeforeTrust(value); break; case CBC_PARAM_INT_NUMBERANALYZE: oldValue = model.numberAnalyzeIterations(); model.setNumberAnalyzeIterations(value); break; case CBC_PARAM_INT_CUTPASSINTREE: oldValue = model.getMaximumCutPasses(); model.setMaximumCutPasses(value); break; case CBC_PARAM_INT_CUTPASS: oldValue = model.getMaximumCutPassesAtRoot(); model.setMaximumCutPassesAtRoot(value); break; #ifdef COIN_HAS_CBC #ifdef CBC_THREAD case CBC_PARAM_INT_THREADS: oldValue = model.getNumberThreads(); model.setNumberThreads(value); break; #endif case CBC_PARAM_INT_RANDOMSEED: oldValue = model.getRandomSeed(); model.setRandomSeed(value); break; #endif default: break; } sprintf(printArray, "%s was changed from %d to %d", name_.c_str(), oldValue, value); returnCode = 0; } return printArray; } int CbcOrClpParam::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_MAXSOLS: value = model.getIntParam(CbcModel::CbcMaxNumSol); break; case CBC_PARAM_INT_MAXSAVEDSOLS: value = model.maximumSavedSolutions(); break; case CBC_PARAM_INT_STRONGBRANCHING: value = model.numberStrong(); break; case CBC_PARAM_INT_NUMBERBEFORE: value = model.numberBeforeTrust(); break; case CBC_PARAM_INT_NUMBERANALYZE: value = model.numberAnalyzeIterations(); break; case CBC_PARAM_INT_CUTPASSINTREE: value = model.getMaximumCutPasses(); break; case CBC_PARAM_INT_CUTPASS: value = model.getMaximumCutPassesAtRoot(); break; #ifdef COIN_HAS_CBC #ifdef CBC_THREAD case CBC_PARAM_INT_THREADS: value = model.getNumberThreads(); #endif case CBC_PARAM_INT_RANDOMSEED: value = model.getRandomSeed(); break; #endif default: value = intValue_; break; } return value; } #endif // Sets current parameter option using string void CbcOrClpParam::setCurrentOption ( const std::string value ) { int action = parameterOption(value); if (action >= 0) currentKeyWord_ = action; } // Sets current parameter option void CbcOrClpParam::setCurrentOption ( int value , bool printIt) { if (printIt && value != currentKeyWord_) std::cout << "Option for " << name_ << " changed from " << definedKeyWords_[currentKeyWord_] << " to " << definedKeyWords_[value] << std::endl; currentKeyWord_ = value; } // Sets current parameter option and returns printable string const char * CbcOrClpParam::setCurrentOptionWithMessage ( int value ) { if (value != currentKeyWord_) { sprintf(printArray, "Option for %s changed from %s to %s", name_.c_str(), definedKeyWords_[currentKeyWord_].c_str(), definedKeyWords_[value].c_str()); currentKeyWord_ = value; } else { printArray[0] = '\0'; } return printArray; } void CbcOrClpParam::setIntValue ( int value ) { if (value < lowerIntValue_ || value > upperIntValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; } else { intValue_ = value; } } void CbcOrClpParam::setDoubleValue ( double value ) { if (value < lowerDoubleValue_ || value > upperDoubleValue_) { std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; } else { doubleValue_ = value; } } void CbcOrClpParam::setStringValue ( std::string value ) { stringValue_ = value; } static char line[1000]; static char * where = NULL; extern int CbcOrClpRead_mode; int CbcOrClpEnvironmentIndex = -1; static size_t fillEnv() { #if defined(_MSC_VER) || defined(__MSVCRT__) return 0; #else // Don't think it will work on Windows char * environ = getenv("CBC_CLP_ENVIRONMENT"); size_t length = 0; if (environ) { length = strlen(environ); if (CbcOrClpEnvironmentIndex < static_cast(length)) { // find next non blank char * whereEnv = environ + CbcOrClpEnvironmentIndex; // munch white space while (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ') whereEnv++; // copy char * put = line; while ( *whereEnv != '\0' ) { if ( *whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ' ) { break; } *put = *whereEnv; put++; assert (put - line < 1000); whereEnv++; } CbcOrClpEnvironmentIndex = static_cast(whereEnv - environ); *put = '\0'; length = strlen(line); } else { length = 0; } } if (!length) CbcOrClpEnvironmentIndex = -1; return length; #endif } extern FILE * CbcOrClpReadCommand; // Simple read stuff std::string CoinReadNextField() { std::string field; if (!where) { // need new line #ifdef COIN_HAS_READLINE if (CbcOrClpReadCommand == stdin) { // Get a line from the user. where = readline (coin_prompt); // If the line has any text in it, save it on the history. if (where) { if ( *where) add_history (where); strcpy(line, where); free(where); } } else { where = fgets(line, 1000, CbcOrClpReadCommand); } #else if (CbcOrClpReadCommand == stdin) { fputs(coin_prompt,stdout); fflush(stdout); } where = fgets(line, 1000, CbcOrClpReadCommand); #endif if (!where) return field; // EOF where = line; // clean image char * lastNonBlank = line - 1; while ( *where != '\0' ) { if ( *where != '\t' && *where < ' ' ) { break; } else if ( *where != '\t' && *where != ' ') { lastNonBlank = where; } where++; } where = line; *(lastNonBlank + 1) = '\0'; } // munch white space while (*where == ' ' || *where == '\t') where++; char * saveWhere = where; while (*where != ' ' && *where != '\t' && *where != '\0') where++; if (where != saveWhere) { char save = *where; *where = '\0'; //convert to string field = saveWhere; *where = save; } else { where = NULL; field = "EOL"; } return field; } std::string CoinReadGetCommand(int argc, const char *argv[]) { std::string field = "EOL"; // say no = afterEquals = ""; while (field == "EOL") { if (CbcOrClpRead_mode > 0) { if ((CbcOrClpRead_mode < argc && argv[CbcOrClpRead_mode]) || CbcOrClpEnvironmentIndex >= 0) { if (CbcOrClpEnvironmentIndex < 0) { field = argv[CbcOrClpRead_mode++]; } else { if (fillEnv()) { field = line; } else { // not there continue; } } if (field == "-") { std::cout << "Switching to line mode" << std::endl; CbcOrClpRead_mode = -1; field = CoinReadNextField(); } else if (field[0] != '-') { if (CbcOrClpRead_mode != 2) { // now allow std::cout<<"skipping non-command "< 0) { if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { if (CbcOrClpEnvironmentIndex < 0) { if (argv[CbcOrClpRead_mode][0] != '-') { field = argv[CbcOrClpRead_mode++]; } else if (!strcmp(argv[CbcOrClpRead_mode], "--")) { field = argv[CbcOrClpRead_mode++]; // -- means import from stdin field = "-"; } } else { fillEnv(); field = line; } } } else { field = CoinReadNextField(); } } else { field = afterEquals; afterEquals = ""; } //std::cout< 0) { if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { if (CbcOrClpEnvironmentIndex < 0) { // may be negative value so do not check for - field = argv[CbcOrClpRead_mode++]; } else { fillEnv(); field = line; } } } else { field = CoinReadNextField(); } } else { field = afterEquals; afterEquals = ""; } long int value = 0; //std::cout<(value); } double CoinReadGetDoubleField(int argc, const char *argv[], int * valid) { std::string field = "EOL"; if (afterEquals == "") { if (CbcOrClpRead_mode > 0) { if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { if (CbcOrClpEnvironmentIndex < 0) { // may be negative value so do not check for - field = argv[CbcOrClpRead_mode++]; } else { fillEnv(); field = line; } } } else { field = CoinReadNextField(); } } else { field = afterEquals; afterEquals = ""; } double value = 0.0; //std::cout<= this treated as artificials in feasibility pump", 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters-1].setLonghelp ( "0.0 off - otherwise variables with costs >= this are treated as artificials and fixed to lower bound in feasibility pump" ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("auto!Scale", "Whether to scale objective, rhs and bounds of problem if they look odd", "off", CLP_PARAM_STR_AUTOSCALE, 7, 0); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( "If you think you may get odd objective values or large equality rows etc then\ it may be worth setting this true. It is still experimental and you may prefer\ to use objective!Scale and rhs!Scale." ); parameters[numberParameters++] = CbcOrClpParam("barr!ier", "Solve using primal dual predictor corrector algorithm", CLP_PARAM_ACTION_BARRIER); parameters[numberParameters-1].setLonghelp ( "This command solves the current model using the primal dual predictor \ corrector algorithm. You may want to link in an alternative \ ordering and factorization. It will also solve models \ with quadratic objectives." ); parameters[numberParameters++] = CbcOrClpParam("basisI!n", "Import basis from bas file", CLP_PARAM_ACTION_BASISIN, 3); parameters[numberParameters-1].setLonghelp ( "This will read an MPS format basis 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 libz then it can read compressed\ files 'xxxxxxxx.gz' or xxxxxxxx.bz2." ); parameters[numberParameters++] = CbcOrClpParam("basisO!ut", "Export basis as bas file", CLP_PARAM_ACTION_BASISOUT); parameters[numberParameters-1].setLonghelp ( "This will write an MPS format basis 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.bas'." ); parameters[numberParameters++] = CbcOrClpParam("biasLU", "Whether factorization biased towards U", "UU", CLP_PARAM_STR_BIASLU, 2, 0); parameters[numberParameters-1].append("UX"); parameters[numberParameters-1].append("LX"); parameters[numberParameters-1].append("LL"); parameters[numberParameters-1].setCurrentOption("LX"); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("branch!AndCut", "Do Branch and Cut", CBC_PARAM_ACTION_BAB); parameters[numberParameters-1].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, forceon. 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. Forceon is same as on but forces code to use \ cut generator at every node. For probing forceonbut just does fixing probing in tree - not strengthening etc. \ 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. If cuts did a good job, then you may wish to \ have more rounds of cuts - see passC!uts and passT!ree." ); #endif parameters[numberParameters++] = CbcOrClpParam("bscale", "Whether to scale in barrier (and ordering speed)", "off", CLP_PARAM_STR_BARRIERSCALE, 7, 0); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("off1"); parameters[numberParameters-1].append("on1"); parameters[numberParameters-1].append("off2"); parameters[numberParameters-1].append("on2"); parameters[numberParameters++] = CbcOrClpParam("chol!esky", "Which cholesky algorithm", "native", CLP_PARAM_STR_CHOLESKY, 7); parameters[numberParameters-1].append("dense"); //#ifdef FOREIGN_BARRIER #ifdef COIN_HAS_WSMP parameters[numberParameters-1].append("fudge!Long"); parameters[numberParameters-1].append("wssmp"); #else parameters[numberParameters-1].append("fudge!Long_dummy"); parameters[numberParameters-1].append("wssmp_dummy"); #endif #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK) parameters[numberParameters-1].append("Uni!versityOfFlorida"); #else parameters[numberParameters-1].append("Uni!versityOfFlorida_dummy"); #endif #ifdef TAUCS_BARRIER parameters[numberParameters-1].append("Taucs"); #else parameters[numberParameters-1].append("Taucs_dummy"); #endif #ifdef COIN_HAS_MUMPS parameters[numberParameters-1].append("Mumps"); #else parameters[numberParameters-1].append("Mumps_dummy"); #endif parameters[numberParameters-1].setLonghelp ( "For a barrier code to be effective it needs a good Cholesky ordering and factorization. \ The native ordering and factorization is not state of the art, although acceptable. \ You may want to link in one from another source. See Makefile.locations for some \ possibilities." ); //#endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("clique!Cuts", "Whether to use Clique cuts", "off", CBC_PARAM_STR_CLIQUECUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].setLonghelp ( "This switches on clique cuts (either at root or in entire tree) \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("combine!Solutions", "Whether to use combine solution heuristic", "off", CBC_PARAM_STR_COMBINE); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].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 obviously only tries after two or more solutions. \ See Rounding for meaning of on,both,before" ); parameters[numberParameters++] = CbcOrClpParam("combine2!Solutions", "Whether to use crossover solution heuristic", "off", CBC_PARAM_STR_CROSSOVER2); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "This switches on a heuristic which does branch and cut on the problem given by \ fixing variables which have same value in two or more solutions. \ It obviously only tries after two or more solutions. \ See Rounding for meaning of on,both,before" ); parameters[numberParameters++] = CbcOrClpParam("constraint!fromCutoff", "Whether to use cutoff as constraint", "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( "This adds the objective as a constraint with best solution as RHS" ); parameters[numberParameters++] = CbcOrClpParam("cost!Strategy", "How to use costs as priorities", "off", CBC_PARAM_STR_COSTSTRATEGY); parameters[numberParameters-1].append("pri!orities"); parameters[numberParameters-1].append("column!Order?"); parameters[numberParameters-1].append("01f!irst?"); parameters[numberParameters-1].append("01l!ast?"); parameters[numberParameters-1].append("length!?"); parameters[numberParameters-1].append("singletons"); parameters[numberParameters-1].append("nonzero"); parameters[numberParameters-1].setLonghelp ( "This orders the variables in order of their absolute costs - with largest cost ones being branched on \ first. This primitive strategy can be surprsingly effective. The column order\ option is obviously not on costs but easy to code here." ); parameters[numberParameters++] = CbcOrClpParam("cplex!Use", "Whether to use Cplex!", "off", CBC_PARAM_STR_CPX); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( " If the user has Cplex, but wants to use some of Cbc's heuristics \ then you can! If this is on, then Cbc will get to the root node and then \ hand over to Cplex. If heuristics find a solution this can be significantly \ quicker. You will probably want to switch off Cbc's cuts as Cplex thinks \ they are genuine constraints. It is also probable that you want to switch \ off preprocessing, although for difficult problems it is worth trying \ both." ); #endif parameters[numberParameters++] = CbcOrClpParam("cpp!Generate", "Generates C++ code", -1, 50000, CLP_PARAM_INT_CPP, 1); parameters[numberParameters-1].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. \ This is now deprecated as you can call stand-alone solver - see \ Cbc/examples/driver4.cpp." ); #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("crash", "Whether to create basis for problem", "off", CLP_PARAM_STR_CRASH); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("so!low_halim"); parameters[numberParameters-1].append("lots"); #ifdef ABC_INHERIT parameters[numberParameters-1].append("dual"); parameters[numberParameters-1].append("dw"); parameters[numberParameters-1].append("idiot"); #endif parameters[numberParameters-1].setLonghelp ( "If crash is set on and there is an all slack basis then Clp will flip or put structural\ variables into basis with the aim of getting dual feasible. On the whole dual seems to be\ better without it and there are alternative types of 'crash' for primal e.g. 'idiot' or 'sprint'. \ I have also added a variant due to Solow and Halim which is as on but just flip."); parameters[numberParameters++] = CbcOrClpParam("cross!over", "Whether to get a basic solution after barrier", "on", CLP_PARAM_STR_CROSSOVER); parameters[numberParameters-1].append("off"); parameters[numberParameters-1].append("maybe"); parameters[numberParameters-1].append("presolve"); parameters[numberParameters-1].setLonghelp ( "Interior point algorithms do not obtain a basic solution (and \ the feasibility criterion is a bit suspect (JJF)). This option will crossover \ to a basic solution suitable for ranging or branch and cut. With the current state \ of quadratic it may be a good idea to switch off crossover for quadratic (and maybe \ presolve as well) - the option maybe does this." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("csv!Statistics", "Create one line of statistics", CLP_PARAM_ACTION_CSVSTATISTICS, 2, 1); parameters[numberParameters-1].setLonghelp ( "This appends statistics to 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. Adds header if file empty or does not exist." ); parameters[numberParameters++] = CbcOrClpParam("cutD!epth", "Depth in tree at which to do cuts", -1, 999999, CBC_PARAM_INT_CUTDEPTH); parameters[numberParameters-1].setLonghelp ( "Cut generators may be - off, on only at root, on if they look possible \ and on. 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 -> code decides)." ); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("cutL!ength", "Length of a cut", -1, COIN_INT_MAX, CBC_PARAM_INT_CUTLENGTH); parameters[numberParameters-1].setLonghelp ( "At present this only applies to Gomory cuts. -1 (default) leaves as is. \ Any value >0 says that all cuts <= this length can be generated both at \ root node and in tree. 0 says to use some dynamic lengths. If value >=10,000,000 \ then the length in tree is value%10000000 - so 10000100 means unlimited length \ at root and 100 in tree." ); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("cuto!ff", "All solutions must be better than this", -1.0e60, 1.0e60, CBC_PARAM_DBL_CUTOFF); parameters[numberParameters-1].setDoubleValue(1.0e50); parameters[numberParameters-1].setLonghelp ( "All solutions must be better than this value (in a minimization sense). \ This is also set by code whenever it obtains a solution and is set to value of \ objective for solution minus cutoff increment." ); parameters[numberParameters++] = CbcOrClpParam("cuts!OnOff", "Switches all cuts on or off", "off", CBC_PARAM_STR_CUTSSTRATEGY); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].setLonghelp ( "This can be used to switch on or off all cuts (apart from Reduce and Split). Then you can do \ individual ones off or on \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("debug!In", "read valid solution from file", CLP_PARAM_ACTION_DEBUG, 7, 1); parameters[numberParameters-1].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\n\ If set to create it will create a file called debug.file after search.\n\n\ The idea is that if you suspect a bad cut generator \ 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' The create case has same effect as saveSolution." ); #endif #ifdef COIN_HAS_CLP #if CLP_MULTIPLE_FACTORIZATIONS >0 parameters[numberParameters++] = CbcOrClpParam("dense!Threshold", "Whether to use dense factorization", -1, 10000, CBC_PARAM_INT_DENSE, 1); parameters[numberParameters-1].setLonghelp ( "If processed problem <= this use dense factorization" ); parameters[numberParameters-1].setIntValue(-1); #endif #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("depth!MiniBab", "Depth at which to try mini BAB", -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters-1].setLonghelp ( "Rather a complicated parameter but can be useful. -1 means off for large problems but on as if -12 for problems where rows+columns<500, -2 \ means use Cplex if it is linked in. Otherwise if negative then go into depth first complete search fast branch and bound when depth>= -value-2 (so -3 will use this at depth>=1). This mode is only switched on after 500 nodes. If you really want to switch it off for small problems then set this to -999. If >=0 the value doesn't matter very much. The code will do approximately 100 nodes of fast branch and bound every now and then at depth>=5. The actual logic is too twisted to describe here." ); parameters[numberParameters++] = CbcOrClpParam("dextra3", "Extra double parameter 3", -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters++] = CbcOrClpParam("dextra4", "Extra double parameter 4", -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters++] = CbcOrClpParam("dextra5", "Extra double parameter 5", -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters++] = CbcOrClpParam("Dins", "Whether to try Distance Induced Neighborhood Search", "off", CBC_PARAM_STR_DINS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].append("often"); parameters[numberParameters-1].setLonghelp ( "This switches on Distance induced neighborhood Search. \ See Rounding for meaning of on,both,before" ); #endif parameters[numberParameters++] = CbcOrClpParam("direction", "Minimize or Maximize", "min!imize", CLP_PARAM_STR_DIRECTION); parameters[numberParameters-1].append("max!imize"); parameters[numberParameters-1].append("zero"); parameters[numberParameters-1].setLonghelp ( "The default is minimize - use 'direction maximize' for maximization.\n\ You can also use the parameters 'maximize' or 'minimize'." ); parameters[numberParameters++] = CbcOrClpParam("directory", "Set Default directory for import etc.", CLP_PARAM_ACTION_DIRECTORY); parameters[numberParameters-1].setLonghelp ( "This sets the directory which import, export, saveModel, restoreModel etc will use.\ It is initialized to './'" ); parameters[numberParameters++] = CbcOrClpParam("dirSample", "Set directory where the COIN-OR sample problems are.", CLP_PARAM_ACTION_DIRSAMPLE, 7, 1); parameters[numberParameters-1].setLonghelp ( "This sets the directory where the COIN-OR sample problems reside. It is\ used only when -unitTest is passed to clp. clp will pick up the test problems\ from this directory.\ It is initialized to '../../Data/Sample'" ); parameters[numberParameters++] = CbcOrClpParam("dirNetlib", "Set directory where the netlib problems are.", CLP_PARAM_ACTION_DIRNETLIB, 7, 1); parameters[numberParameters-1].setLonghelp ( "This sets the directory where the netlib problems reside. One can get\ the netlib problems from COIN-OR or from the main netlib site. This\ parameter is used only when -netlib is passed to clp. clp will pick up the\ netlib problems from this directory. If clp is built without zlib support\ then the problems must be uncompressed.\ It is initialized to '../../Data/Netlib'" ); parameters[numberParameters++] = CbcOrClpParam("dirMiplib", "Set directory where the miplib 2003 problems are.", CBC_PARAM_ACTION_DIRMIPLIB, 7, 1); parameters[numberParameters-1].setLonghelp ( "This sets the directory where the miplib 2003 problems reside. One can\ get the miplib problems from COIN-OR or from the main miplib site. This\ parameter is used only when -miplib is passed to cbc. cbc will pick up the\ miplib problems from this directory. If cbc is built without zlib support\ then the problems must be uncompressed.\ It is initialized to '../../Data/miplib3'" ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("diveO!pt", "Diving options", -1, 200000, CBC_PARAM_INT_DIVEOPT, 1); parameters[numberParameters-1].setLonghelp ( "If >2 && <8 then modify diving options - \ \n\t3 only at root and if no solution, \ \n\t4 only at root and if this heuristic has not got solution, \ \n\t5 only at depth <4, \ \n\t6 decay, \ \n\t7 run up to 2 times if solution found 4 otherwise." ); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("DivingS!ome", "Whether to try Diving heuristics", "off", CBC_PARAM_STR_DIVINGS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "This switches on a random diving heuristic at various times. \ C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - PseudoCost, V - VectorLength. \ You may prefer to use individual on/off \ See Rounding for meaning of on,both,before" ); parameters[numberParameters++] = CbcOrClpParam("DivingC!oefficient", "Whether to try DiveCoefficient", "off", CBC_PARAM_STR_DIVINGC); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("DivingF!ractional", "Whether to try DiveFractional", "off", CBC_PARAM_STR_DIVINGF); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("DivingG!uided", "Whether to try DiveGuided", "off", CBC_PARAM_STR_DIVINGG); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("DivingL!ineSearch", "Whether to try DiveLineSearch", "off", CBC_PARAM_STR_DIVINGL); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("DivingP!seudoCost", "Whether to try DivePseudoCost", "off", CBC_PARAM_STR_DIVINGP); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("DivingV!ectorLength", "Whether to try DiveVectorLength", "off", CBC_PARAM_STR_DIVINGV); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters++] = CbcOrClpParam("doH!euristic", "Do heuristics before any preprocessing", CBC_PARAM_ACTION_DOHEURISTIC, 3); parameters[numberParameters-1].setLonghelp ( "Normally heuristics are done in branch and bound. It may be useful to do them outside. \ Only those heuristics with 'both' or 'before' set will run. \ Doing this may also set cutoff, which can help with preprocessing." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("dualB!ound", "Initially algorithm acts as if no \ gap between bounds exceeds this value", 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALBOUND); parameters[numberParameters-1].setLonghelp ( "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\ algorithm where you first get feasible then optimal. If a problem has both upper and\ lower bounds then it is trivial to get dual feasible by setting non basic variables\ to correct bound. If the gap between the upper and lower bounds of a variable is more\ than the value of dualBound Clp introduces fake bounds so that it can make the problem\ dual feasible. This has the same effect as a composite objective function in the\ primal algorithm. Too high a value may mean more iterations, while too low a bound means\ the code may go all the way and then have to increase the bounds. OSL had a heuristic to\ adjust bounds, maybe we need that here." ); parameters[numberParameters++] = CbcOrClpParam("dualize", "Solves dual reformulation", 0, 4, CLP_PARAM_INT_DUALIZE, 1); parameters[numberParameters-1].setLonghelp ( "Don't even think about it." ); parameters[numberParameters++] = CbcOrClpParam("dualP!ivot", "Dual pivot choice algorithm", "auto!matic", CLP_PARAM_STR_DUALPIVOT, 7, 1); parameters[numberParameters-1].append("dant!zig"); parameters[numberParameters-1].append("partial"); parameters[numberParameters-1].append("steep!est"); parameters[numberParameters-1].setLonghelp ( "Clp can use any pivot selection algorithm which the user codes as long as it\ implements the features in the abstract pivot base class. The Dantzig method is implemented\ to show a simple method but its use is deprecated. Steepest is the method of choice and there\ are two variants which keep all weights updated but only scan a subset each iteration.\ Partial switches this on while automatic decides at each iteration based on information\ about the factorization." ); parameters[numberParameters++] = CbcOrClpParam("dualS!implex", "Do dual simplex algorithm", CLP_PARAM_ACTION_DUALSIMPLEX); parameters[numberParameters-1].setLonghelp ( "This command solves the continuous relaxation of the current model using the dual steepest edge algorithm.\ The time and iterations may be affected by settings such as presolve, scaling, crash\ and also by dual pivot method, fake bound on variables and dual and primal tolerances." ); #endif parameters[numberParameters++] = CbcOrClpParam("dualT!olerance", "For an optimal solution \ no dual infeasibility may exceed this value", 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALTOLERANCE); parameters[numberParameters-1].setLonghelp ( "Normally the default tolerance is fine, but you may want to increase it a\ bit if a dual run seems to be having a hard time. One method which can be faster is \ to use a large tolerance e.g. 1.0e-4 and dual and then clean up problem using primal and the \ correct tolerance (remembering to switch off presolve for this final short clean up phase)." ); #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("either!Simplex", "Do dual or primal simplex algorithm", CLP_PARAM_ACTION_EITHERSIMPLEX); parameters[numberParameters-1].setLonghelp ( "This command solves the continuous relaxation of the current model using the dual or primal algorithm,\ based on a dubious analysis of model." ); #endif parameters[numberParameters++] = CbcOrClpParam("end", "Stops clp execution", CLP_PARAM_ACTION_EXIT); parameters[numberParameters-1].setLonghelp ( "This stops execution ; end, exit, quit and stop are synonyms" ); parameters[numberParameters++] = CbcOrClpParam("environ!ment", "Read commands from environment", CLP_PARAM_ACTION_ENVIRONMENT, 7, 0); parameters[numberParameters-1].setLonghelp ( "This starts reading from environment variable CBC_CLP_ENVIRONMENT." ); parameters[numberParameters++] = CbcOrClpParam("error!sAllowed", "Whether to allow import errors", "off", CLP_PARAM_STR_ERRORSALLOWED, 3); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].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[numberParameters++] = CbcOrClpParam("exit", "Stops clp execution", CLP_PARAM_ACTION_EXIT); parameters[numberParameters-1].setLonghelp ( "This stops the execution of Clp, end, exit, quit and stop are synonyms" ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("exper!iment", "Whether to use testing features", -1, 200, CBC_PARAM_INT_EXPERIMENT, 0); parameters[numberParameters-1].setLonghelp ( "Defines how adventurous you want to be in using new ideas. \ 0 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!" ); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters++] = CbcOrClpParam("expensive!Strong", "Whether to do even more strong branching", 0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0); parameters[numberParameters-1].setLonghelp ( "Strategy for extra strong branching \n\ \n\t0 - normal\n\ \n\twhen to do all fractional\n\ \n\t1 - root node\n\ \n\t2 - depth less than modifier\n\ \n\t4 - if objective == best possible\n\ \n\t6 - as 2+4\n\ \n\twhen to do all including satisfied\n\ \n\t10 - root node etc.\n\ \n\tIf >=100 then do when depth <= strategy/100 (otherwise 5)" ); parameters[numberParameters-1].setIntValue(0); #endif parameters[numberParameters++] = CbcOrClpParam("export", "Export model as mps file", CLP_PARAM_ACTION_EXPORT); parameters[numberParameters-1].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'. \ It can be useful to get rid of the original names and go over to using Rnnnnnnn and Cnnnnnnn. This can be done by setting 'keepnames' off before importing mps file." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("extra1", "Extra integer parameter 1", -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("extra2", "Extra integer parameter 2", -100, COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("extra3", "Extra integer parameter 3", -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("extra4", "Extra integer parameter 4", -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA4, 0); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters-1].setLonghelp ( "This switches on yet more special options!! \ The bottom digit is a strategy when to used shadow price stuff e.g. 3 \ means use until a solution is found. The next two digits say what sort \ of dual information to use. After that it goes back to powers of 2 so -\n\ \n\t1000 - switches on experimental hotstart\n\ \n\t2,4,6000 - switches on experimental methods of stopping cuts\n\ \n\t8000 - increase minimum drop gradually\n\ \n\t16000 - switches on alternate gomory criterion" ); parameters[numberParameters++] = CbcOrClpParam("extraV!ariables", "Allow creation of extra integer variables", -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters-1].setLonghelp ( "This switches on creation of extra integer variables \ to gather all variables with same cost." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("fact!orization", "Which factorization to use", "normal", CLP_PARAM_STR_FACTORIZATION); parameters[numberParameters-1].append("dense"); parameters[numberParameters-1].append("simple"); parameters[numberParameters-1].append("osl"); parameters[numberParameters-1].setLonghelp ( #ifndef ABC_INHERIT "The default is to use the normal CoinFactorization, but \ other choices are a dense one, osl's or one designed for small problems." #else "Normally the default is to use the normal CoinFactorization, but \ other choices are a dense one, osl's or one designed for small problems. \ However if at Aboca then the default is CoinAbcFactorization and other choices are \ a dense one, one designed for small problems or if enabled a long factorization." #endif ); parameters[numberParameters++] = CbcOrClpParam("fakeB!ound", "All bounds <= this value - DEBUG", 1.0, 1.0e15, CLP_PARAM_ACTION_FAKEBOUND, 0); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("feas!ibilityPump", "Whether to try Feasibility Pump", "off", CBC_PARAM_STR_FPUMP); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "This switches on feasibility pump heuristic at root. This is due to Fischetti, Lodi and Glover \ and uses a sequence of Lps to try and get an integer feasible solution. \ Some fine tuning is available by passFeasibilityPump and also pumpTune. \ See Rounding for meaning of on,both,before" ); parameters[numberParameters++] = CbcOrClpParam("fix!OnDj", "Try heuristic based on fixing variables with \ reduced costs greater than this", -1.0e20, 1.0e20, CBC_PARAM_DBL_DJFIX, 1); parameters[numberParameters-1].setLonghelp ( "If this is set integer variables with reduced costs greater than this will be fixed \ before branch and bound - use with extreme caution!" ); parameters[numberParameters++] = CbcOrClpParam("flow!CoverCuts", "Whether to use Flow Cover cuts", "off", CBC_PARAM_STR_FLOWCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].setLonghelp ( "This switches on flow cover cuts (either at root or in entire tree) \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("force!Solution", "Whether to use given solution as crash for BAB", -1, 20000000, CLP_PARAM_INT_USESOLUTION); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters-1].setLonghelp ( "-1 off. If 1 then tries to branch to solution given by AMPL or priorities file. \ If 0 then just tries to set as best solution \ If >1 then also does that many nodes on fixed problem." ); parameters[numberParameters++] = CbcOrClpParam("fraction!forBAB", "Fraction in feasibility pump", 1.0e-5, 1.1, CBC_PARAM_DBL_SMALLBAB, 1); parameters[numberParameters-1].setDoubleValue(0.5); parameters[numberParameters-1].setLonghelp ( "After a pass in feasibility pump, variables which have not moved \ about are fixed and if the preprocessed model is small enough a few nodes \ of branch and bound are done on reduced problem. Small problem has to be less than this fraction of original." ); #endif parameters[numberParameters++] = CbcOrClpParam("gamma!(Delta)", "Whether to regularize barrier", "off", CLP_PARAM_STR_GAMMA, 7, 1); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("gamma"); parameters[numberParameters-1].append("delta"); parameters[numberParameters-1].append("onstrong"); parameters[numberParameters-1].append("gammastrong"); parameters[numberParameters-1].append("deltastrong"); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("GMI!Cuts", "Whether to use alternative Gomory cuts", "off", CBC_PARAM_STR_GMICUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("endonly"); parameters[numberParameters-1].append("long"); parameters[numberParameters-1].append("longroot"); parameters[numberParameters-1].append("longifmove"); parameters[numberParameters-1].append("forceLongOn"); parameters[numberParameters-1].append("longendonly"); parameters[numberParameters-1].setLonghelp ( "This switches on an alternative Gomory cut generator (either at root or in entire tree) \ This version is by Giacomo Nannicini and may be more robust \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("GMI!Cuts", "Whether to use alternative Gomory cuts", "off", CBC_PARAM_STR_GMICUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("endonly"); parameters[numberParameters-1].append("long"); parameters[numberParameters-1].append("longroot"); parameters[numberParameters-1].append("longifmove"); parameters[numberParameters-1].append("forceLongOn"); parameters[numberParameters-1].append("longendonly"); parameters[numberParameters-1].setLonghelp ( "This switches on an alternative Gomory cut generator (either at root or in entire tree) \ This version is by Giacomo Nannicini and may be more robust \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("gomory!Cuts", "Whether to use Gomory cuts", "off", CBC_PARAM_STR_GOMORYCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].append("forceandglobal"); parameters[numberParameters-1].append("forceLongOn"); parameters[numberParameters-1].append("long"); parameters[numberParameters-1].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 (Long allows any length). \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("greedy!Heuristic", "Whether to use a greedy heuristic", "off", CBC_PARAM_STR_GREEDY); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); //parameters[numberParameters-1].append("root"); parameters[numberParameters-1].setLonghelp ( "Switches on a 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. \ See Rounding for meaning of on,both,before" ); #endif parameters[numberParameters++] = CbcOrClpParam("gsolu!tion", "Puts glpk solution to file", CLP_PARAM_ACTION_GMPL_SOLUTION); parameters[numberParameters-1].setLonghelp ( "Will write a glpk 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' (this defaults to ordinary solution if stdout). \ If problem created from gmpl model - will do any reports." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("heur!isticsOnOff", "Switches most heuristics on or off", "off", CBC_PARAM_STR_HEURISTICSTRATEGY); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( "This can be used to switch on or off all heuristics. Then you can do \ individual ones off or on. CbcTreeLocal is not included as it dramatically \ alters search." ); #endif parameters[numberParameters++] = CbcOrClpParam("help", "Print out version, non-standard options and some help", CLP_PARAM_ACTION_HELP, 3); parameters[numberParameters-1].setLonghelp ( "This prints out some help to get user started. If you have printed this then \ you should be past that stage:-)" ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("hOp!tions", "Heuristic options", -9999999, 9999999, CBC_PARAM_INT_HOPTIONS, 1); parameters[numberParameters-1].setLonghelp ( "1 says stop heuristic immediately allowable gap reached. \ Others are for feasibility pump - \ 2 says do exact number of passes given, \ 4 only applies if initial cutoff given and says relax after 50 passes, \ while 8 will adapt cutoff rhs after first solution if it looks as if code is stalling." ); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters++] = CbcOrClpParam("hot!StartMaxIts", "Maximum iterations on hot start", 0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("idiot!Crash", "Whether to try idiot crash", -1, 99999999, CLP_PARAM_INT_IDIOT); parameters[numberParameters-1].setLonghelp ( "This is a type of 'crash' which works well on some homogeneous problems.\ It works best on problems with unit elements and rhs but will do something to any model. It should only be\ used before primal. It can be set to -1 when the code decides for itself whether to use it,\ 0 to switch off or n > 0 to do n passes." ); #endif parameters[numberParameters++] = CbcOrClpParam("import", "Import model from mps file", CLP_PARAM_ACTION_IMPORT, 3); parameters[numberParameters-1].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' or 'xxxxxxxx.bz2'. \ If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("inc!rement", "A valid solution must be at least this \ much better than last integer solution", -1.0e20, 1.0e20, CBC_PARAM_DBL_INCREMENT); parameters[numberParameters-1].setLonghelp ( "Whenever a solution is found the bound on solutions is set to solution (in a minimization\ sense) plus this. If it is not set then the code will try and work one out e.g. if \ all objective coefficients are multiples of 0.01 and only integer variables have entries in \ objective then this can be set to 0.01. Be careful if you set this negative!" ); parameters[numberParameters++] = CbcOrClpParam("inf!easibilityWeight", "Each integer infeasibility is expected \ to cost this much", 0.0, 1.0e20, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1); parameters[numberParameters-1].setLonghelp ( "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is \ expected to cost this much." ); parameters[numberParameters++] = CbcOrClpParam("initialS!olve", "Solve to continuous", CLP_PARAM_ACTION_SOLVECONTINUOUS); parameters[numberParameters-1].setLonghelp ( "This just solves the problem to continuous - without adding any cuts" ); parameters[numberParameters++] = CbcOrClpParam("integerT!olerance", "For an optimal solution \ no integer variable may be this away from an integer value", 1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE); parameters[numberParameters-1].setLonghelp ( "Beware of setting this smaller than the primal tolerance." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("keepN!ames", "Whether to keep names from import", "on", CLP_PARAM_STR_KEEPNAMES); parameters[numberParameters-1].append("off"); parameters[numberParameters-1].setLonghelp ( "It saves space to get rid of names so if you need to you can set this to off. \ This needs to be set before the import of model - so -keepnames off -import xxxxx.mps." ); parameters[numberParameters++] = CbcOrClpParam("KKT", "Whether to use KKT factorization", "off", CLP_PARAM_STR_KKT, 7, 1); parameters[numberParameters-1].append("on"); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("knapsack!Cuts", "Whether to use Knapsack cuts", "off", CBC_PARAM_STR_KNAPSACKCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].append("forceandglobal"); parameters[numberParameters-1].setLonghelp ( "This switches on knapsack cuts (either at root or in entire tree) \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts", "off", CBC_PARAM_STR_LAGOMORYCUTS); parameters[numberParameters-1].append("endonlyroot"); parameters[numberParameters-1].append("endcleanroot"); parameters[numberParameters-1].append("endbothroot"); parameters[numberParameters-1].append("endonly"); parameters[numberParameters-1].append("endclean"); parameters[numberParameters-1].append("endboth"); parameters[numberParameters-1].append("onlyaswell"); parameters[numberParameters-1].append("cleanaswell"); parameters[numberParameters-1].append("bothaswell"); parameters[numberParameters-1].append("onlyinstead"); parameters[numberParameters-1].append("cleaninstead"); parameters[numberParameters-1].append("bothinstead"); parameters[numberParameters-1].setLonghelp ( "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \ by Matteo Fischetti & Domenico Salvagnin. This simplification \ just uses original constraints while modifying objective using other cuts. \ So you don't use messy constraints generated by Gomory etc. \ A variant is to allow non messy cuts e.g. clique cuts. \ So 'only' does this while clean also allows integral valued cuts. \ 'End' is recommended which waits until other cuts have finished and then \ does a few passes. \ The length options for gomory cuts are used." ); parameters[numberParameters++] = CbcOrClpParam("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts", "off", CBC_PARAM_STR_LATWOMIRCUTS); parameters[numberParameters-1].append("endonlyroot"); parameters[numberParameters-1].append("endcleanroot"); parameters[numberParameters-1].append("endbothroot"); parameters[numberParameters-1].append("endonly"); parameters[numberParameters-1].append("endclean"); parameters[numberParameters-1].append("endboth"); parameters[numberParameters-1].append("onlyaswell"); parameters[numberParameters-1].append("cleanaswell"); parameters[numberParameters-1].append("bothaswell"); parameters[numberParameters-1].append("onlyinstead"); parameters[numberParameters-1].append("cleaninstead"); parameters[numberParameters-1].append("bothinstead"); parameters[numberParameters-1].setLonghelp ( "This is a lagrangean relaxation for TwoMir cuts. See \ lagomoryCuts for description of options." ); parameters[numberParameters++] = CbcOrClpParam("lift!AndProjectCuts", "Whether to use Lift and Project cuts", "off", CBC_PARAM_STR_LANDPCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].setLonghelp ( "Lift and project cuts. \ May be slow \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("local!TreeSearch", "Whether to use local treesearch", "off", CBC_PARAM_STR_LOCALTREE); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].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 Coin solve it has limited functionality. It is not switched on when \ heuristics are switched on." ); #endif #ifndef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("log!Level", "Level of detail in Solver output", -1, 999999, CLP_PARAM_INT_SOLVERLOGLEVEL); #else parameters[numberParameters++] = CbcOrClpParam("log!Level", "Level of detail in Coin branch and Cut output", -63, 63, CLP_PARAM_INT_LOGLEVEL); parameters[numberParameters-1].setIntValue(1); #endif parameters[numberParameters-1].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[numberParameters++] = CbcOrClpParam("max!imize", "Set optimization direction to maximize", CLP_PARAM_ACTION_MAXIMIZE, 7); parameters[numberParameters-1].setLonghelp ( "The default is minimize - use 'maximize' for maximization.\n\ You can also use the parameters 'direction maximize'." ); #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("maxF!actor", "Maximum number of iterations between \ refactorizations", 1, 999999, CLP_PARAM_INT_MAXFACTOR); parameters[numberParameters-1].setLonghelp ( "If this is at its initial value of 200 then in this executable clp will guess at a\ value to use. Otherwise the user can set a value. The code may decide to re-factorize\ earlier for accuracy." ); parameters[numberParameters++] = CbcOrClpParam("maxIt!erations", "Maximum number of iterations before \ stopping", 0, 2147483647, CLP_PARAM_INT_MAXITERATION); parameters[numberParameters-1].setLonghelp ( "This can be used for testing purposes. The corresponding library call\n\ \tsetMaximumIterations(value)\n can be useful. If the code stops on\ seconds or by an interrupt this will be treated as stopping on maximum iterations. This is ignored in branchAndCut - use maxN!odes." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("maxN!odes", "Maximum number of nodes to do", -1, 2147483647, CBC_PARAM_INT_MAXNODES); parameters[numberParameters-1].setLonghelp ( "This is a repeatable way to limit search. Normally using time is easier \ but then the results may not be repeatable." ); parameters[numberParameters++] = CbcOrClpParam("maxSaved!Solutions", "Maximum number of solutions to save", 0, 2147483647, CBC_PARAM_INT_MAXSAVEDSOLS); parameters[numberParameters-1].setLonghelp ( "Number of solutions to save." ); parameters[numberParameters++] = CbcOrClpParam("maxSo!lutions", "Maximum number of solutions to get", 1, 2147483647, CBC_PARAM_INT_MAXSOLS); parameters[numberParameters-1].setLonghelp ( "You may want to stop after (say) two solutions or an hour. \ This is checked every node in tree, so it is possible to get more solutions from heuristics." ); #endif parameters[numberParameters++] = CbcOrClpParam("min!imize", "Set optimization direction to minimize", CLP_PARAM_ACTION_MINIMIZE, 7); parameters[numberParameters-1].setLonghelp ( "The default is minimize - use 'maximize' for maximization.\n\ This should only be necessary if you have previously set maximization \ You can also use the parameters 'direction minimize'." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0); parameters[numberParameters++] = CbcOrClpParam("more!MipOptions", "More dubious options for mip", -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0); parameters[numberParameters++] = CbcOrClpParam("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts", "off", CBC_PARAM_STR_MIXEDCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].setLonghelp ( "This switches on mixed integer rounding cuts (either at root or in entire tree) \ See branchAndCut for information on options." ); #endif parameters[numberParameters++] = CbcOrClpParam("mess!ages", "Controls if Clpnnnn is printed", "off", CLP_PARAM_STR_MESSAGES); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ("The default behavior is to put out messages such as:\n\ Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\n\ but 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. This only affects Clp not Cbc." ); parameters[numberParameters++] = CbcOrClpParam("miplib", "Do some of miplib test set", CBC_PARAM_ACTION_MIPLIB, 3, 1); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("mips!tart", "reads an initial feasible solution from file", CBC_PARAM_ACTION_MIPSTART); parameters[numberParameters-1].setLonghelp ("\ The MIPStart allows one to enter an initial integer feasible solution \ to CBC. Values of the main decision variables which are active (have \ non-zero values) in this solution are specified in a text file. The \ text file format used is the same of the solutions saved by CBC, but \ not all fields are required to be filled. First line may contain the \ solution status and will be ignored, remaining lines contain column \ indexes, names and values as in this example:\n\ \n\ Stopped on iterations - objective value 57597.00000000\n\ 0 x(1,1,2,2) 1 \n\ 1 x(3,1,3,2) 1 \n\ 5 v(5,1) 2 \n\ 33 x(8,1,5,2) 1 \n\ ...\n\ \n\ Column indexes are also ignored since pre-processing can change them. \ There is no need to include values for continuous or integer auxiliary \ variables, since they can be computed based on main decision variables. \ Starting CBC with an integer feasible solution can dramatically improve \ its performance: several MIP heuristics (e.g. RINS) rely on having at \ least one feasible solution available and can start immediately if the \ user provides one. Feasibility Pump (FP) is a heuristic which tries to \ overcome the problem of taking too long to find feasible solution (or \ not finding at all), but it not always succeeds. If you provide one \ starting solution you will probably save some time by disabling FP. \ \n\n\ Knowledge specific to your problem can be considered to write an \ external module to quickly produce an initial feasible solution - some \ alternatives are the implementation of simple greedy heuristics or the \ solution (by CBC for example) of a simpler model created just to find \ a feasible solution. \ \n\n\ Question and suggestions regarding MIPStart can be directed to\n\ haroldo.santos@gmail.com.\ "); #endif parameters[numberParameters++] = CbcOrClpParam("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp", 0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("moreT!une", "Yet more dubious ideas for feasibility pump", 0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0); parameters[numberParameters-1].setLonghelp ( "Yet more ideas for Feasibility Pump \n\ \t/100000 == 1 use box constraints and original obj in cleanup\n\ \t/1000 == 1 Pump will run twice if no solution found\n\ \t/1000 == 2 Pump will only run after root cuts if no solution found\n\ \t/1000 >10 as above but even if solution found\n\ \t/100 == 1,3.. exact 1.0 for objective values\n\ \t/100 == 2,3.. allow more iterations per pass\n\ \t n fix if value of variable same for last n iterations." ); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters++] = CbcOrClpParam("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions", 0, 100000000, CBC_PARAM_INT_MULTIPLEROOTS, 0); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters-1].setLonghelp ( "Do (in parallel if threads enabled) the root phase this number of times \ and collect all solutions and cuts generated. The actual format is aabbcc \ where aa is number of extra passes, if bb is non zero \ then it is number of threads to use (otherwise uses threads setting) and \ cc is number of times to do root phase. Yet another one from the Italian idea factory \ (This time - Andrea Lodi , Matteo Fischetti , Michele Monaci , Domenico Salvagnin , \ and Andrea Tramontani). \ The solvers do not interact with each other. However if extra passes are specified \ then cuts are collected and used in later passes - so there is interaction there." ); parameters[numberParameters++] = CbcOrClpParam("naive!Heuristics", "Whether to try some stupid heuristic", "off", CBC_PARAM_STR_NAIVE, 7, 1); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "Really silly stuff e.g. fix all integers with costs to zero!. \ Doh option does heuristic before preprocessing" ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("netlib", "Solve entire netlib test set", CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\ The user can set options before e.g. clp -presolve off -netlib" ); parameters[numberParameters++] = CbcOrClpParam("netlibB!arrier", "Solve entire netlib test set with barrier", CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp and then solves the netlib test set using barrier.\ The user can set options before e.g. clp -kkt on -netlib" ); parameters[numberParameters++] = CbcOrClpParam("netlibD!ual", "Solve entire netlib test set (dual)", CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp and then solves the netlib test set using dual.\ The user can set options before e.g. clp -presolve off -netlib" ); parameters[numberParameters++] = CbcOrClpParam("netlibP!rimal", "Solve entire netlib test set (primal)", CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp and then solves the netlib test set using primal.\ The user can set options before e.g. clp -presolve off -netlibp" ); parameters[numberParameters++] = CbcOrClpParam("netlibT!une", "Solve entire netlib test set with 'best' algorithm", CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp and then solves the netlib test set using whatever \ works best. I know this is cheating but it also stresses the code better by doing a \ mixture of stuff. The best algorithm was chosen on a Linux ThinkPad using native cholesky \ with University of Florida ordering." ); parameters[numberParameters++] = CbcOrClpParam("network", "Tries to make network matrix", CLP_PARAM_ACTION_NETWORK, 7, 0); parameters[numberParameters-1].setLonghelp ( "Clp will go faster if the matrix can be converted to a network. The matrix\ operations may be a bit faster with more efficient storage, but the main advantage\ comes from using a network factorization. It will probably not be as fast as a \ specialized network code." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("nextB!estSolution", "Prints next best saved solution to file", CLP_PARAM_ACTION_NEXTBESTSOLUTION); parameters[numberParameters-1].setLonghelp ( "To write best solution, just use solution. This prints next best (if exists) \ and then deletes it. \ 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[numberParameters++] = CbcOrClpParam("node!Strategy", "What strategy to use to select nodes", "hybrid", CBC_PARAM_STR_NODESTRATEGY); parameters[numberParameters-1].append("fewest"); parameters[numberParameters-1].append("depth"); parameters[numberParameters-1].append("upfewest"); parameters[numberParameters-1].append("downfewest"); parameters[numberParameters-1].append("updepth"); parameters[numberParameters-1].append("downdepth"); parameters[numberParameters-1].setLonghelp ( "Normally before a solution the code will choose node with fewest infeasibilities. \ You can choose depth as the criterion. You can also say if up or down branch must \ be done first (the up down choice will carry on after solution). \ Default has now been changed to hybrid which is breadth first on small depth nodes then fewest." ); parameters[numberParameters++] = CbcOrClpParam("numberA!nalyze", "Number of analysis iterations", -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0); parameters[numberParameters-1].setLonghelp ( "This says how many iterations to spend at root node analyzing problem. \ This is a first try and will hopefully become more sophisticated." ); #endif parameters[numberParameters++] = CbcOrClpParam("objective!Scale", "Scale factor to apply to objective", -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE, 1); parameters[numberParameters-1].setLonghelp ( "If the objective function has some very large values, you may wish to scale them\ internally by this amount. It can also be set by autoscale. It is applied after scaling. You are unlikely to need this." ); parameters[numberParameters-1].setDoubleValue(1.0); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("outDup!licates", "takes duplicate rows etc out of integer model", CLP_PARAM_ACTION_OUTDUPROWS, 7, 0); #endif parameters[numberParameters++] = CbcOrClpParam("output!Format", "Which output format to use", 1, 6, CLP_PARAM_INT_OUTPUTFORMAT); parameters[numberParameters-1].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 gives one value per line, even two. Values 1,2 give normal format, 3,4\ gives greater precision, while 5,6 give IEEE values. When used for exporting a basis 1 does not save \ values, 2 saves values, 3 with greater accuracy and 4 in IEEE." ); #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("para!metrics", "Import data from file and do parametrics", CLP_PARAM_ACTION_PARAMETRICS, 3); parameters[numberParameters-1].setLonghelp ( "This will read a file with parametric data from the given file name \ and then do parametrics. 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 modified csv format - a line ROWS will be followed by rows data \ while a line COLUMNS will be followed by column data. The last line \ should be ENDATA. The ROWS line must exist and is in the format \ ROWS, inital theta, final theta, interval theta, n where n is 0 to get \ CLPI0062 message at interval or at each change of theta \ and 1 to get CLPI0063 message at each iteration. If interval theta is 0.0 \ or >= final theta then no interval reporting. n may be missed out when it is \ taken as 0. If there is Row data then \ there is a headings line with allowed headings - name, number, \ lower(rhs change), upper(rhs change), rhs(change). Either the lower and upper \ fields should be given or the rhs field. \ The optional COLUMNS line is followed by a headings line with allowed \ headings - name, number, objective(change), lower(change), upper(change). \ Exactly one of name and number must be given for either section and \ missing ones have value 0.0." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("passC!uts", "Number of cut passes at root node", -9999999, 9999999, CBC_PARAM_INT_CUTPASS); parameters[numberParameters-1].setLonghelp ( "The default is 100 passes if less than 500 columns, 100 passes (but \ stop if drop small if less than 5000 columns, 20 otherwise" ); parameters[numberParameters++] = CbcOrClpParam("passF!easibilityPump", "How many passes in feasibility pump", 0, 10000, CBC_PARAM_INT_FPUMPITS); parameters[numberParameters-1].setLonghelp ( "This fine tunes Feasibility Pump by doing more or fewer passes." ); parameters[numberParameters-1].setIntValue(20); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("passP!resolve", "How many passes in presolve", -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1); parameters[numberParameters-1].setLonghelp ( "Normally Presolve does 5 passes but you may want to do less to make it\ more lightweight or do more if improvements are still being made. As Presolve will return\ if nothing is being taken out, you should not normally need to use this fine tuning." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("passT!reeCuts", "Number of cut passes in tree", -9999999, 9999999, CBC_PARAM_INT_CUTPASSINTREE); parameters[numberParameters-1].setLonghelp ( "The default is one pass" ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("pertV!alue", "Method of perturbation", -5000, 102, CLP_PARAM_INT_PERTVALUE, 1); parameters[numberParameters++] = CbcOrClpParam("perturb!ation", "Whether to perturb problem", "on", CLP_PARAM_STR_PERTURBATION); parameters[numberParameters-1].append("off"); parameters[numberParameters-1].setLonghelp ( "Perturbation helps to stop cycling, but Clp uses other measures for this.\ However large problems and especially ones with unit elements and unit rhs or costs\ benefit from perturbation. Normally Clp tries to be intelligent, but you can switch this off.\ The Clp library has this off by default. This program has it on by default." ); parameters[numberParameters++] = CbcOrClpParam("PFI", "Whether to use Product Form of Inverse in simplex", "off", CLP_PARAM_STR_PFI, 7, 0); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( "By default clp uses Forrest-Tomlin L-U update. If you are masochistic you can switch it off." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic", "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "stuff needed. \ Doh option does heuristic before preprocessing" ); parameters[numberParameters++] = CbcOrClpParam("pivotAndF!ix", "Whether to try Pivot and Fix heuristic", "off", CBC_PARAM_STR_PIVOTANDFIX); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "stuff needed. \ Doh option does heuristic before preprocessing" ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("plus!Minus", "Tries to make +- 1 matrix", CLP_PARAM_ACTION_PLUSMINUS, 7, 0); parameters[numberParameters-1].setLonghelp ( "Clp will go slightly faster if the matrix can be converted so that the elements are\ not stored and are known to be unit. The main advantage is memory use. Clp may automatically\ see if it can convert the problem so you should not need to use this." ); parameters[numberParameters++] = CbcOrClpParam("pO!ptions", "Dubious print options", 0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1); parameters[numberParameters-1].setIntValue(0); parameters[numberParameters-1].setLonghelp ( "If this is > 0 then presolve will give more information and branch and cut will give statistics" ); parameters[numberParameters++] = CbcOrClpParam("preO!pt", "Presolve options", 0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0); #endif parameters[numberParameters++] = CbcOrClpParam("presolve", "Whether to presolve problem", "on", CLP_PARAM_STR_PRESOLVE); parameters[numberParameters-1].append("off"); parameters[numberParameters-1].append("more"); parameters[numberParameters-1].append("file"); parameters[numberParameters-1].setLonghelp ( "Presolve analyzes the model to find such things as redundant equations, equations\ which fix some variables, equations which can be transformed into bounds etc etc. For the\ initial solve of any problem this is worth doing unless you know that it will have no effect. \ on will normally do 5 passes while using 'more' will do 10. If the problem is very large you may need \ to write the original to file using 'file'." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("preprocess", "Whether to use integer preprocessing", "off", CBC_PARAM_STR_PREPROCESS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("save"); parameters[numberParameters-1].append("equal"); parameters[numberParameters-1].append("sos"); parameters[numberParameters-1].append("trysos"); parameters[numberParameters-1].append("equalall"); parameters[numberParameters-1].append("strategy"); parameters[numberParameters-1].append("aggregate"); parameters[numberParameters-1].append("forcesos"); parameters[numberParameters-1].setLonghelp ( "This tries to reduce size of 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." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("preT!olerance", "Tolerance to use in presolve", 1.0e-20, 1.0e12, CLP_PARAM_DBL_PRESOLVETOLERANCE); parameters[numberParameters-1].setLonghelp ( "The default is 1.0e-8 - you may wish to try 1.0e-7 if presolve says the problem is \ infeasible and you have awkward numbers and you are sure the problem is really feasible." ); parameters[numberParameters++] = CbcOrClpParam("primalP!ivot", "Primal pivot choice algorithm", "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1); parameters[numberParameters-1].append("exa!ct"); parameters[numberParameters-1].append("dant!zig"); parameters[numberParameters-1].append("part!ial"); parameters[numberParameters-1].append("steep!est"); parameters[numberParameters-1].append("change"); parameters[numberParameters-1].append("sprint"); parameters[numberParameters-1].setLonghelp ( "Clp can use any pivot selection algorithm which the user codes as long as it\ implements the features in the abstract pivot base class. The Dantzig method is implemented\ to show a simple method but its use is deprecated. Exact devex is the method of choice and there\ are two variants which keep all weights updated but only scan a subset each iteration.\ Partial switches this on while change initially does dantzig until the factorization\ becomes denser. This is still a work in progress." ); parameters[numberParameters++] = CbcOrClpParam("primalS!implex", "Do primal simplex algorithm", CLP_PARAM_ACTION_PRIMALSIMPLEX); parameters[numberParameters-1].setLonghelp ( "This command solves the continuous relaxation of the current model using the primal algorithm.\ The default is to use exact devex.\ The time and iterations may be affected by settings such as presolve, scaling, crash\ and also by column selection method, infeasibility weight and dual and primal tolerances." ); #endif parameters[numberParameters++] = CbcOrClpParam("primalT!olerance", "For an optimal solution \ no primal infeasibility may exceed this value", 1.0e-20, 1.0e12, CLP_PARAM_DBL_PRIMALTOLERANCE); parameters[numberParameters-1].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" ); #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("primalW!eight", "Initially algorithm acts as if it \ costs this much to be infeasible", 1.0e-20, 1.0e20, CLP_PARAM_DBL_PRIMALWEIGHT); parameters[numberParameters-1].setLonghelp ( "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\ algorithm where you first get feasible then optimal. So Clp is minimizing this weight times\ the sum of primal infeasibilities plus the true objective function (in minimization sense).\ Too high a value may mean more iterations, while too low a bound means\ the code may go all the way and then have to increase the weight in order to get feasible.\ OSL had a heuristic to\ adjust bounds, maybe we need that here." ); #endif parameters[numberParameters++] = CbcOrClpParam("printi!ngOptions", "Print options", "normal", CLP_PARAM_STR_INTPRINT, 3); parameters[numberParameters-1].append("integer"); parameters[numberParameters-1].append("special"); parameters[numberParameters-1].append("rows"); parameters[numberParameters-1].append("all"); parameters[numberParameters-1].append("csv"); parameters[numberParameters-1].append("bound!ranging"); parameters[numberParameters-1].append("rhs!ranging"); parameters[numberParameters-1].append("objective!ranging"); parameters[numberParameters-1].append("stats"); parameters[numberParameters-1].append("boundsint"); parameters[numberParameters-1].append("boundsall"); parameters[numberParameters-1].setLonghelp ( "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\ integer - nonzero integer column variables\n\ special - in format suitable for OsiRowCutDebugger\n\ rows - nonzero column variables and row activities\n\ all - all column variables and row activities.\n\ \nFor non-integer problems 'integer' and 'special' act like 'normal'. \ Also see printMask for controlling output." ); parameters[numberParameters++] = CbcOrClpParam("printM!ask", "Control printing of solution on a mask", CLP_PARAM_ACTION_PRINTMASK, 3); parameters[numberParameters-1].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 '' i.e. unset so all variables are printed. \ This is only active if model has names." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("prio!rityIn", "Import priorities etc from file", CBC_PARAM_ACTION_PRIORITYIN, 3); parameters[numberParameters-1].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[numberParameters++] = CbcOrClpParam("probing!Cuts", "Whether to use Probing cuts", "off", CBC_PARAM_STR_PROBINGCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].append("forceonglobal"); parameters[numberParameters-1].append("forceOnBut"); parameters[numberParameters-1].append("forceOnStrong"); parameters[numberParameters-1].append("forceOnButStrong"); parameters[numberParameters-1].append("strongRoot"); parameters[numberParameters-1].setLonghelp ( "This switches on probing cuts (either at root or in entire tree) \ See branchAndCut for information on options. \ but strong options do more probing" ); parameters[numberParameters++] = CbcOrClpParam("proximity!Search", "Whether to do proximity search heuristic", "off", CBC_PARAM_STR_PROXIMITY); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].append("10"); parameters[numberParameters-1].append("100"); parameters[numberParameters-1].append("300"); parameters[numberParameters-1].setLonghelp ( "This switches on a heuristic which looks for a solution close \ to incumbent solution (Fischetti and Monaci). \ See Rounding for meaning of on,both,before. \ The ones at end have different maxNode settings (and are 'on'(on==30))." ); parameters[numberParameters++] = CbcOrClpParam("pumpC!utoff", "Fake cutoff for use in feasibility pump", -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters-1].setLonghelp ( "0.0 off - otherwise add a constraint forcing objective below this value\ in feasibility pump" ); parameters[numberParameters++] = CbcOrClpParam("pumpI!ncrement", "Fake increment for use in feasibility pump", -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters-1].setLonghelp ( "0.0 off - otherwise use as absolute increment to cutoff \ when solution found in feasibility pump" ); parameters[numberParameters++] = CbcOrClpParam("pumpT!une", "Dubious ideas for feasibility pump", 0, 100000000, CBC_PARAM_INT_FPUMPTUNE); parameters[numberParameters-1].setLonghelp ( "This fine tunes Feasibility Pump \n\ \t>=10000000 use as objective weight switch\n\ \t>=1000000 use as accumulate switch\n\ \t>=1000 use index+1 as number of large loops\n\ \t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\ \t%100 == 10,20 affects how each solve is done\n\ \t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \ If accumulate is on then after a major pass, variables which have not moved \ are fixed and a small branch and bound is tried." ); parameters[numberParameters-1].setIntValue(0); #endif parameters[numberParameters++] = CbcOrClpParam("quit", "Stops clp execution", CLP_PARAM_ACTION_EXIT); parameters[numberParameters-1].setLonghelp ( "This stops the execution of Clp, end, exit, quit and stop are synonyms" ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("randomC!bcSeed", "Random seed for Cbc", -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED); parameters[numberParameters-1].setLonghelp ( "This sets a random seed for Cbc \ - 0 says use time of day, -1 is as now." ); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("randomi!zedRounding", "Whether to try randomized rounding heuristic", "off", CBC_PARAM_STR_RANDROUND); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "stuff needed. \ Doh option does heuristic before preprocessing" ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("randomS!eed", "Random seed for Clp", 0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED); parameters[numberParameters-1].setLonghelp ( "This sets a random seed for Clp \ - 0 says use time of day." ); parameters[numberParameters-1].setIntValue(1234567); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("ratio!Gap", "Stop when gap between best possible and \ best less than this fraction of larger of two", 0.0, 1.0e20, CBC_PARAM_DBL_GAPRATIO); parameters[numberParameters-1].setDoubleValue(0.0); parameters[numberParameters-1].setLonghelp ( "If the gap between best solution and 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[numberParameters++] = CbcOrClpParam("readS!tored", "Import stored cuts from file", CLP_PARAM_ACTION_STOREDFILE, 3, 0); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("reallyO!bjectiveScale", "Scale factor to apply to objective in place", -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE2, 0); parameters[numberParameters-1].setLonghelp ( "You can set this to -1.0 to test maximization or other to stress code" ); parameters[numberParameters-1].setDoubleValue(1.0); parameters[numberParameters++] = CbcOrClpParam("reallyS!cale", "Scales model in place", CLP_PARAM_ACTION_REALLY_SCALE, 7, 0); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts", "off", CBC_PARAM_STR_REDSPLITCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].setLonghelp ( "This switches on reduce and split cuts (either at root or in entire tree). \ May be slow \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2", "off", CBC_PARAM_STR_REDSPLIT2CUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("longOn"); parameters[numberParameters-1].append("longRoot"); parameters[numberParameters-1].setLonghelp ( "This switches on reduce and split cuts (either at root or in entire tree) \ This version is by Giacomo Nannicini based on Francois Margot's version \ Standard setting only uses rows in tableau <=256, long uses all \ May be slow \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2", "off", CBC_PARAM_STR_REDSPLIT2CUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("longOn"); parameters[numberParameters-1].append("longRoot"); parameters[numberParameters-1].setLonghelp ( "This switches on reduce and split cuts (either at root or in entire tree) \ This version is by Giacomo Nannicini based on Francois Margot's version \ Standard setting only uses rows in tableau <=256, long uses all \ See branchAndCut for information on options." ); parameters[numberParameters++] = CbcOrClpParam("residual!CapacityCuts", "Whether to use Residual Capacity cuts", "off", CBC_PARAM_STR_RESIDCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].setLonghelp ( "Residual capacity cuts. \ See branchAndCut for information on options." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("restore!Model", "Restore model from binary file", CLP_PARAM_ACTION_RESTORE, 7, 1); parameters[numberParameters-1].setLonghelp ( "This reads data save by saveModel from the given file. 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.prob'." ); parameters[numberParameters++] = CbcOrClpParam("reverse", "Reverses sign of objective", CLP_PARAM_ACTION_REVERSE, 7, 0); parameters[numberParameters-1].setLonghelp ( "Useful for testing if maximization works correctly" ); parameters[numberParameters++] = CbcOrClpParam("rhs!Scale", "Scale factor to apply to rhs and bounds", -1.0e20, 1.0e20, CLP_PARAM_DBL_RHSSCALE, 0); parameters[numberParameters-1].setLonghelp ( "If the rhs or bounds have some very large meaningful values, you may wish to scale them\ internally by this amount. It can also be set by autoscale. This should not be needed." ); parameters[numberParameters-1].setDoubleValue(1.0); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("Rens", "Whether to try Relaxation Enforced Neighborhood Search", "off", CBC_PARAM_STR_RENS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].append("200"); parameters[numberParameters-1].append("1000"); parameters[numberParameters-1].append("10000"); parameters[numberParameters-1].append("dj"); parameters[numberParameters-1].append("djbefore"); parameters[numberParameters-1].setLonghelp ( "This switches on Relaxation enforced neighborhood Search. \ on just does 50 nodes \ 200 or 1000 does that many nodes. \ Doh option does heuristic before preprocessing" ); parameters[numberParameters++] = CbcOrClpParam("Rins", "Whether to try Relaxed Induced Neighborhood Search", "off", CBC_PARAM_STR_RINS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].append("often"); parameters[numberParameters-1].setLonghelp ( "This switches on Relaxed induced neighborhood Search. \ Doh option does heuristic before preprocessing" ); parameters[numberParameters++] = CbcOrClpParam("round!ingHeuristic", "Whether to use Rounding heuristic", "off", CBC_PARAM_STR_ROUNDING); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].setLonghelp ( "This switches on a simple (but effective) rounding heuristic at each node of tree. \ On means do in solve i.e. after preprocessing, \ Before means do if doHeuristics used, off otherwise, \ and both means do if doHeuristics and in solve." ); #endif parameters[numberParameters++] = CbcOrClpParam("saveM!odel", "Save model to binary file", CLP_PARAM_ACTION_SAVE, 7, 1); parameters[numberParameters-1].setLonghelp ( "This will save the problem to the given file name for future use\ by restoreModel. 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.prob'." ); parameters[numberParameters++] = CbcOrClpParam("saveS!olution", "saves solution to file", CLP_PARAM_ACTION_SAVESOL); parameters[numberParameters-1].setLonghelp ( "This will write a binary 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 'solution.file'. To read the file use fread(int) twice to pick up number of rows \ and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \ activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \ If name contains '_fix_read_' then does not write but reads and will fix all variables" ); parameters[numberParameters++] = CbcOrClpParam("scal!ing", "Whether to scale problem", "off", CLP_PARAM_STR_SCALING); parameters[numberParameters-1].append("equi!librium"); parameters[numberParameters-1].append("geo!metric"); parameters[numberParameters-1].append("auto!matic"); parameters[numberParameters-1].append("dynamic"); parameters[numberParameters-1].append("rows!only"); parameters[numberParameters-1].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[numberParameters-1].setCurrentOption(3); // say auto #ifndef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("sec!onds", "Maximum seconds", -1.0, 1.0e12, CLP_PARAM_DBL_TIMELIMIT); parameters[numberParameters-1].setLonghelp ( "After this many seconds clp will act as if maximum iterations had been reached \ (if value >=0)." ); #else parameters[numberParameters++] = CbcOrClpParam("sec!onds", "maximum seconds", -1.0, 1.0e12, CBC_PARAM_DBL_TIMELIMIT_BAB); parameters[numberParameters-1].setLonghelp ( "After this many seconds coin solver will act as if maximum nodes had been reached." ); #endif parameters[numberParameters++] = CbcOrClpParam("sleep", "for debug", CLP_PARAM_ACTION_DUMMY, 7, 0); parameters[numberParameters-1].setLonghelp ( "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("slow!cutpasses", "Maximum number of tries for slower cuts", -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS); parameters[numberParameters-1].setLonghelp ( "Some cut generators are fairly slow - this limits the number of times they are tried." ); parameters[numberParameters-1].setIntValue(10); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("slp!Value", "Number of slp passes before primal", -1, 50000, CLP_PARAM_INT_SLPVALUE, 1); parameters[numberParameters-1].setLonghelp ( "If you are solving a quadratic problem using primal then it may be helpful to do some \ sequential Lps to get a good approximate solution." ); #if CLP_MULTIPLE_FACTORIZATIONS > 0 parameters[numberParameters++] = CbcOrClpParam("small!Factorization", "Whether to use small factorization", -1, 10000, CBC_PARAM_INT_SMALLFACT, 1); parameters[numberParameters-1].setLonghelp ( "If processed problem <= this use small factorization" ); parameters[numberParameters-1].setIntValue(-1); #endif #endif parameters[numberParameters++] = CbcOrClpParam("solu!tion", "Prints solution to file", CLP_PARAM_ACTION_SOLUTION); parameters[numberParameters-1].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." ); #ifdef COIN_HAS_CLP #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("solv!e", "Solve problem", CBC_PARAM_ACTION_BAB); parameters[numberParameters-1].setLonghelp ( "If there are no integer variables then this just solves LP. If there are integer variables \ this does branch and cut." ); parameters[numberParameters++] = CbcOrClpParam("sos!Options", "Whether to use SOS from AMPL", "off", CBC_PARAM_STR_SOS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setCurrentOption("on"); parameters[numberParameters-1].setLonghelp ( "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\ be turned off - this does so." ); parameters[numberParameters++] = CbcOrClpParam("slog!Level", "Level of detail in (LP) Solver output", -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL); parameters[numberParameters-1].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. This parameter is only used inside MIP - for Clp use 'log'" ); #else // allow solve as synonym for possible dual parameters[numberParameters++] = CbcOrClpParam("solv!e", "Solve problem using dual simplex (probably)", CLP_PARAM_ACTION_EITHERSIMPLEX); parameters[numberParameters-1].setLonghelp ( "Just so can use solve for clp as well as in cbc" ); #endif #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("spars!eFactor", "Whether factorization treated as sparse", "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0); parameters[numberParameters-1].append("off"); parameters[numberParameters++] = CbcOrClpParam("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp", 0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0); parameters[numberParameters++] = CbcOrClpParam("sprint!Crash", "Whether to try sprint crash", -1, 5000000, CLP_PARAM_INT_SPRINT); parameters[numberParameters-1].setLonghelp ( "For long and thin problems this program may solve a series of small problems\ created by taking a subset of the columns. I introduced the idea as 'Sprint' after\ an LP code of that name of the 60's which tried the same tactic (not totally successfully).\ Cplex calls it 'sifting'. -1 is automatic choice, 0 is off, n is number of passes" ); parameters[numberParameters++] = CbcOrClpParam("stat!istics", "Print some statistics", CLP_PARAM_ACTION_STATISTICS); parameters[numberParameters-1].setLonghelp ( "This command prints some statistics for the current model.\ If log level >1 then more is printed.\ These are for presolved model if presolve on (and unscaled)." ); #endif parameters[numberParameters++] = CbcOrClpParam("stop", "Stops clp execution", CLP_PARAM_ACTION_EXIT); parameters[numberParameters-1].setLonghelp ( "This stops the execution of Clp, end, exit, quit and stop are synonyms" ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("strat!egy", "Switches on groups of features", 0, 2, CBC_PARAM_INT_STRATEGY); parameters[numberParameters-1].setLonghelp ( "This turns on newer features. \ Use 0 for easy problems, 1 is default, 2 is aggressive. \ 1 uses Gomory cuts using tolerance of 0.01 at root, \ does a possible restart after 100 nodes if can fix many \ and activates a diving and RINS heuristic and makes feasibility pump \ more aggressive. \ This does not apply to unit tests (where 'experiment' may have similar effects)." ); parameters[numberParameters-1].setIntValue(1); #ifdef CBC_KEEP_DEPRECATED parameters[numberParameters++] = CbcOrClpParam("strengthen", "Create strengthened problem", CBC_PARAM_ACTION_STRENGTHEN, 3); parameters[numberParameters-1].setLonghelp ( "This creates a new problem by applying the root node cuts. All tight constraints \ will be in resulting problem" ); #endif parameters[numberParameters++] = CbcOrClpParam("strong!Branching", "Number of variables to look at in strong branching", 0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING); parameters[numberParameters-1].setLonghelp ( "In order to decide which variable to branch on, the code will choose up to this number \ of unsatisfied variables to do mini up and down branches on. Then 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." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("subs!titution", "How long a column to substitute for in presolve", 0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0); parameters[numberParameters-1].setLonghelp ( "Normally Presolve gets rid of 'free' variables when there are no more than 3 \ variables in column. If you increase this the number of rows may decrease but number of \ elements may increase." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("testO!si", "Test OsiObject stuff", -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0); #endif #ifdef CBC_THREAD parameters[numberParameters++] = CbcOrClpParam("thread!s", "Number of threads to try and use", -100, 100000, CBC_PARAM_INT_THREADS, 1); parameters[numberParameters-1].setLonghelp ( "To use multiple threads, set threads to number wanted. It may be better \ to use one or two more than number of cpus available. If 100+n then n threads and \ search is repeatable (maybe be somewhat slower), \ if 200+n use threads for root cuts, 400+n threads used in sub-trees." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("tighten!Factor", "Tighten bounds using this times largest \ activity at continuous solution", 1.0e-3, 1.0e20, CBC_PARAM_DBL_TIGHTENFACTOR, 0); parameters[numberParameters-1].setLonghelp ( "This sleazy trick can help on some problems." ); #endif #ifdef COIN_HAS_CLP parameters[numberParameters++] = CbcOrClpParam("tightLP", "Poor person's preSolve for now", CLP_PARAM_ACTION_TIGHTEN, 7, 0); #endif parameters[numberParameters++] = CbcOrClpParam("timeM!ode", "Whether to use CPU or elapsed time", "cpu", CLP_PARAM_STR_TIME_MODE); parameters[numberParameters-1].append("elapsed"); parameters[numberParameters-1].setLonghelp ( "cpu uses CPU time for stopping, while elapsed uses elapsed time. \ (On Windows, elapsed time is always used)." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("trust!PseudoCosts", "Number of branches before we trust pseudocosts", -3, 2000000000, CBC_PARAM_INT_NUMBERBEFORE); parameters[numberParameters-1].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." ); #endif #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("tune!PreProcess", "Dubious tuning parameters", 0, 20000000, CLP_PARAM_INT_PROCESSTUNE, 1); parameters[numberParameters-1].setLonghelp ( "For making equality cliques this is minimumsize. Also for adding \ integer slacks. May be used for more later \ If <10000 that is what it does. If <1000000 - numberPasses is (value/10000)-1 and tune is tune %10000. \ If >= 1000000! - numberPasses is (value/1000000)-1 and tune is tune %1000000. In this case if tune is now still >=10000 \ numberPassesPerInnerLoop is changed from 10 to (tune-10000)-1 and tune becomes tune % 10000!!!!! - happy? - \ so to keep normal limit on cliques of 5, do 3 major passes (include presolves) but only doing one tightening pass per major pass - \ you would use 3010005 (I think)" ); parameters[numberParameters++] = CbcOrClpParam("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts", "off", CBC_PARAM_STR_TWOMIRCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].append("forceandglobal"); parameters[numberParameters-1].append("forceLongOn"); parameters[numberParameters-1].setLonghelp ( "This switches on two phase mixed integer rounding cuts (either at root or in entire tree) \ See branchAndCut for information on options." ); #endif parameters[numberParameters++] = CbcOrClpParam("unitTest", "Do unit test", CLP_PARAM_ACTION_UNITTEST, 3, 1); parameters[numberParameters-1].setLonghelp ( "This exercises the unit test for clp" ); parameters[numberParameters++] = CbcOrClpParam("userClp", "Hand coded Clp stuff", CLP_PARAM_ACTION_USERCLP, 0, 0); parameters[numberParameters-1].setLonghelp ( "There are times e.g. when using AMPL interface when you may wish to do something unusual. \ Look for USERCLP in main driver and modify sample code." ); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("userCbc", "Hand coded Cbc stuff", CBC_PARAM_ACTION_USERCBC, 0, 0); parameters[numberParameters-1].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. \ It is possible you can get same effect by using example driver4.cpp." ); parameters[numberParameters++] = CbcOrClpParam("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search", "off", CBC_PARAM_STR_VND); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("both"); parameters[numberParameters-1].append("before"); parameters[numberParameters-1].append("intree"); parameters[numberParameters-1].setLonghelp ( "This switches on variable neighborhood Search. \ Doh option does heuristic before preprocessing" ); #endif parameters[numberParameters++] = CbcOrClpParam("vector", "Whether to use vector? Form of matrix in simplex", "off", CLP_PARAM_STR_VECTOR, 7, 0); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].setLonghelp ( "If this is on ClpPackedMatrix uses extra column copy in odd format." ); parameters[numberParameters++] = CbcOrClpParam("verbose", "Switches on longer help on single ?", 0, 31, CLP_PARAM_INT_VERBOSE, 0); parameters[numberParameters-1].setLonghelp ( "Set to 1 to get short help with ? list, 2 to get long help, 3 for both. (add 4 to just get ampl ones)." ); parameters[numberParameters-1].setIntValue(0); #ifdef COIN_HAS_CBC parameters[numberParameters++] = CbcOrClpParam("vub!heuristic", "Type of vub heuristic", -2, 20, CBC_PARAM_INT_VUBTRY, 0); parameters[numberParameters-1].setLonghelp ( "If set will try and fix some integer variables" ); parameters[numberParameters-1].setIntValue(-1); parameters[numberParameters++] = CbcOrClpParam("zero!HalfCuts", "Whether to use zero half cuts", "off", CBC_PARAM_STR_ZEROHALFCUTS); parameters[numberParameters-1].append("on"); parameters[numberParameters-1].append("root"); parameters[numberParameters-1].append("ifmove"); parameters[numberParameters-1].append("forceOn"); parameters[numberParameters-1].append("onglobal"); parameters[numberParameters-1].setLonghelp ( "This switches on zero-half cuts (either at root or in entire tree) \ See branchAndCut for information on options. This implementation was written by \ Alberto Caprara." ); #endif parameters[numberParameters++] = CbcOrClpParam("zeroT!olerance", "Kill all coefficients \ whose absolute value is less than this value", 1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE); parameters[numberParameters-1].setLonghelp ( "This applies to reading mps files (and also lp files \ if KILL_ZERO_READLP defined)" ); parameters[numberParameters-1].setDoubleValue(1.0e-20); assert(numberParameters < CBCMAXPARAMETERS); } // Given a parameter type - returns its number in list int whichParam (CbcOrClpParameterType name, int numberParameters, CbcOrClpParam *const parameters) { int i; for (i = 0; i < numberParameters; i++) { if (parameters[i].type() == name) break; } assert (i < numberParameters); return i; } #ifdef COIN_HAS_CLP /* Restore a solution from file. mode 0 normal, 1 swap rows and columns and primal and dual if 2 set then also change signs */ void restoreSolution(ClpSimplex * lpSolver, std::string fileName, int mode) { FILE * fp = fopen(fileName.c_str(), "rb"); if (fp) { int numberRows = lpSolver->numberRows(); int numberColumns = lpSolver->numberColumns(); int numberRowsFile; int numberColumnsFile; double objectiveValue; size_t nRead; nRead = fread(&numberRowsFile, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); nRead = fread(&numberColumnsFile, sizeof(int), 1, fp); if (nRead != 1) throw("Error in fread"); nRead = fread(&objectiveValue, sizeof(double), 1, fp); if (nRead != 1) throw("Error in fread"); double * dualRowSolution = lpSolver->dualRowSolution(); double * primalRowSolution = lpSolver->primalRowSolution(); double * dualColumnSolution = lpSolver->dualColumnSolution(); double * primalColumnSolution = lpSolver->primalColumnSolution(); if (mode) { // swap int k = numberRows; numberRows = numberColumns; numberColumns = k; double * temp; temp = dualRowSolution; dualRowSolution = primalColumnSolution; primalColumnSolution = temp; temp = dualColumnSolution; dualColumnSolution = primalRowSolution; primalRowSolution = temp; } if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) { std::cout << "Mismatch on rows and/or columns - giving up" << std::endl; } else { lpSolver->setObjectiveValue(objectiveValue); if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) { nRead = fread(primalRowSolution, sizeof(double), numberRows, fp); if (nRead != static_cast(numberRows)) throw("Error in fread"); nRead = fread(dualRowSolution, sizeof(double), numberRows, fp); if (nRead != static_cast(numberRows)) throw("Error in fread"); nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp); if (nRead != static_cast(numberColumns)) throw("Error in fread"); nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp); if (nRead != static_cast(numberColumns)) throw("Error in fread"); } else { std::cout << "Mismatch on rows and/or columns - truncating" << std::endl; double * temp = new double [CoinMax(numberRowsFile, numberColumnsFile)]; nRead = fread(temp, sizeof(double), numberRowsFile, fp); if (nRead != static_cast(numberRowsFile)) throw("Error in fread"); CoinMemcpyN(temp, numberRows, primalRowSolution); nRead = fread(temp, sizeof(double), numberRowsFile, fp); if (nRead != static_cast(numberRowsFile)) throw("Error in fread"); CoinMemcpyN(temp, numberRows, dualRowSolution); nRead = fread(temp, sizeof(double), numberColumnsFile, fp); if (nRead != static_cast(numberColumnsFile)) throw("Error in fread"); CoinMemcpyN(temp, numberColumns, primalColumnSolution); nRead = fread(temp, sizeof(double), numberColumnsFile, fp); if (nRead != static_cast(numberColumnsFile)) throw("Error in fread"); CoinMemcpyN(temp, numberColumns, dualColumnSolution); delete [] temp; } if (mode == 3) { int i; for (i = 0; i < numberRows; i++) { primalRowSolution[i] = -primalRowSolution[i]; dualRowSolution[i] = -dualRowSolution[i]; } for (i = 0; i < numberColumns; i++) { primalColumnSolution[i] = -primalColumnSolution[i]; dualColumnSolution[i] = -dualColumnSolution[i]; } } } fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } // Dump a solution to file void saveSolution(const ClpSimplex * lpSolver, std::string fileName) { if (strstr(fileName.c_str(), "_fix_read_")) { FILE * fp = fopen(fileName.c_str(), "rb"); if (fp) { ClpSimplex * solver = const_cast(lpSolver); restoreSolution(solver, fileName, 0); // fix all int logLevel = solver->logLevel(); int iColumn; int numberColumns = solver->numberColumns(); double * primalColumnSolution = solver->primalColumnSolution(); double * columnLower = solver->columnLower(); double * columnUpper = solver->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = primalColumnSolution[iColumn]; if (value > columnUpper[iColumn]) { if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1) printf("%d value of %g - bounds %g %g\n", iColumn, value, columnLower[iColumn], columnUpper[iColumn]); value = columnUpper[iColumn]; } else if (value < columnLower[iColumn]) { if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1) printf("%d value of %g - bounds %g %g\n", iColumn, value, columnLower[iColumn], columnUpper[iColumn]); value = columnLower[iColumn]; } columnLower[iColumn] = value; columnUpper[iColumn] = value; } return; } } FILE * fp = fopen(fileName.c_str(), "wb"); if (fp) { int numberRows = lpSolver->numberRows(); int numberColumns = lpSolver->numberColumns(); double objectiveValue = lpSolver->objectiveValue(); size_t nWrite; nWrite = fwrite(&numberRows, sizeof(int), 1, fp); if (nWrite != 1) throw("Error in fwrite"); nWrite = fwrite(&numberColumns, sizeof(int), 1, fp); if (nWrite != 1) throw("Error in fwrite"); nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp); if (nWrite != 1) throw("Error in fwrite"); double * dualRowSolution = lpSolver->dualRowSolution(); double * primalRowSolution = lpSolver->primalRowSolution(); nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp); if (nWrite != static_cast(numberRows)) throw("Error in fwrite"); nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp); if (nWrite != static_cast(numberRows)) throw("Error in fwrite"); double * dualColumnSolution = lpSolver->dualColumnSolution(); double * primalColumnSolution = lpSolver->primalColumnSolution(); nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp); if (nWrite != static_cast(numberColumns)) throw("Error in fwrite"); nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp); if (nWrite != static_cast(numberColumns)) throw("Error in fwrite"); fclose(fp); } else { std::cout << "Unable to open file " << fileName << std::endl; } } #endif Clp-1.15.10/src/ClpSimplexNonlinear.cpp0000644000076600007660000056035512130104455016305 0ustar coincoin/* $Id: ClpSimplexNonlinear.cpp 1931 2013-04-06 20:44:29Z 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 "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpSimplexNonlinear.hpp" #include "ClpFactorization.hpp" #include "ClpNonLinearCost.hpp" #include "ClpLinearObjective.hpp" #include "ClpConstraint.hpp" #include "ClpQuadraticObjective.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "ClpPrimalColumnPivot.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include #include #include #include #include #ifndef NDEBUG #define CLP_DEBUG 1 #endif // primal int ClpSimplexNonlinear::primal () { int ifValuesPass = 1; algorithm_ = +3; // save data ClpDataSave data = saveData(); matrix_->refresh(this); // make sure matrix okay // Save objective ClpObjective * saveObjective = NULL; if (objective_->type() > 1) { // expand to full if quadratic #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif // for moment only if no scaling // May be faster if switched off - but can't see why if (!quadraticObj->fullMatrix() && (!rowScale_ && !scalingFlag_) && objectiveScale_ == 1.0) { saveObjective = objective_; objective_ = new ClpQuadraticObjective(*quadraticObj, 1); } } double bestObjectiveWhenFlagged = COIN_DBL_MAX; int pivotMode = 15; //pivotMode=20; // initialize - maybe values pass and algorithm_ is +1 // true does something (? perturbs) if (!startup(true)) { // Set average theta nonLinearCost_->setAverageTheta(1.0e3); int lastCleaned = 0; // last time objective or bounds cleaned up // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // This says whether to restore things etc int factorType = 0; // Start check for cycles progress_.startCheck(); /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible -5 - looks unbounded */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick // If we have done no iterations - special if (lastGoodIteration_ == numberIterations_ && factorType) factorType = 3; // may factorize, checks if problem finished if (objective_->type() > 1 && lastFlaggedIteration_ >= 0 && numberIterations_ > lastFlaggedIteration_ + 507) { unflag(); lastFlaggedIteration_ = numberIterations_; if (pivotMode >= 10) { pivotMode--; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("pivot mode now %d\n", pivotMode); #endif if (pivotMode == 9) pivotMode = 0; // switch off fast attempt } } statusOfProblemInPrimal(lastCleaned, factorType, &progress_, true, bestObjectiveWhenFlagged); // Say good factorization factorType = 1; // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // exit if victory declared if (problemStatus_ >= 0) break; // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && firstFree_ < 0)) { problemStatus_ = 3; break; } if (firstFree_ < 0) { if (ifValuesPass) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Iterate whileIterating(pivotMode); } } // if infeasible get real values if (problemStatus_ == 1) { infeasibilityCost_ = 0.0; createRim(1 + 4); delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); nonLinearCost_->checkInfeasibilities(0.0); sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities(); numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); // and get good feasible duals computeDuals(NULL); } // correct objective value if (numberColumns_) objectiveValue_ = nonLinearCost_->feasibleCost() + objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); // clean up unflag(); finish(); restoreData(data); // restore objective if full if (saveObjective) { delete objective_; objective_ = saveObjective; } return problemStatus_; } /* Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void ClpSimplexNonlinear::statusOfProblemInPrimal(int & lastCleaned, int type, ClpSimplexProgress * progress, bool doFactorization, double & bestObjectiveWhenFlagged) { int dummy; // for use in generalExpanded if (type == 2) { // trouble - restore solution CoinMemcpyN(saveStatus_, (numberColumns_ + numberRows_), status_ ); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); forceFactorization_ = 1; // a bit drastic but .. pivotRow_ = -1; // say no weights update changeMade_++; // say change made } int saveThreshold = factorization_->sparseThreshold(); int tentativeStatus = problemStatus_; int numberThrownOut = 1; // to loop round on bad factorization in values pass while (numberThrownOut) { if (problemStatus_ > -3 || problemStatus_ == -4) { // factorize // later on we will need to recover from singularities // also we could skip if first time // do weights // This may save pivotRow_ for use if (doFactorization) primalColumnPivot_->saveWeights(this, 1); if (type && doFactorization) { // is factorization okay? int factorStatus = internalFactorize(1); if (factorStatus) { if (type != 1 || largestPrimalError_ > 1.0e3 || largestDualError_ > 1.0e3) { // was ||largestDualError_>1.0e3||objective_->type()>1) { // switch off dense int saveDense = factorization_->denseThreshold(); factorization_->setDenseThreshold(0); // make sure will do safe factorization pivotVariable_[0] = -1; internalFactorize(2); factorization_->setDenseThreshold(saveDense); // Go to safe factorization_->pivotTolerance(0.99); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); } else { // no - restore previous basis CoinMemcpyN(saveStatus_, (numberColumns_ + numberRows_), status_ ); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff matrix_->generalExpanded(this, 6, dummy); matrix_->generalExpanded(this, 5, dummy); forceFactorization_ = 1; // a bit drastic but .. type = 2; // Go to safe factorization_->pivotTolerance(0.99); if (internalFactorize(1) != 0) largestPrimalError_ = 1.0e4; // force other type } // flag incoming if (sequenceIn_ >= 0 && getStatus(sequenceIn_) != basic) { setFlagged(sequenceIn_); saveStatus_[sequenceIn_] = status_[sequenceIn_]; } changeMade_++; // say change made } } if (problemStatus_ != -4) problemStatus_ = -3; } // at this stage status is -3 or -5 if looks unbounded // get primal and dual solutions // put back original costs and then check createRim(4); // May need to do more if column generation dummy = 4; matrix_->generalExpanded(this, 9, dummy); numberThrownOut = gutsOfSolution(NULL, NULL, (firstFree_ >= 0)); if (numberThrownOut) { problemStatus_ = tentativeStatus; doFactorization = true; } } // Double check reduced costs if no action if (progress->lastIterationNumber(0) == numberIterations_) { if (primalColumnPivot_->looksOptimal()) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; } } // Check if looping int loop; if (type != 2) loop = progress->looping(); else loop = -1; if (loop >= 0) { if (!problemStatus_) { // declaring victory numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else { problemStatus_ = loop; //exit if in loop problemStatus_ = 10; // instead - try other algorithm } problemStatus_ = 10; // instead - try other algorithm return ; } else if (loop < -1) { // Is it time for drastic measures if (nonLinearCost_->numberInfeasibilities() && progress->badTimes() > 5 && progress->oddState() < 10 && progress->oddState() >= 0) { progress->newOddState(); nonLinearCost_->zapCosts(); } // something may have changed gutsOfSolution(NULL, NULL, true); } // If progress then reset costs if (loop == -1 && !nonLinearCost_->numberInfeasibilities() && progress->oddState() < 0) { createRim(4, false); // costs back delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); progress->endOddState(); gutsOfSolution(NULL, NULL, true); } // Flag to say whether to go to dual to clean up //bool goToDual = false; // really for free variables in //if((progressFlag_&2)!=0) //problemStatus_=-1;; progressFlag_ = 0; //reset progress flag handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << nonLinearCost_->feasibleReportCost(); handler_->printing(nonLinearCost_->numberInfeasibilities() > 0) << nonLinearCost_->sumInfeasibilities() << nonLinearCost_->numberInfeasibilities(); handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; if (!primalFeasible()) { nonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfSolution(NULL, NULL, true); nonLinearCost_->checkInfeasibilities(primalTolerance_); } double trueInfeasibility = nonLinearCost_->sumInfeasibilities(); if (trueInfeasibility > 1.0) { // If infeasibility going up may change weights double testValue = trueInfeasibility - 1.0e-4 * (10.0 + trueInfeasibility); if(progress->lastInfeasibility() < testValue) { if (infeasibilityCost_ < 1.0e14) { infeasibilityCost_ *= 1.5; if (handler_->logLevel() == 63) printf("increasing weight to %g\n", infeasibilityCost_); gutsOfSolution(NULL, NULL, true); } } } // we may wish to say it is optimal even if infeasible bool alwaysOptimal = (specialOptions_ & 1) != 0; // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } // had ||(type==3&&problemStatus_!=-5) -- ??? why ???? if (dualFeasible() || problemStatus_ == -4) { // see if extra helps if (nonLinearCost_->numberInfeasibilities() && (nonLinearCost_->sumInfeasibilities() > 1.0e-3 || sumOfRelaxedPrimalInfeasibilities_) && !alwaysOptimal) { //may need infeasiblity cost changed // we can see if we can construct a ray // make up a new objective double saveWeight = infeasibilityCost_; // save nonlinear cost as we are going to switch off costs ClpNonLinearCost * nonLinear = nonLinearCost_; // do twice to make sure Primal solution has settled // put non-basics to bounds in case tolerance moved // put back original costs createRim(4); nonLinearCost_->checkInfeasibilities(0.0); gutsOfSolution(NULL, NULL, true); infeasibilityCost_ = 1.0e100; // put back original costs createRim(4); nonLinearCost_->checkInfeasibilities(primalTolerance_); // may have fixed infeasibilities - double check if (nonLinearCost_->numberInfeasibilities() == 0) { // carry on problemStatus_ = -1; infeasibilityCost_ = saveWeight; nonLinearCost_->checkInfeasibilities(primalTolerance_); } else { nonLinearCost_ = NULL; // scale int i; for (i = 0; i < numberRows_ + numberColumns_; i++) cost_[i] *= 1.0e-95; gutsOfSolution(NULL, NULL, false); nonLinearCost_ = nonLinear; infeasibilityCost_ = saveWeight; if ((infeasibilityCost_ >= 1.0e18 || numberDualInfeasibilities_ == 0) && perturbation_ == 101) { /* goToDual = unPerturb(); // stop any further perturbation if (nonLinearCost_->sumInfeasibilities() > 1.0e-1) goToDual = false; */ unPerturb(); nonLinearCost_->checkInfeasibilities(primalTolerance_); numberDualInfeasibilities_ = 1; // carry on problemStatus_ = -1; } if (infeasibilityCost_ >= 1.0e20 || numberDualInfeasibilities_ == 0) { // we are infeasible - use as ray delete [] ray_; ray_ = new double [numberRows_]; CoinMemcpyN(dual_, numberRows_, ray_); // and get feasible duals infeasibilityCost_ = 0.0; createRim(4); nonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfSolution(NULL, NULL, true); // so will exit infeasibilityCost_ = 1.0e30; // reset infeasibilities sumPrimalInfeasibilities_ = nonLinearCost_->sumInfeasibilities();; numberPrimalInfeasibilities_ = nonLinearCost_->numberInfeasibilities(); } if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; changeMade_++; // say change made unflag(); handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check createRim(4); nonLinearCost_->checkInfeasibilities(0.0); gutsOfSolution(NULL, NULL, true); problemStatus_ = -1; //continue //goToDual = false; } else { // say infeasible problemStatus_ = 1; } } } else { // may be optimal if (perturbation_ == 101) { /* goToDual =*/ unPerturb(); // stop any further perturbation lastCleaned = -1; // carry on } bool unflagged = unflag() != 0; if ( lastCleaned != numberIterations_ || unflagged) { handler_->message(CLP_PRIMAL_OPTIMAL, messages_) << primalTolerance_ << CoinMessageEol; double current = nonLinearCost_->feasibleReportCost(); if (numberTimesOptimal_ < 4) { if (bestObjectiveWhenFlagged <= current) { numberTimesOptimal_++; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("%d times optimal, current %g best %g\n", numberTimesOptimal_, current, bestObjectiveWhenFlagged); #endif } else { bestObjectiveWhenFlagged = current; } changeMade_++; // say change made if (numberTimesOptimal_ == 1) { // better to have small tolerance even if slower factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15)); } lastCleaned = numberIterations_; if (primalTolerance_ != dblParam_[ClpPrimalTolerance]) handler_->message(CLP_PRIMAL_ORIGINAL, messages_) << CoinMessageEol; double oldTolerance = primalTolerance_; primalTolerance_ = dblParam_[ClpPrimalTolerance]; // put back original costs and then check createRim(4); nonLinearCost_->checkInfeasibilities(oldTolerance); gutsOfSolution(NULL, NULL, true); if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } if (dualFeasible() && !nonLinearCost_->numberInfeasibilities() && lastCleaned >= 0) problemStatus_ = 0; else problemStatus_ = -1; } else { problemStatus_ = 0; // optimal if (lastCleaned < numberIterations_) { handler_->message(CLP_SIMPLEX_GIVINGUP, messages_) << CoinMessageEol; } } } else { problemStatus_ = 0; // optimal } } } else { // see if looks unbounded if (problemStatus_ == -5) { if (nonLinearCost_->numberInfeasibilities()) { if (infeasibilityCost_ > 1.0e18 && perturbation_ == 101) { // back off weight infeasibilityCost_ = 1.0e13; unPerturb(); // stop any further perturbation } //we need infeasiblity cost changed if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; changeMade_++; // say change made unflag(); handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check createRim(4); gutsOfSolution(NULL, NULL, true); problemStatus_ = -1; //continue } else { // say unbounded problemStatus_ = 2; } } else { // say unbounded problemStatus_ = 2; } } else { if(type == 3 && problemStatus_ != -5) unflag(); // odd // carry on problemStatus_ = -1; } } // save extra stuff matrix_->generalExpanded(this, 5, dummy); if (type == 0 || type == 1) { if (type != 1 || !saveStatus_) { // create save arrays delete [] saveStatus_; delete [] savedSolution_; saveStatus_ = new unsigned char [numberRows_+numberColumns_]; savedSolution_ = new double [numberRows_+numberColumns_]; } // save arrays CoinMemcpyN(status_, (numberColumns_ + numberRows_), saveStatus_); CoinMemcpyN(rowActivityWork_, numberRows_, savedSolution_ + numberColumns_ ); CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_ ); } if (doFactorization) { // restore weights (if saved) - also recompute infeasibility list if (tentativeStatus > -3) primalColumnPivot_->saveWeights(this, (type < 2) ? 2 : 4); else primalColumnPivot_->saveWeights(this, 3); if (saveThreshold) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } } if (problemStatus_ < 0 && !changeMade_) { problemStatus_ = 4; // unknown } lastGoodIteration_ = numberIterations_; //if (goToDual) //problemStatus_=10; // try dual // Allow matrices to be sorted etc int fake = -999; // signal sort matrix_->correctSequence(this, fake, fake); } /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) -4 end of values pass and done iterations +0 looks optimal (might be infeasible - but we will investigate) +2 looks unbounded +3 max iterations */ int ClpSimplexNonlinear::whileIterating(int & pivotMode) { // Say if values pass //int ifValuesPass=(firstFree_>=0) ? 1 : 0; int ifValuesPass = 1; int returnCode = -1; // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int numberInterior = 0; int nextUnflag = 10; int nextUnflagIteration = numberIterations_ + 10; // get two arrays double * array1 = new double[2*(numberRows_+numberColumns_)]; double solutionError = -1.0; while (problemStatus_ == -1) { int result; rowArray_[1]->clear(); //#define CLP_DEBUG #if CLP_DEBUG > 1 rowArray_[0]->checkClear(); rowArray_[1]->checkClear(); rowArray_[2]->checkClear(); rowArray_[3]->checkClear(); columnArray_[0]->checkClear(); #endif if (numberInterior >= 5) { // this can go when we have better minimization if (pivotMode < 10) pivotMode = 1; unflag(); #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("interior unflag\n"); #endif numberInterior = 0; nextUnflag = 10; nextUnflagIteration = numberIterations_ + 10; } else { if (numberInterior > nextUnflag && numberIterations_ > nextUnflagIteration) { nextUnflagIteration = numberIterations_ + 10; nextUnflag += 10; unflag(); #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("unflagging as interior\n"); #endif } } pivotRow_ = -1; result = pivotColumn(rowArray_[3], rowArray_[0], columnArray_[0], rowArray_[1], pivotMode, solutionError, array1); if (result) { if (result == 2 && sequenceIn_ < 0) { // does not look good double currentObj; double thetaObj; double predictedObj; objective_->stepLength(this, solution_, solution_, 0.0, currentObj, thetaObj, predictedObj); if (currentObj == predictedObj) { #ifdef CLP_INVESTIGATE printf("looks bad - no change in obj %g\n", currentObj); #endif if (factorization_->pivots()) result = 3; else problemStatus_ = 0; } } if (result == 3) break; // null vector not accurate #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { double currentObj; double thetaObj; double predictedObj; objective_->stepLength(this, solution_, solution_, 0.0, currentObj, thetaObj, predictedObj); printf("obj %g after interior move\n", currentObj); } #endif // just move and try again if (pivotMode < 10) { pivotMode = result - 1; numberInterior++; } continue; } else { if (pivotMode < 10) { if (theta_ > 0.001) pivotMode = 0; else if (pivotMode == 2) pivotMode = 1; } numberInterior = 0; nextUnflag = 10; nextUnflagIteration = numberIterations_ + 10; } sequenceOut_ = -1; rowArray_[1]->clear(); if (sequenceIn_ >= 0) { // we found a pivot column assert (!flagged(sequenceIn_)); #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) { char x = isColumn(sequenceIn_) ? 'C' : 'R'; std::cout << "pivot column " << x << sequenceWithin(sequenceIn_) << std::endl; } #endif // do second half of iteration if (pivotRow_ < 0 && theta_ < 1.0e-8) { assert (sequenceIn_ >= 0); returnCode = pivotResult(ifValuesPass); } else { // specialized code returnCode = pivotNonlinearResult(); //printf("odd pivrow %d\n",sequenceOut_); if (sequenceOut_ >= 0 && theta_ < 1.0e-5) { if (getStatus(sequenceOut_) != isFixed) { if (getStatus(sequenceOut_) == atUpperBound) solution_[sequenceOut_] = upper_[sequenceOut_]; else if (getStatus(sequenceOut_) == atLowerBound) solution_[sequenceOut_] = lower_[sequenceOut_]; setFlagged(sequenceOut_); } } } if (returnCode < -1 && returnCode > -5) { problemStatus_ = -2; // } else if (returnCode == -5) { // something flagged - continue; } else if (returnCode == 2) { problemStatus_ = -5; // looks unbounded } else if (returnCode == 4) { problemStatus_ = -2; // looks unbounded but has iterated } else if (returnCode != -1) { assert(returnCode == 3); problemStatus_ = 3; } } else { // no pivot column #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (pivotMode < 10) { // looks optimal primalColumnPivot_->setLooksOptimal(true); } else { pivotMode--; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("pivot mode now %d\n", pivotMode); #endif if (pivotMode == 9) pivotMode = 0; // switch off fast attempt unflag(); } if (nonLinearCost_->numberInfeasibilities()) problemStatus_ = -4; // might be infeasible returnCode = 0; break; } } delete [] array1; return returnCode; } // Creates direction vector void ClpSimplexNonlinear::directionVector (CoinIndexedVector * vectorArray, CoinIndexedVector * spare1, CoinIndexedVector * spare2, int pivotMode2, double & normFlagged, double & normUnflagged, int & numberNonBasic) { #if CLP_DEBUG > 1 vectorArray->checkClear(); spare1->checkClear(); spare2->checkClear(); #endif double *array = vectorArray->denseVector(); int * index = vectorArray->getIndices(); int number = 0; sequenceIn_ = -1; normFlagged = 0.0; normUnflagged = 1.0; double dualTolerance2 = CoinMin(1.0e-8, 1.0e-2 * dualTolerance_); double dualTolerance3 = CoinMin(1.0e-2, 1.0e3 * dualTolerance_); if (!numberNonBasic) { //if (nonLinearCost_->sumInfeasibilities()>1.0e-4) //printf("infeasible\n"); if (!pivotMode2 || pivotMode2 >= 10) { normUnflagged = 0.0; double bestDj = 0.0; double bestSuper = 0.0; double sumSuper = 0.0; sequenceIn_ = -1; int nSuper = 0; for (int iSequence = 0; iSequence < numberColumns_ + numberRows_; iSequence++) { array[iSequence] = 0.0; if (flagged(iSequence)) { // accumulate norm switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case atLowerBound: if (dj_[iSequence] < -dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; } continue; } switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) { if (dj_[iSequence] > dualTolerance3) normUnflagged += dj_[iSequence] * dj_[iSequence]; if (pivotMode2 < 10) { array[iSequence] = -dj_[iSequence]; index[number++] = iSequence; } else { if (dj_[iSequence] > bestDj) { bestDj = dj_[iSequence]; sequenceIn_ = iSequence; } } } break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) { if (dj_[iSequence] < -dualTolerance3) normUnflagged += dj_[iSequence] * dj_[iSequence]; if (pivotMode2 < 10) { array[iSequence] = -dj_[iSequence]; index[number++] = iSequence; } else { if (-dj_[iSequence] > bestDj) { bestDj = -dj_[iSequence]; sequenceIn_ = iSequence; } } } break; case isFree: case superBasic: //#define ALLSUPER #define NOSUPER #ifndef ALLSUPER if (fabs(dj_[iSequence]) > dualTolerance_) { if (fabs(dj_[iSequence]) > dualTolerance3) normUnflagged += dj_[iSequence] * dj_[iSequence]; nSuper++; bestSuper = CoinMax(fabs(dj_[iSequence]), bestSuper); sumSuper += fabs(dj_[iSequence]); } if (fabs(dj_[iSequence]) > dualTolerance2) { array[iSequence] = -dj_[iSequence]; index[number++] = iSequence; } #else array[iSequence] = -dj_[iSequence]; index[number++] = iSequence; if (pivotMode2 >= 10) bestSuper = CoinMax(fabs(dj_[iSequence]), bestSuper); #endif break; } } #ifdef NOSUPER // redo bestSuper = sumSuper; if(sequenceIn_ >= 0 && bestDj > bestSuper) { int j; // get rid of superbasics for (j = 0; j < number; j++) { int iSequence = index[j]; array[iSequence] = 0.0; } number = 0; array[sequenceIn_] = -dj_[sequenceIn_]; index[number++] = sequenceIn_; } else { sequenceIn_ = -1; } #else if (pivotMode2 >= 10 || !nSuper) { bool takeBest = true; if (pivotMode2 == 100 && nSuper > 1) takeBest = false; if(sequenceIn_ >= 0 && takeBest) { if (fabs(dj_[sequenceIn_]) > bestSuper) { array[sequenceIn_] = -dj_[sequenceIn_]; index[number++] = sequenceIn_; } else { sequenceIn_ = -1; } } else { sequenceIn_ = -1; } } #endif #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { if (sequenceIn_ >= 0) printf("%d superBasic, chosen %d - dj %g\n", nSuper, sequenceIn_, dj_[sequenceIn_]); else printf("%d superBasic - none chosen\n", nSuper); } #endif } else { double bestDj = 0.0; double saveDj = 0.0; if (sequenceOut_ >= 0) { saveDj = dj_[sequenceOut_]; dj_[sequenceOut_] = 0.0; switch(getStatus(sequenceOut_)) { case basic: sequenceOut_ = -1; case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[sequenceOut_] > dualTolerance_) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("after pivot out %d values %g %g %g, dj %g\n", sequenceOut_, lower_[sequenceOut_], solution_[sequenceOut_], upper_[sequenceOut_], dj_[sequenceOut_]); #endif } break; case atLowerBound: if (dj_[sequenceOut_] < -dualTolerance_) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("after pivot out %d values %g %g %g, dj %g\n", sequenceOut_, lower_[sequenceOut_], solution_[sequenceOut_], upper_[sequenceOut_], dj_[sequenceOut_]); #endif } break; case isFree: case superBasic: if (dj_[sequenceOut_] > dualTolerance_) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("after pivot out %d values %g %g %g, dj %g\n", sequenceOut_, lower_[sequenceOut_], solution_[sequenceOut_], upper_[sequenceOut_], dj_[sequenceOut_]); #endif } else if (dj_[sequenceOut_] < -dualTolerance_) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("after pivot out %d values %g %g %g, dj %g\n", sequenceOut_, lower_[sequenceOut_], solution_[sequenceOut_], upper_[sequenceOut_], dj_[sequenceOut_]); #endif } break; } } // Go for dj pivotMode2 = 3; for (int iSequence = 0; iSequence < numberColumns_ + numberRows_; iSequence++) { array[iSequence] = 0.0; if (flagged(iSequence)) continue; switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) { double distance = CoinMin(1.0e-2, solution_[iSequence] - lower_[iSequence]); double merit = distance * dj_[iSequence]; if (pivotMode2 == 1) merit *= 1.0e-20; // discourage if (pivotMode2 == 3) merit = fabs(dj_[iSequence]); if (merit > bestDj) { sequenceIn_ = iSequence; bestDj = merit; } } break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) { double distance = CoinMin(1.0e-2, upper_[iSequence] - solution_[iSequence]); double merit = -distance * dj_[iSequence]; if (pivotMode2 == 1) merit *= 1.0e-20; // discourage if (pivotMode2 == 3) merit = fabs(dj_[iSequence]); if (merit > bestDj) { sequenceIn_ = iSequence; bestDj = merit; } } break; case isFree: case superBasic: if (dj_[iSequence] > dualTolerance_) { double distance = CoinMin(1.0e-2, solution_[iSequence] - lower_[iSequence]); distance = CoinMin(solution_[iSequence] - lower_[iSequence], upper_[iSequence] - solution_[iSequence]); double merit = distance * dj_[iSequence]; if (pivotMode2 == 1) merit = distance; if (pivotMode2 == 3) merit = fabs(dj_[iSequence]); if (merit > bestDj) { sequenceIn_ = iSequence; bestDj = merit; } } else if (dj_[iSequence] < -dualTolerance_) { double distance = CoinMin(1.0e-2, upper_[iSequence] - solution_[iSequence]); distance = CoinMin(solution_[iSequence] - lower_[iSequence], upper_[iSequence] - solution_[iSequence]); double merit = -distance * dj_[iSequence]; if (pivotMode2 == 1) merit = distance; if (pivotMode2 == 3) merit = fabs(dj_[iSequence]); if (merit > bestDj) { sequenceIn_ = iSequence; bestDj = merit; } } break; } } if (sequenceOut_ >= 0) { dj_[sequenceOut_] = saveDj; sequenceOut_ = -1; } if (sequenceIn_ >= 0) { array[sequenceIn_] = -dj_[sequenceIn_]; index[number++] = sequenceIn_; } } numberNonBasic = number; } else { // compute norms normUnflagged = 0.0; for (int iSequence = 0; iSequence < numberColumns_ + numberRows_; iSequence++) { if (flagged(iSequence)) { // accumulate norm switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance_) normFlagged += dj_[iSequence] * dj_[iSequence]; break; } } } // re-use list number = 0; int j; for (j = 0; j < numberNonBasic; j++) { int iSequence = index[j]; if (flagged(iSequence)) continue; switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: continue; //abort(); break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) { number++; normUnflagged += dj_[iSequence] * dj_[iSequence]; } break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) { number++; normUnflagged += dj_[iSequence] * dj_[iSequence]; } break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance_) { number++; normUnflagged += dj_[iSequence] * dj_[iSequence]; } break; } array[iSequence] = -dj_[iSequence]; } // switch to large normUnflagged = 1.0; if (!number) { for (j = 0; j < numberNonBasic; j++) { int iSequence = index[j]; array[iSequence] = 0.0; } numberNonBasic = 0; } number = numberNonBasic; } if (number) { int j; // Now do basic ones - how do I compensate for small basic infeasibilities? int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value = 0.0; if (solution_[iPivot] > upper_[iPivot]) { value = upper_[iPivot] - solution_[iPivot]; } else if (solution_[iPivot] < lower_[iPivot]) { value = lower_[iPivot] - solution_[iPivot]; } //if (value) //printf("inf %d %g %g %g\n",iPivot,lower_[iPivot],solution_[iPivot], // upper_[iPivot]); //value=0.0; value *= -1.0e0; if (value) { array[iPivot] = value; index[number++] = iPivot; } } double * array2 = spare1->denseVector(); int * index2 = spare1->getIndices(); int number2 = 0; times(-1.0, array, array2); array = array + numberColumns_; for (iRow = 0; iRow < numberRows_; iRow++) { double value = array2[iRow] + array[iRow]; if (value) { array2[iRow] = value; index2[number2++] = iRow; } else { array2[iRow] = 0.0; } } array -= numberColumns_; spare1->setNumElements(number2); // Ftran factorization_->updateColumn(spare2, spare1); number2 = spare1->getNumElements(); for (j = 0; j < number2; j++) { int iSequence = index2[j]; double value = array2[iSequence]; array2[iSequence] = 0.0; if (value) { int iPivot = pivotVariable_[iSequence]; double oldValue = array[iPivot]; if (!oldValue) { array[iPivot] = value; index[number++] = iPivot; } else { // something already there array[iPivot] = value + oldValue; } } } spare1->setNumElements(0); } vectorArray->setNumElements(number); } #define MINTYPE 1 #if MINTYPE==2 static double innerProductIndexed(const double * region1, int size, const double * region2, const int * which) { int i; double value = 0.0; for (i = 0; i < size; i++) { int j = which[i]; value += region1[j] * region2[j]; } return value; } #endif /* Row array and column array have direction Returns 0 - can do normal iteration (basis change) 1 - no basis change */ int ClpSimplexNonlinear::pivotColumn(CoinIndexedVector * longArray, CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * spare, int & pivotMode, double & solutionError, double * dArray) { // say not optimal primalColumnPivot_->setLooksOptimal(false); double acceptablePivot = 1.0e-10; int lastSequenceIn = -1; if (pivotMode && pivotMode < 10) { acceptablePivot = 1.0e-6; if (factorization_->pivots()) acceptablePivot = 1.0e-5; // if we have iterated be more strict } double acceptableBasic = 1.0e-7; int number = longArray->getNumElements(); int numberTotal = numberRows_ + numberColumns_; int bestSequence = -1; int bestBasicSequence = -1; double eps = 1.0e-1; eps = 1.0e-6; double basicTheta = 1.0e30; double objTheta = 0.0; bool finished = false; sequenceIn_ = -1; int nPasses = 0; int nTotalPasses = 0; int nBigPasses = 0; double djNorm0 = 0.0; double djNorm = 0.0; double normFlagged = 0.0; double normUnflagged = 0.0; int localPivotMode = pivotMode; bool allFinished = false; bool justOne = false; int returnCode = 1; double currentObj; double predictedObj; double thetaObj; objective_->stepLength(this, solution_, solution_, 0.0, currentObj, predictedObj, thetaObj); double saveObj = currentObj; #if MINTYPE ==2 // try Shanno's method //would be memory leak //double * saveY=new double[numberTotal]; //double * saveS=new double[numberTotal]; //double * saveY2=new double[numberTotal]; //double * saveS2=new double[numberTotal]; double saveY[100]; double saveS[100]; double saveY2[100]; double saveS2[100]; double zz[10000]; #endif double * dArray2 = dArray + numberTotal; // big big loop while (!allFinished) { double * work = longArray->denseVector(); int * which = longArray->getIndices(); allFinished = true; // CONJUGATE 0 - never, 1 as pivotMode, 2 as localPivotMode, 3 always //#define SMALLTHETA1 1.0e-25 //#define SMALLTHETA2 1.0e-25 #define SMALLTHETA1 1.0e-10 #define SMALLTHETA2 1.0e-10 #define CONJUGATE 2 #if CONJUGATE == 0 int conjugate = 0; #elif CONJUGATE == 1 int conjugate = (pivotMode < 10) ? MINTYPE : 0; #elif CONJUGATE == 2 int conjugate = MINTYPE; #else int conjugate = MINTYPE; #endif //if (pivotMode==1) //localPivotMode=11;; #if CLP_DEBUG > 1 longArray->checkClear(); #endif int numberNonBasic = 0; int startLocalMode = -1; while (!finished) { double simpleObjective = COIN_DBL_MAX; returnCode = 1; int iSequence; objective_->reducedGradient(this, dj_, false); // get direction vector in longArray longArray->clear(); // take out comment to try slightly different idea if (nPasses + nTotalPasses > 3000 || nBigPasses > 100) { if (factorization_->pivots()) returnCode = 3; break; } if (!nPasses) { numberNonBasic = 0; nBigPasses++; } // just do superbasic if in cleanup mode int local = localPivotMode; if (!local && pivotMode >= 10 && nBigPasses < 10) { local = 100; } else if (local == -1 || nBigPasses >= 10) { local = 0; localPivotMode = 0; } if (justOne) { local = 2; //local=100; justOne = false; } if (!nPasses) startLocalMode = local; directionVector(longArray, spare, rowArray, local, normFlagged, normUnflagged, numberNonBasic); { // check null vector double * rhs = spare->denseVector(); #if CLP_DEBUG > 1 spare->checkClear(); #endif int iRow; multiplyAdd(solution_ + numberColumns_, numberRows_, -1.0, rhs, 0.0); matrix_->times(1.0, solution_, rhs, rowScale_, columnScale_); double largest = 0.0; #if CLP_DEBUG > 0 int iLargest = -1; #endif for (iRow = 0; iRow < numberRows_; iRow++) { double value = fabs(rhs[iRow]); rhs[iRow] = 0.0; if (value > largest) { largest = value; #if CLP_DEBUG > 0 iLargest = iRow; #endif } } #if CLP_DEBUG > 0 if ((handler_->logLevel() & 32) && largest > 1.0e-8) printf("largest rhs error %g on row %d\n", largest, iLargest); #endif if (solutionError < 0.0) { solutionError = largest; } else if (largest > CoinMax(1.0e-8, 1.0e2 * solutionError) && factorization_->pivots()) { longArray->clear(); pivotRow_ = -1; theta_ = 0.0; return 3; } } if (sequenceIn_ >= 0) lastSequenceIn = sequenceIn_; #if MINTYPE!=2 double djNormSave = djNorm; #endif djNorm = 0.0; int iIndex; for (iIndex = 0; iIndex < numberNonBasic; iIndex++) { int iSequence = which[iIndex]; double alpha = work[iSequence]; djNorm += alpha * alpha; } // go to conjugate gradient if necessary if (numberNonBasic && localPivotMode >= 10 && (nPasses > 4 || sequenceIn_ < 0)) { localPivotMode = 0; nTotalPasses += nPasses; nPasses = 0; } #if CONJUGATE == 2 conjugate = (localPivotMode < 10) ? MINTYPE : 0; #endif //printf("bigP %d pass %d nBasic %d norm %g normI %g normF %g\n", // nBigPasses,nPasses,numberNonBasic,normUnflagged,normFlagged); if (!nPasses) { //printf("numberNon %d\n",numberNonBasic); #if MINTYPE==2 assert (numberNonBasic < 100); memset(zz, 0, numberNonBasic * numberNonBasic * sizeof(double)); int put = 0; for (int iVariable = 0; iVariable < numberNonBasic; iVariable++) { zz[put] = 1.0; put += numberNonBasic + 1; } #endif djNorm0 = CoinMax(djNorm, 1.0e-20); CoinMemcpyN(work, numberTotal, dArray); CoinMemcpyN(work, numberTotal, dArray2); if (sequenceIn_ >= 0 && numberNonBasic == 1) { // see if simple move double objTheta2 = objective_->stepLength(this, solution_, work, 1.0e30, currentObj, predictedObj, thetaObj); rowArray->clear(); // update the incoming column unpackPacked(rowArray); factorization_->updateColumnFT(spare, rowArray); theta_ = 0.0; double * work2 = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which2 = rowArray->getIndices(); int iIndex; bool easyMove = false; double way; if (dj_[sequenceIn_] > 0.0) way = -1.0; else way = 1.0; double largest = COIN_DBL_MAX; #ifdef CLP_DEBUG int kPivot = -1; #endif for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which2[iIndex]; double alpha = way * work2[iIndex]; int iPivot = pivotVariable_[iRow]; if (alpha < -1.0e-5) { double distance = upper_[iPivot] - solution_[iPivot]; if (distance < -largest * alpha) { #ifdef CLP_DEBUG kPivot = iPivot; #endif largest = CoinMax(0.0, -distance / alpha); } if (distance < -1.0e-12 * alpha) { easyMove = true; break; } } else if (alpha > 1.0e-5) { double distance = solution_[iPivot] - lower_[iPivot]; if (distance < largest * alpha) { #ifdef CLP_DEBUG kPivot = iPivot; #endif largest = CoinMax(0.0, distance / alpha); } if (distance < 1.0e-12 * alpha) { easyMove = true; break; } } } // But largest has to match up with change assert (work[sequenceIn_]); largest /= fabs(work[sequenceIn_]); if (largest < objTheta2) { easyMove = true; } else if (!easyMove) { double objDrop = currentObj - predictedObj; double th = objective_->stepLength(this, solution_, work, largest, currentObj, predictedObj, simpleObjective); simpleObjective = CoinMax(simpleObjective, predictedObj); double easyDrop = currentObj - simpleObjective; if (easyDrop > 1.0e-8 && easyDrop > 0.5 * objDrop) { easyMove = true; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("easy - obj drop %g, easy drop %g\n", objDrop, easyDrop); #endif if (easyDrop > objDrop) { // debug printf("****** th %g simple %g\n", th, simpleObjective); objective_->stepLength(this, solution_, work, 1.0e30, currentObj, predictedObj, simpleObjective); objective_->stepLength(this, solution_, work, largest, currentObj, predictedObj, simpleObjective); } } } rowArray->clear(); #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("largest %g piv %d\n", largest, kPivot); #endif if (easyMove) { valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; if (dualIn_ > 0.0) directionIn_ = -1; else directionIn_ = 1; longArray->clear(); pivotRow_ = -1; theta_ = 0.0; return 0; } } } else { #if MINTYPE==1 if (conjugate) { double djNorm2 = djNorm; if (numberNonBasic && 0) { int iIndex; djNorm2 = 0.0; for (iIndex = 0; iIndex < numberNonBasic; iIndex++) { int iSequence = which[iIndex]; double alpha = work[iSequence]; //djNorm2 += alpha*alpha; double alpha2 = work[iSequence] - dArray2[iSequence]; djNorm2 += alpha * alpha2; } //printf("a %.18g b %.18g\n",djNorm,djNorm2); } djNorm = djNorm2; double beta = djNorm2 / djNormSave; // reset beta every so often //if (numberNonBasic&&nPasses>numberNonBasic&&(nPasses%(3*numberNonBasic))==1) //beta=0.0; //printf("current norm %g, old %g - beta %g\n", // djNorm,djNormSave,beta); for (iSequence = 0; iSequence < numberTotal; iSequence++) { dArray[iSequence] = work[iSequence] + beta * dArray[iSequence]; dArray2[iSequence] = work[iSequence]; } } else { for (iSequence = 0; iSequence < numberTotal; iSequence++) dArray[iSequence] = work[iSequence]; } #else int number2 = numberNonBasic; if (number2) { // pack down into dArray int jLast = -1; for (iSequence = 0; iSequence < numberNonBasic; iSequence++) { int j = which[iSequence]; assert(j > jLast); jLast = j; double value = work[j]; dArray[iSequence] = -value; } // see whether to restart // check signs - gradient double g1 = innerProduct(dArray, number2, dArray); double g2 = innerProduct(dArray, number2, saveY2); // Get differences for (iSequence = 0; iSequence < numberNonBasic; iSequence++) { saveY2[iSequence] = dArray[iSequence] - saveY2[iSequence]; saveS2[iSequence] = solution_[iSequence] - saveS2[iSequence]; } double g3 = innerProduct(saveS2, number2, saveY2); printf("inner %g\n", g3); //assert(g3>0); double zzz[10000]; int iVariable; g2 = 1.0e50; // temp if (fabs(g2) >= 0.2 * fabs(g1)) { // restart double delta = innerProduct(saveY2, number2, saveS2) / innerProduct(saveY2, number2, saveY2); delta = 1.0; //temp memset(zz, 0, number2 * sizeof(double)); int put = 0; for (iVariable = 0; iVariable < number2; iVariable++) { zz[put] = delta; put += number2 + 1; } } else { } CoinMemcpyN(zz, number2 * number2, zzz); double ww[100]; // get sk -Hkyk for (iVariable = 0; iVariable < number2; iVariable++) { double value = 0.0; for (int jVariable = 0; jVariable < number2; jVariable++) { value += saveY2[jVariable] * zzz[iVariable+number2*jVariable]; } ww[iVariable] = saveS2[iVariable] - value; } double ys = innerProduct(saveY2, number2, saveS2); double multiplier1 = 1.0 / ys; double multiplier2 = innerProduct(saveY2, number2, ww) / (ys * ys); #if 1 // and second way // Hy double h[100]; for (iVariable = 0; iVariable < number2; iVariable++) { double value = 0.0; for (int jVariable = 0; jVariable < number2; jVariable++) { value += saveY2[jVariable] * zzz[iVariable+number2*jVariable]; } h[iVariable] = value; } double hh[10000]; double yhy1 = innerProduct(h, number2, saveY2) * multiplier1 + 1.0; yhy1 *= multiplier1; for (iVariable = 0; iVariable < number2; iVariable++) { for (int jVariable = 0; jVariable < number2; jVariable++) { int put = iVariable + number2 * jVariable; double value = zzz[put]; value += yhy1 * saveS2[iVariable] * saveS2[jVariable]; hh[put] = value; } } for (iVariable = 0; iVariable < number2; iVariable++) { for (int jVariable = 0; jVariable < number2; jVariable++) { int put = iVariable + number2 * jVariable; double value = hh[put]; value -= multiplier1 * (saveS2[iVariable] * h[jVariable]); value -= multiplier1 * (saveS2[jVariable] * h[iVariable]); hh[put] = value; } } #endif // now update H for (iVariable = 0; iVariable < number2; iVariable++) { for (int jVariable = 0; jVariable < number2; jVariable++) { int put = iVariable + number2 * jVariable; double value = zzz[put]; value += multiplier1 * (ww[iVariable] * saveS2[jVariable] + ww[jVariable] * saveS2[iVariable]); value -= multiplier2 * saveS2[iVariable] * saveS2[jVariable]; zzz[put] = value; } } //memcpy(zzz,hh,size*sizeof(double)); // do search direction memset(dArray, 0, numberTotal * sizeof(double)); for (iVariable = 0; iVariable < numberNonBasic; iVariable++) { double value = 0.0; for (int jVariable = 0; jVariable < number2; jVariable++) { int k = which[jVariable]; value += work[k] * zzz[iVariable+number2*jVariable]; } int i = which[iVariable]; dArray[i] = value; } // Now fill out dArray { int j; // Now do basic ones int iRow; CoinIndexedVector * spare1 = spare; CoinIndexedVector * spare2 = rowArray; #if CLP_DEBUG > 1 spare1->checkClear(); spare2->checkClear(); #endif double * array2 = spare1->denseVector(); int * index2 = spare1->getIndices(); int number2 = 0; times(-1.0, dArray, array2); dArray = dArray + numberColumns_; for (iRow = 0; iRow < numberRows_; iRow++) { double value = array2[iRow] + dArray[iRow]; if (value) { array2[iRow] = value; index2[number2++] = iRow; } else { array2[iRow] = 0.0; } } dArray -= numberColumns_; spare1->setNumElements(number2); // Ftran factorization_->updateColumn(spare2, spare1); number2 = spare1->getNumElements(); for (j = 0; j < number2; j++) { int iSequence = index2[j]; double value = array2[iSequence]; array2[iSequence] = 0.0; if (value) { int iPivot = pivotVariable_[iSequence]; double oldValue = dArray[iPivot]; dArray[iPivot] = value + oldValue; } } spare1->setNumElements(0); } //assert (innerProductIndexed(dArray,number2,work,which)>0); //printf ("innerP1 %g\n",innerProduct(dArray,numberTotal,work)); printf ("innerP1 %g innerP2 %g\n", innerProduct(dArray, numberTotal, work), innerProductIndexed(dArray, numberNonBasic, work, which)); assert (innerProduct(dArray, numberTotal, work) > 0); #if 1 { // check null vector int iRow; double qq[10]; memset(qq, 0, numberRows_ * sizeof(double)); multiplyAdd(dArray + numberColumns_, numberRows_, -1.0, qq, 0.0); matrix_->times(1.0, dArray, qq, rowScale_, columnScale_); double largest = 0.0; int iLargest = -1; for (iRow = 0; iRow < numberRows_; iRow++) { double value = fabs(qq[iRow]); if (value > largest) { largest = value; iLargest = iRow; } } printf("largest null error %g on row %d\n", largest, iLargest); for (iSequence = 0; iSequence < numberTotal; iSequence++) { if (getStatus(iSequence) == basic) assert (fabs(dj_[iSequence]) < 1.0e-3); } } #endif CoinMemcpyN(saveY2, numberNonBasic, saveY); CoinMemcpyN(saveS2, numberNonBasic, saveS); } #endif } #if MINTYPE==2 for (iSequence = 0; iSequence < numberNonBasic; iSequence++) { int j = which[iSequence]; saveY2[iSequence] = -work[j]; saveS2[iSequence] = solution_[j]; } #endif if (djNorm < eps * djNorm0 || (nPasses > 100 && djNorm < CoinMin(1.0e-1 * djNorm0, 1.0e-12))) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("dj norm reduced from %g to %g\n", djNorm0, djNorm); #endif if (pivotMode < 10 || !numberNonBasic) { finished = true; } else { localPivotMode = pivotMode; nTotalPasses += nPasses; nPasses = 0; continue; } } //if (nPasses==100||nPasses==50) //printf("pass %d dj norm reduced from %g to %g - flagged norm %g\n",nPasses,djNorm0,djNorm, // normFlagged); if (nPasses > 100 && djNorm < 1.0e-2 * normFlagged && !startLocalMode) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("dj norm reduced from %g to %g - flagged norm %g - unflagging\n", djNorm0, djNorm, normFlagged); #endif unflag(); localPivotMode = 0; nTotalPasses += nPasses; nPasses = 0; continue; } if (djNorm > 0.99 * djNorm0 && nPasses > 1500) { finished = true; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("dj norm NOT reduced from %g to %g\n", djNorm0, djNorm); #endif djNorm = 1.2345e-20; } number = longArray->getNumElements(); if (!numberNonBasic) { // looks optimal // check if any dj look plausible int nSuper = 0; int nFlagged = 0; int nNormal = 0; for (int iSequence = 0; iSequence < numberColumns_ + numberRows_; iSequence++) { if (flagged(iSequence)) { switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) nFlagged++; break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) nFlagged++; break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance_) nFlagged++; break; } continue; } switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance_) nNormal++; break; case atLowerBound: if (dj_[iSequence] < -dualTolerance_) nNormal++; break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance_) nSuper++; break; } } #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("%d super, %d normal, %d flagged\n", nSuper, nNormal, nFlagged); #endif int nFlagged2 = 1; if (lastSequenceIn < 0 && !nNormal && !nSuper) { nFlagged2 = unflag(); if (pivotMode >= 10) { pivotMode--; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("pivot mode now %d\n", pivotMode); #endif if (pivotMode == 9) pivotMode = 0; // switch off fast attempt } } else { lastSequenceIn = -1; } if (!nFlagged2 || (normFlagged + normUnflagged < 1.0e-8)) { primalColumnPivot_->setLooksOptimal(true); return 0; } else { localPivotMode = -1; nTotalPasses += nPasses; nPasses = 0; finished = false; continue; } } bestSequence = -1; bestBasicSequence = -1; // temp nPasses++; if (nPasses > 2000) finished = true; double theta = 1.0e30; basicTheta = 1.0e30; theta_ = 1.0e30; double basicTolerance = 1.0e-4 * primalTolerance_; for (iSequence = 0; iSequence < numberTotal; iSequence++) { //if (flagged(iSequence) // continue; double alpha = dArray[iSequence]; Status thisStatus = getStatus(iSequence); double oldValue = solution_[iSequence]; if (thisStatus != basic) { if (fabs(alpha) >= acceptablePivot) { if (alpha < 0.0) { // variable going towards lower bound double bound = lower_[iSequence]; oldValue -= bound; if (oldValue + theta * alpha < 0.0) { bestSequence = iSequence; theta = CoinMax(0.0, oldValue / (-alpha)); } } else { // variable going towards upper bound double bound = upper_[iSequence]; oldValue = bound - oldValue; if (oldValue - theta * alpha < 0.0) { bestSequence = iSequence; theta = CoinMax(0.0, oldValue / alpha); } } } } else { if (fabs(alpha) >= acceptableBasic) { if (alpha < 0.0) { // variable going towards lower bound double bound = lower_[iSequence]; oldValue -= bound; if (oldValue + basicTheta * alpha < -basicTolerance) { bestBasicSequence = iSequence; basicTheta = CoinMax(0.0, (oldValue + basicTolerance) / (-alpha)); } } else { // variable going towards upper bound double bound = upper_[iSequence]; oldValue = bound - oldValue; if (oldValue - basicTheta * alpha < -basicTolerance) { bestBasicSequence = iSequence; basicTheta = CoinMax(0.0, (oldValue + basicTolerance) / alpha); } } } } } theta_ = CoinMin(theta, basicTheta); // Now find minimum of function double objTheta2 = objective_->stepLength(this, solution_, dArray, CoinMin(theta, basicTheta), currentObj, predictedObj, thetaObj); #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("current obj %g thetaObj %g, predictedObj %g\n", currentObj, thetaObj, predictedObj); #endif objTheta2=CoinMin(objTheta2,1.0e29); #if MINTYPE==1 if (conjugate) { double offset; const double * gradient = objective_->gradient(this, dArray, offset, true, 0); double product = 0.0; for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double alpha = dArray[iSequence]; double value = alpha * gradient[iSequence]; product += value; } //#define INCLUDESLACK #ifdef INCLUDESLACK for (; iSequence < numberColumns_ + numberRows_; iSequence++) { double alpha = dArray[iSequence]; double value = alpha * cost_[iSequence]; product += value; } #endif if (product > 0.0) objTheta = djNorm / product; else objTheta = COIN_DBL_MAX; #ifndef NDEBUG if (product < -1.0e-8 && handler_->logLevel() > 1) printf("bad product %g\n", product); #endif product = CoinMax(product, 0.0); } else { objTheta = objTheta2; } #else objTheta = objTheta2; #endif // if very small difference then take pivot (depends on djNorm?) // distinguish between basic and non-basic bool chooseObjTheta = objTheta < theta_; if (chooseObjTheta) { if (thetaObj < currentObj - 1.0e-12 && objTheta + 1.0e-10 > theta_) chooseObjTheta = false; //if (thetaObjtheta_) //chooseObjTheta=false; } //if (objTheta+SMALLTHETA1currentObj+difference&&objThetabasicTheta) { //theta = CoinMax(theta,1.00000001*basicTheta); //theta_ = basicTheta; //} } // always out if one variable in and zero move if (theta_ == basicTheta || (sequenceIn_ >= 0 && theta_ < 1.0e-10)) finished = true; // come out #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { printf("%d pass,", nPasses); if (sequenceIn_ >= 0) printf (" Sin %d,", sequenceIn_); if (basicTheta == theta_) printf(" X(%d) basicTheta %g", bestBasicSequence, basicTheta); else printf(" basicTheta %g", basicTheta); if (theta == theta_) printf(" X(%d) non-basicTheta %g", bestSequence, theta); else printf(" non-basicTheta %g", theta); printf(" %s objTheta %g", objTheta == theta_ ? "X" : "", objTheta); printf(" djNorm %g\n", djNorm); } #endif if (handler_->logLevel() > 3 && objTheta != theta_) { printf("%d pass obj %g,", nPasses, currentObj); if (sequenceIn_ >= 0) printf (" Sin %d,", sequenceIn_); if (basicTheta == theta_) printf(" X(%d) basicTheta %g", bestBasicSequence, basicTheta); else printf(" basicTheta %g", basicTheta); if (theta == theta_) printf(" X(%d) non-basicTheta %g", bestSequence, theta); else printf(" non-basicTheta %g", theta); printf(" %s objTheta %g", objTheta == theta_ ? "X" : "", objTheta); printf(" djNorm %g\n", djNorm); } if (objTheta != theta_) { //printf("hit boundary after %d passes\n",nPasses); nTotalPasses += nPasses; nPasses = 0; // start again } if (localPivotMode < 10 || lastSequenceIn == bestSequence) { if (theta_ == theta && theta_ < basicTheta && theta_ < 1.0e-5) setFlagged(bestSequence); // out of active set } // Update solution for (iSequence = 0; iSequence < numberTotal; iSequence++) { //for (iIndex=0;iIndexsetOne(iSequence, value); break; case superBasic: // To get correct action setStatus(iSequence, isFixed); nonLinearCost_->setOne(iSequence, value); //assert (getStatus(iSequence)!=isFixed); break; } } } if (objTheta < SMALLTHETA2 && objTheta == theta_) { if (sequenceIn_ >= 0 && basicTheta < 1.0e-9) { // try just one localPivotMode = 0; sequenceIn_ = -1; nTotalPasses += nPasses; nPasses = 0; //finished=true; //objTheta=0.0; //theta_=0.0; } else if (sequenceIn_ < 0 && nTotalPasses > 10) { if (objTheta < 1.0e-10) { finished = true; //printf("zero move\n"); break; } } } #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { objective_->stepLength(this, solution_, work, 0.0, currentObj, predictedObj, thetaObj); printf("current obj %g after update - simple was %g\n", currentObj, simpleObjective); } #endif if (sequenceIn_ >= 0 && !finished && objTheta > 1.0e-4) { // we made some progress - back to normal if (localPivotMode < 10) { localPivotMode = 0; sequenceIn_ = -1; nTotalPasses += nPasses; nPasses = 0; } #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("some progress?\n"); #endif } #if CLP_DEBUG > 1 longArray->checkClean(); #endif } #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("out of loop after %d (%d) passes\n", nPasses, nTotalPasses); #endif if (nTotalPasses >= 1000 || (nTotalPasses > 10 && sequenceIn_ < 0 && theta_ < 1.0e-10)) returnCode = 2; bool ordinaryDj = false; //if(sequenceIn_>=0&&numberNonBasic==1&&theta_<1.0e-7&&theta_==basicTheta) //printf("could try ordinary iteration %g\n",theta_); if(sequenceIn_ >= 0 && numberNonBasic == 1 && theta_ < 1.0e-15) { //printf("trying ordinary iteration\n"); ordinaryDj = true; } if (!basicTheta && !ordinaryDj) { //returnCode=2; //objTheta=-1.0; // so we fall through } assert (theta_ < 1.0e30); // for now // See if we need to pivot if (theta_ == basicTheta || ordinaryDj) { if (!ordinaryDj) { // find an incoming column which will force pivot int iRow; pivotRow_ = -1; for (iRow = 0; iRow < numberRows_; iRow++) { if (pivotVariable_[iRow] == bestBasicSequence) { pivotRow_ = iRow; break; } } assert (pivotRow_ >= 0); // Get good size for pivot double acceptablePivot = 1.0e-7; if (factorization_->pivots() > 10) acceptablePivot = 1.0e-5; // if we have iterated be more strict else if (factorization_->pivots() > 5) acceptablePivot = 1.0e-6; // if we have iterated be slightly more strict // should be dArray but seems better this way! double direction = work[bestBasicSequence] > 0.0 ? -1.0 : 1.0; // create as packed rowArray->createPacked(1, &pivotRow_, &direction); factorization_->updateColumnTranspose(spare, rowArray); // put row of tableau in rowArray and columnArray matrix_->transposeTimes(this, -1.0, rowArray, spare, columnArray); // choose one futhest away from bound which has reasonable pivot // If increasing we want negative alpha double * work2; int iSection; sequenceIn_ = -1; double bestValue = -1.0; double bestDirection = 0.0; // First pass we take correct direction and large pivots // then correct direction // then any double check[] = {1.0e-8, -1.0e-12, -1.0e30}; double mult[] = {100.0, 1.0, 1.0}; for (int iPass = 0; iPass < 3; iPass++) { //if (!bestValue&&iPass==2) //bestValue=-1.0; double acceptable = acceptablePivot * mult[iPass]; double checkValue = check[iPass]; for (iSection = 0; iSection < 2; iSection++) { int addSequence; if (!iSection) { work2 = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { work2 = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } int i; for (i = 0; i < number; i++) { int iSequence = which[i] + addSequence; if (flagged(iSequence)) continue; //double distance = CoinMin(solution_[iSequence]-lower_[iSequence], // upper_[iSequence]-solution_[iSequence]); double alpha = work2[i]; // should be dArray but seems better this way! double change = work[iSequence]; Status thisStatus = getStatus(iSequence); double direction = 0;; switch(thisStatus) { case basic: case ClpSimplex::isFixed: break; case isFree: case superBasic: if (alpha < -acceptable && change > checkValue) direction = 1.0; else if (alpha > acceptable && change < -checkValue) direction = -1.0; break; case atUpperBound: if (alpha > acceptable && change < -checkValue) direction = -1.0; else if (iPass == 2 && alpha < -acceptable && change < -checkValue) direction = 1.0; break; case atLowerBound: if (alpha < -acceptable && change > checkValue) direction = 1.0; else if (iPass == 2 && alpha > acceptable && change > checkValue) direction = -1.0; break; } if (direction) { if (sequenceIn_ != lastSequenceIn || localPivotMode < 10) { if (CoinMin(solution_[iSequence] - lower_[iSequence], upper_[iSequence] - solution_[iSequence]) > bestValue) { bestValue = CoinMin(solution_[iSequence] - lower_[iSequence], upper_[iSequence] - solution_[iSequence]); sequenceIn_ = iSequence; bestDirection = direction; } } else { // choose bestValue = COIN_DBL_MAX; sequenceIn_ = iSequence; bestDirection = direction; } } } } if (sequenceIn_ >= 0 && bestValue > 0.0) break; } if (sequenceIn_ >= 0) { valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (bestDirection < 0.0) { // we want positive dj if (dualIn_ <= 0.0) { //printf("bad dj - xx %g\n",dualIn_); dualIn_ = 1.0; } } else { // we want negative dj if (dualIn_ >= 0.0) { //printf("bad dj - xx %g\n",dualIn_); dualIn_ = -1.0; } } lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; if (dualIn_ > 0.0) directionIn_ = -1; else directionIn_ = 1; } else { //ordinaryDj=true; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { printf("no easy pivot - norm %g mode %d\n", djNorm, localPivotMode); if (rowArray->getNumElements() + columnArray->getNumElements() < 12) { for (iSection = 0; iSection < 2; iSection++) { int addSequence; if (!iSection) { work2 = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { work2 = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } int i; char section[] = {'R', 'C'}; for (i = 0; i < number; i++) { int iSequence = which[i] + addSequence; if (flagged(iSequence)) { printf("%c%d flagged\n", section[iSection], which[i]); continue; } else { printf("%c%d status %d sol %g %g %g alpha %g change %g\n", section[iSection], which[i], status_[iSequence], lower_[iSequence], solution_[iSequence], upper_[iSequence], work2[i], work[iSequence]); } } } } } #endif assert (sequenceIn_ < 0); justOne = true; allFinished = false; // Round again finished = false; nTotalPasses += nPasses; nPasses = 0; if (djNorm < 0.9 * djNorm0 && djNorm < 1.0e-3 && !localPivotMode) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("no pivot - mode %d norms %g %g - unflagging\n", localPivotMode, djNorm0, djNorm); #endif unflag(); //unflagging returnCode = 1; } else { returnCode = 2; // do single incoming returnCode = 1; } } } rowArray->clear(); columnArray->clear(); longArray->clear(); if (ordinaryDj) { valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; if (dualIn_ > 0.0) directionIn_ = -1; else directionIn_ = 1; } if (returnCode == 1) returnCode = 0; } else { // round again longArray->clear(); if (djNorm < 1.0e-3 && !localPivotMode) { if (djNorm == 1.2345e-20 && djNorm0 > 1.0e-4) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("slow convergence djNorm0 %g, %d passes, mode %d, result %d\n", djNorm0, nPasses, localPivotMode, returnCode); #endif //if (!localPivotMode) //returnCode=2; // force singleton } else { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("unflagging as djNorm %g %g, %d passes\n", djNorm, djNorm0, nPasses); #endif if (pivotMode >= 10) { pivotMode--; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("pivot mode now %d\n", pivotMode); #endif if (pivotMode == 9) pivotMode = 0; // switch off fast attempt } bool unflagged = unflag() != 0; if (!unflagged && djNorm < 1.0e-10) { // ? declare victory sequenceIn_ = -1; returnCode = 0; } } } } } if (djNorm0 < 1.0e-12 * normFlagged) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("unflagging as djNorm %g %g and flagged norm %g\n", djNorm, djNorm0, normFlagged); #endif unflag(); } if (saveObj - currentObj < 1.0e-5 && nTotalPasses > 2000) { normUnflagged = 0.0; double dualTolerance3 = CoinMin(1.0e-2, 1.0e3 * dualTolerance_); for (int iSequence = 0; iSequence < numberColumns_ + numberRows_; iSequence++) { switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case atUpperBound: if (dj_[iSequence] > dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case atLowerBound: if (dj_[iSequence] < -dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; case isFree: case superBasic: if (fabs(dj_[iSequence]) > dualTolerance3) normFlagged += dj_[iSequence] * dj_[iSequence]; break; } } if (handler_->logLevel() > 2) printf("possible optimal %d %d %g %g\n", nBigPasses, nTotalPasses, saveObj - currentObj, normFlagged); if (normFlagged < 1.0e-5) { unflag(); primalColumnPivot_->setLooksOptimal(true); returnCode = 0; } } return returnCode; } /* Do last half of an iteration. Return codes Reasons to come out normal mode -1 normal -2 factorize now - good iteration -3 slight inaccuracy - refactorize - iteration done -4 inaccuracy - refactorize - no iteration -5 something flagged - go round again +2 looks unbounded +3 max iterations (iteration done) */ int ClpSimplexNonlinear::pivotNonlinearResult() { int returnCode = -1; rowArray_[1]->clear(); // we found a pivot column // update the incoming column unpackPacked(rowArray_[1]); factorization_->updateColumnFT(rowArray_[2], rowArray_[1]); theta_ = 0.0; double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); bool keepValue = false; double saveValue = 0.0; if (pivotRow_ >= 0) { sequenceOut_ = pivotVariable_[pivotRow_];; valueOut_ = solution(sequenceOut_); keepValue = true; saveValue = valueOut_; lowerOut_ = lower_[sequenceOut_]; upperOut_ = upper_[sequenceOut_]; int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; if (iRow == pivotRow_) { alpha_ = work[iIndex]; break; } } } else { int iIndex; double smallest = COIN_DBL_MAX; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; if (fabs(alpha) > 1.0e-6) { int iPivot = pivotVariable_[iRow]; double distance = CoinMin(upper_[iPivot] - solution_[iPivot], solution_[iPivot] - lower_[iPivot]); if (distance < smallest) { pivotRow_ = iRow; alpha_ = alpha; smallest = distance; } } } if (smallest > primalTolerance_) { smallest = COIN_DBL_MAX; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iIndex]; if (fabs(alpha) > 1.0e-6) { double distance = randomNumberGenerator_.randomDouble(); if (distance < smallest) { pivotRow_ = iRow; alpha_ = alpha; smallest = distance; } } } } assert (pivotRow_ >= 0); sequenceOut_ = pivotVariable_[pivotRow_];; valueOut_ = solution(sequenceOut_); lowerOut_ = lower_[sequenceOut_]; upperOut_ = upper_[sequenceOut_]; } double newValue = valueOut_ - theta_ * alpha_; bool isSuperBasic = false; if (valueOut_ >= upperOut_ - primalTolerance_) { directionOut_ = -1; // to upper bound upperOut_ = nonLinearCost_->nearest(sequenceOut_, newValue); upperOut_ = newValue; } else if (valueOut_ <= lowerOut_ + primalTolerance_) { directionOut_ = 1; // to lower bound lowerOut_ = nonLinearCost_->nearest(sequenceOut_, newValue); } else { lowerOut_ = valueOut_; upperOut_ = valueOut_; isSuperBasic = true; //printf("XX superbasic out\n"); } dualOut_ = dj_[sequenceOut_]; // if stable replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_); // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { returnCode = -3; } } else if (updateStatus == 2) { // major error // better to have small tolerance even if slower factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15)); int maxFactor = factorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); } // later we may need to unwind more e.g. fake bounds if(lastGoodIteration_ != numberIterations_) { clearAll(); pivotRow_ = -1; returnCode = -4; } else { // need to reject something char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; sequenceOut_ = -1; returnCode = -5; } return returnCode; } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); returnCode = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } // update primal solution double objectiveChange = 0.0; // after this rowArray_[1] is not empty - used to update djs // If pivot row >= numberRows then may be gub updatePrimalsInPrimal(rowArray_[1], theta_, objectiveChange, 1); double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ -= fabs(theta_); } else { valueIn_ = lowerIn_; } } else { // as if from lower bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ += fabs(theta_); } else { valueIn_ = upperIn_; } } objectiveChange += dualIn_ * (valueIn_ - oldValue); // outgoing if (sequenceIn_ != sequenceOut_) { if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } if(valueOut_ < lower_[sequenceOut_] - primalTolerance_) valueOut_ = lower_[sequenceOut_] - 0.9 * primalTolerance_; else if (valueOut_ > upper_[sequenceOut_] + primalTolerance_) valueOut_ = upper_[sequenceOut_] + 0.9 * primalTolerance_; // may not be exactly at bound and bounds may have changed // Make sure outgoing looks feasible if (!isSuperBasic) directionOut_ = nonLinearCost_->setOneOutgoing(sequenceOut_, valueOut_); solution_[sequenceOut_] = valueOut_; } // change cost and bounds on incoming if primal nonLinearCost_->setOne(sequenceIn_, valueIn_); int whatNext = housekeeping(objectiveChange); if (keepValue) solution_[sequenceOut_] = saveValue; if (isSuperBasic) setStatus(sequenceOut_, superBasic); //#define CLP_DEBUG #if CLP_DEBUG > 1 { int ninf = matrix_->checkFeasible(this); if (ninf) printf("infeas %d\n", ninf); } #endif if (whatNext == 1) { returnCode = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent returnCode = 3; } else if(numberIterations_ == lastGoodIteration_ + 2 * factorization_->maximumPivots()) { // done a lot of flips - be safe returnCode = -2; // refactorize } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 4; } } return returnCode; } // A sequential LP method int ClpSimplexNonlinear::primalSLP(int numberPasses, double deltaTolerance) { // Are we minimizing or maximizing double whichWay = optimizationDirection(); if (whichWay < 0.0) whichWay = -1.0; else if (whichWay > 0.0) whichWay = 1.0; int numberColumns = this->numberColumns(); int numberRows = this->numberRows(); double * columnLower = this->columnLower(); double * columnUpper = this->columnUpper(); double * solution = this->primalColumnSolution(); if (objective_->type() < 2) { // no nonlinear part return ClpSimplex::primal(0); } // Get list of non linear columns char * markNonlinear = new char[numberColumns]; memset(markNonlinear, 0, numberColumns); int numberNonLinearColumns = objective_->markNonlinear(markNonlinear); if (!numberNonLinearColumns) { delete [] markNonlinear; // no nonlinear part return ClpSimplex::primal(0); } int iColumn; int * listNonLinearColumn = new int[numberNonLinearColumns]; numberNonLinearColumns = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if(markNonlinear[iColumn]) listNonLinearColumn[numberNonLinearColumns++] = iColumn; } // Replace objective ClpObjective * trueObjective = objective_; objective_ = new ClpLinearObjective(NULL, numberColumns); double * objective = this->objective(); // get feasible if (this->status() < 0 || numberPrimalInfeasibilities()) ClpSimplex::primal(1); // still infeasible if (numberPrimalInfeasibilities()) { delete [] listNonLinearColumn; return 0; } algorithm_ = 1; int jNon; int * last[3]; double * trust = new double[numberNonLinearColumns]; double * trueLower = new double[numberNonLinearColumns]; double * trueUpper = new double[numberNonLinearColumns]; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; trust[jNon] = 0.5; trueLower[jNon] = columnLower[iColumn]; trueUpper[jNon] = columnUpper[iColumn]; if (solution[iColumn] < trueLower[jNon]) solution[iColumn] = trueLower[jNon]; else if (solution[iColumn] > trueUpper[jNon]) solution[iColumn] = trueUpper[jNon]; } int saveLogLevel = logLevel(); 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]; #define MULTIPLE 0 #if MULTIPLE>2 // Duplication but doesn't really matter double * saveSolutionM[MULTIPLE }; for (jNon=0; jNonnewXValues(); double theta = -1.0; double maxTheta = COIN_DBL_MAX; //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)); times(1.0, solution, rowActivity_); memset(saveRowSolution, 0, numberRows_ * sizeof(double)); 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]; } CoinMemcpyN(rowActivity_, numberRows, saveRowSolution); } // get current value anyway double predictedObj, thetaObj; double maxTheta2 = 2.0; // to work out a b c double theta2 = trueObjective->stepLength(this, saveSolution, changeRegion, maxTheta2, objValue, predictedObj, thetaObj); int lastMoveStatus = goodMove; if (goodMove >= 0) { theta = CoinMin(theta2, maxTheta); #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("theta %g, current %g, at maxtheta %g, predicted %g\n", theta, objValue, thetaObj, predictedObj); #endif 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)); times(1.0, solution, rowActivity_); if (lambda > 0.999) { CoinMemcpyN(savePi, numberRows, this->dualRowSolution()); CoinMemcpyN(saveStatus, numberRows + numberColumns, status_); } // Do local minimization #define LOCAL #ifdef LOCAL bool absolutelyOptimal = false; int saveScaling = scalingFlag(); scaling(0); int savePerturbation = perturbation_; perturbation_ = 100; if (saveLogLevel == 1) setLogLevel(0); int status = startup(1); if (!status) { int numberTotal = numberRows_ + numberColumns_; // resize arrays for (int i = 0; i < 4; i++) { rowArray_[i]->reserve(CoinMax(numberRows_ + numberColumns_, rowArray_[i]->capacity())); } CoinIndexedVector * longArray = rowArray_[3]; CoinIndexedVector * rowArray = rowArray_[0]; //CoinIndexedVector * columnArray = columnArray_[0]; CoinIndexedVector * spare = rowArray_[1]; double * work = longArray->denseVector(); int * which = longArray->getIndices(); int nPass = 100; //bool conjugate=false; // Put back true bounds for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { int iColumn = listNonLinearColumn[jNon]; double value; value = trueLower[jNon]; trueLower[jNon] = lower_[iColumn]; lower_[iColumn] = value; value = trueUpper[jNon]; trueUpper[jNon] = upper_[iColumn]; upper_[iColumn] = value; switch(getStatus(iColumn)) { case basic: case isFree: case superBasic: break; case isFixed: case atUpperBound: case atLowerBound: if (solution_[iColumn] > lower_[iColumn] + primalTolerance_) { if(solution_[iColumn] < upper_[iColumn] - primalTolerance_) { setStatus(iColumn, superBasic); } else { setStatus(iColumn, atUpperBound); } } else { if(solution_[iColumn] < upper_[iColumn] - primalTolerance_) { setStatus(iColumn, atLowerBound); } else { setStatus(iColumn, isFixed); } } break; } } for (int jPass = 0; jPass < nPass; jPass++) { trueObjective->reducedGradient(this, dj_, true); // get direction vector in longArray longArray->clear(); double normFlagged = 0.0; double normUnflagged = 0.0; int numberNonBasic = 0; directionVector(longArray, spare, rowArray, 0, normFlagged, normUnflagged, numberNonBasic); if (normFlagged + normUnflagged < 1.0e-8) { absolutelyOptimal = true; break; //looks optimal } double djNorm = 0.0; int iIndex; for (iIndex = 0; iIndex < numberNonBasic; iIndex++) { int iSequence = which[iIndex]; double alpha = work[iSequence]; djNorm += alpha * alpha; } //if (!jPass) //printf("dj norm %g - %d \n",djNorm,numberNonBasic); //int number=longArray->getNumElements(); if (!numberNonBasic) { // looks optimal absolutelyOptimal = true; break; } double theta = 1.0e30; int iSequence; for (iSequence = 0; iSequence < numberTotal; iSequence++) { double alpha = work[iSequence]; double oldValue = solution_[iSequence]; if (alpha < -1.0e-15) { // variable going towards lower bound double bound = lower_[iSequence]; oldValue -= bound; if (oldValue + theta * alpha < 0.0) { theta = CoinMax(0.0, oldValue / (-alpha)); } } else if (alpha > 1.0e-15) { // variable going towards upper bound double bound = upper_[iSequence]; oldValue = bound - oldValue; if (oldValue - theta * alpha < 0.0) { theta = CoinMax(0.0, oldValue / alpha); } } } // Now find minimum of function double currentObj; double predictedObj; double thetaObj; // need to use true objective double * saveCost = cost_; cost_ = NULL; double objTheta = trueObjective->stepLength(this, solution_, work, theta, currentObj, predictedObj, thetaObj); cost_ = saveCost; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("current obj %g thetaObj %g, predictedObj %g\n", currentObj, thetaObj, predictedObj); #endif //printf("current obj %g thetaObj %g, predictedObj %g\n",currentObj,thetaObj,predictedObj); //printf("objTheta %g theta %g\n",objTheta,theta); if (theta > objTheta) { theta = objTheta; thetaObj = predictedObj; } // update one used outside objValue = currentObj; if (theta > 1.0e-9 && (currentObj - thetaObj < -CoinMax(1.0e-8, 1.0e-15 * fabs(currentObj)) || jPass < 5)) { // Update solution for (iSequence = 0; iSequence < numberTotal; iSequence++) { double alpha = work[iSequence]; if (alpha) { double value = solution_[iSequence] + theta * alpha; solution_[iSequence] = value; switch(getStatus(iSequence)) { case basic: case isFixed: case isFree: break; case atUpperBound: case atLowerBound: case superBasic: if (value > lower_[iSequence] + primalTolerance_) { if(value < upper_[iSequence] - primalTolerance_) { setStatus(iSequence, superBasic); } else { setStatus(iSequence, atUpperBound); } } else { if(value < upper_[iSequence] - primalTolerance_) { setStatus(iSequence, atLowerBound); } else { setStatus(iSequence, isFixed); } } break; } } } } else { break; } } // Put back fake bounds for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { int iColumn = listNonLinearColumn[jNon]; double value; value = trueLower[jNon]; trueLower[jNon] = lower_[iColumn]; lower_[iColumn] = value; value = trueUpper[jNon]; trueUpper[jNon] = upper_[iColumn]; upper_[iColumn] = value; } } problemStatus_ = 0; finish(); scaling(saveScaling); perturbation_ = savePerturbation; setLogLevel(saveLogLevel); #endif // redo rowActivity memset(rowActivity_, 0, numberRows_ * sizeof(double)); times(1.0, solution, rowActivity_); if (theta > 0.99999 && theta2 < 1.9 && !absolutelyOptimal) { // If big changes then tighten /* thetaObj is objvalue + a*2*2 +b*2 predictedObj is objvalue + a*theta2*theta2 +b*theta2 */ double rhs1 = thetaObj - objValue; double rhs2 = predictedObj - objValue; double subtractB = theta2 * 0.5; double a = (rhs2 - subtractB * rhs1) / (theta2 * theta2 - 4.0 * subtractB); double b = 0.5 * (rhs1 - 4.0 * a); if (fabs(a + b) > 1.0e-2) { // tighten all goodMove = -1; } } } } CoinMemcpyN(trueObjective->gradient(this, solution, offset, true, 2), numberColumns, objective); //printf("offset comp %g orig %g\n",offset,objectiveOffset); // could do faster trueObjective->stepLength(this, solution, changeRegion, 0.0, objValue, predictedObj, thetaObj); #ifdef CLP_INVESTIGATE printf("offset comp %g orig %g - obj from stepLength %g\n", offset, objectiveOffset, objValue); #endif setDblParam(ClpObjOffset, objectiveOffset + offset); 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 (handler_->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; } if(lastMoveStatus == -1 && goodMove == -1) goodMove = 1; // to force solve if (goodMove > 0) { double drop = lastObjective - objValue; handler_->message(CLP_SLP_ITER, messages_) << iPass << objValue - objectiveOffset << drop << maxDelta << CoinMessageEol; if (iPass > 20 && drop < 1.0e-12 * fabs(objValue)) drop = 0.999e-4; // so will exit if (maxDelta < deltaTolerance && drop < 1.0e-4 && goodMove && theta < 0.99999) { if (handler_->logLevel() > 1) std::cout << "Exiting as maxDelta < tolerance and small drop" << std::endl; break; } } else if (!numberSmaller && iPass > 1) { if (handler_->logLevel() > 1) std::cout << "Exiting as all gaps small" << std::endl; break; } if (!iPass) goodMove = 1; targetDrop = 0.0; double * r = this->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 this->matrix()->transposeTimes(savePi, this->dualColumnSolution()); 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)); } #if 0 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) { CoinMemcpyN(solution, numberColumns, saveSolution); CoinMemcpyN(rowActivity_, numberRows, saveRowSolution); CoinMemcpyN(this->dualRowSolution(), numberRows, savePi); CoinMemcpyN(status_, numberRows + numberColumns, saveStatus); #if MULTIPLE>2 double * tempSol = saveSolutionM[0]; for (jNon = 0; jNon < MULTIPLE - 1; jNon++) { saveSolutionM[jNon] = saveSolutionM[jNon+1]; } saveSolutionM[MULTIPLE-1] = tempSol; CoinMemcpyN(solution, numberColumns, tempSol); #endif #ifdef CLP_DEBUG if (handler_->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))) && goodMove && iPass > 3) { if (handler_->logLevel() > 1) printf("Exiting on target drop %g\n", targetDrop); break; } #ifdef CLP_DEBUG { double * r = this->dualColumnSolution(); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; if (handler_->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 //setLogLevel(63); this->scaling(false); if (saveLogLevel == 1) setLogLevel(0); ClpSimplex::primal(1); algorithm_ = 1; setLogLevel(saveLogLevel); #ifdef CLP_DEBUG if (this->status()) { writeMps("xx.mps"); } #endif if (this->status() == 1) { // not feasible ! - backtrack and exit // use safe solution CoinMemcpyN(safeSolution, numberColumns, solution); CoinMemcpyN(solution, numberColumns, saveSolution); memset(rowActivity_, 0, numberRows_ * sizeof(double)); times(1.0, solution, rowActivity_); CoinMemcpyN(rowActivity_, numberRows, saveRowSolution); CoinMemcpyN(savePi, numberRows, this->dualRowSolution()); CoinMemcpyN(saveStatus, numberRows + numberColumns, status_); 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 CoinMemcpyN(solution, numberColumns, safeSolution); } if (problemStatus_ == 3) break; // probably user interrupt goodMove = 1; } else { // bad pass - restore solution #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("Backtracking\n"); #endif CoinMemcpyN(saveSolution, numberColumns, solution); CoinMemcpyN(saveRowSolution, numberRows, rowActivity_); CoinMemcpyN(savePi, numberRows, this->dualRowSolution()); CoinMemcpyN(saveStatus, numberRows + numberColumns, status_); iPass--; assert (exitPass > 0); goodMove = -1; } } #if MULTIPLE>2 for (jNon = 0; jNon < MULTIPLE; jNon++) { delete [] saveSolutionM[jNon]; } #endif // restore solution CoinMemcpyN(saveSolution, numberColumns, solution); CoinMemcpyN(saveRowSolution, numberRows, rowActivity_); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = CoinMax(solution[iColumn], trueLower[jNon]); columnUpper[iColumn] = CoinMin(solution[iColumn], trueUpper[jNon]); } delete [] markNonlinear; delete [] statusCheck; delete [] savePi; delete [] saveStatus; // redo objective CoinMemcpyN(trueObjective->gradient(this, solution, offset, true, 2), numberColumns, objective); ClpSimplex::primal(1); delete objective_; objective_ = trueObjective; // redo values setDblParam(ClpObjOffset, objectiveOffset); objectiveValue_ += whichWay * offset; 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 [] listNonLinearColumn; delete [] changeRegion; // temp //setLogLevel(63); return 0; } /* Primal algorithm for nonlinear constraints Using a semi-trust region approach as for pooling problem This is in because I have it lying around */ int ClpSimplexNonlinear::primalSLP(int numberConstraints, ClpConstraint ** constraints, int numberPasses, double deltaTolerance) { if (!numberConstraints) { // no nonlinear constraints - may be nonlinear objective return primalSLP(numberPasses, deltaTolerance); } // Are we minimizing or maximizing double whichWay = optimizationDirection(); if (whichWay < 0.0) whichWay = -1.0; else if (whichWay > 0.0) whichWay = 1.0; // check all matrix for odd rows is empty int iConstraint; int numberBad = 0; CoinPackedMatrix * columnCopy = matrix(); // Get a row copy in standard format CoinPackedMatrix copy; copy.reverseOrderedCopyOf(*columnCopy); // get matrix data pointers //const int * column = copy.getIndices(); //const CoinBigIndex * rowStart = copy.getVectorStarts(); const int * rowLength = copy.getVectorLengths(); //const double * elementByRow = copy.getElements(); int numberArtificials = 0; // We could use nonlinearcost to do segments - maybe later #define SEGMENTS 3 // Penalties may be adjusted by duals // Both these should be modified depending on problem // Possibly start with big bounds //double penalties[]={1.0e-3,1.0e7,1.0e9}; double penalties[] = {1.0e7, 1.0e8, 1.0e9}; double bounds[] = {1.0e-2, 1.0e2, COIN_DBL_MAX}; // see how many extra we need CoinBigIndex numberExtra = 0; for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; int iRow = constraint->rowNumber(); assert (iRow >= 0); int n = constraint->numberCoefficients() - rowLength[iRow]; numberExtra += n; if (iRow >= numberRows_) numberBad++; else if (rowLength[iRow] && n) numberBad++; if (rowLower_[iRow] > -1.0e20) numberArtificials++; if (rowUpper_[iRow] < 1.0e20) numberArtificials++; } if (numberBad) return numberBad; ClpObjective * trueObjective = NULL; if (objective_->type() >= 2) { // Replace objective trueObjective = objective_; objective_ = new ClpLinearObjective(NULL, numberColumns_); } ClpSimplex newModel(*this); // we can put back true objective if (trueObjective) { // Replace objective delete objective_; objective_ = trueObjective; } int numberColumns2 = numberColumns_; int numberSmallGap = numberArtificials; if (numberArtificials) { numberArtificials *= SEGMENTS; numberColumns2 += numberArtificials; int * addStarts = new int [numberArtificials+1]; int * addRow = new int[numberArtificials]; double * addElement = new double[numberArtificials]; double * addUpper = new double[numberArtificials]; addStarts[0] = 0; double * addCost = new double [numberArtificials]; numberArtificials = 0; for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; int iRow = constraint->rowNumber(); if (rowLower_[iRow] > -1.0e20) { for (int k = 0; k < SEGMENTS; k++) { addRow[numberArtificials] = iRow; addElement[numberArtificials] = 1.0; addCost[numberArtificials] = penalties[k]; addUpper[numberArtificials] = bounds[k]; numberArtificials++; addStarts[numberArtificials] = numberArtificials; } } if (rowUpper_[iRow] < 1.0e20) { for (int k = 0; k < SEGMENTS; k++) { addRow[numberArtificials] = iRow; addElement[numberArtificials] = -1.0; addCost[numberArtificials] = penalties[k]; addUpper[numberArtificials] = bounds[k]; numberArtificials++; addStarts[numberArtificials] = numberArtificials; } } } newModel.addColumns(numberArtificials, NULL, addUpper, addCost, addStarts, addRow, addElement); delete [] addStarts; delete [] addRow; delete [] addElement; delete [] addUpper; delete [] addCost; // newModel.primal(1); } // find nonlinear columns int * listNonLinearColumn = new int [numberColumns_+numberSmallGap]; char * mark = new char[numberColumns_]; memset(mark, 0, numberColumns_); for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; constraint->markNonlinear(mark); } if (trueObjective) trueObjective->markNonlinear(mark); int iColumn; int numberNonLinearColumns = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (mark[iColumn]) listNonLinearColumn[numberNonLinearColumns++] = iColumn; } // and small gap artificials for (iColumn = numberColumns_; iColumn < numberColumns2; iColumn += SEGMENTS) { listNonLinearColumn[numberNonLinearColumns++] = iColumn; } // build row copy of matrix with space for nonzeros // Get column copy columnCopy = newModel.matrix(); copy.reverseOrderedCopyOf(*columnCopy); // get matrix data pointers const int * column = copy.getIndices(); const CoinBigIndex * rowStart = copy.getVectorStarts(); rowLength = copy.getVectorLengths(); const double * elementByRow = copy.getElements(); numberExtra += copy.getNumElements(); CoinBigIndex * newStarts = new CoinBigIndex [numberRows_+1]; int * newColumn = new int[numberExtra]; double * newElement = new double[numberExtra]; newStarts[0] = 0; int * backRow = new int [numberRows_]; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) backRow[iRow] = -1; for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; iRow = constraint->rowNumber(); backRow[iRow] = iConstraint; } numberExtra = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (backRow[iRow] < 0) { // copy normal for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { newColumn[numberExtra] = column[j]; newElement[numberExtra++] = elementByRow[j]; } } else { ClpConstraint * constraint = constraints[backRow[iRow]]; assert(iRow == constraint->rowNumber()); int numberArtificials = 0; if (rowLower_[iRow] > -1.0e20) numberArtificials += SEGMENTS; if (rowUpper_[iRow] < 1.0e20) numberArtificials += SEGMENTS; if (numberArtificials == rowLength[iRow]) { // all possible memset(mark, 0, numberColumns_); constraint->markNonzero(mark); for (int k = 0; k < numberColumns_; k++) { if (mark[k]) { newColumn[numberExtra] = k; newElement[numberExtra++] = 1.0; } } // copy artificials for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { newColumn[numberExtra] = column[j]; newElement[numberExtra++] = elementByRow[j]; } } else { // there already // copy for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { newColumn[numberExtra] = column[j]; assert (elementByRow[j]); newElement[numberExtra++] = elementByRow[j]; } } } newStarts[iRow+1] = numberExtra; } delete [] backRow; CoinPackedMatrix saveMatrix(false, numberColumns2, numberRows_, numberExtra, newElement, newColumn, newStarts, NULL, 0.0, 0.0); delete [] newStarts; delete [] newColumn; delete [] newElement; delete [] mark; // get feasible if (whichWay < 0.0) { newModel.setOptimizationDirection(1.0); double * objective = newModel.objective(); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) objective[iColumn] = - objective[iColumn]; } newModel.primal(1); // still infeasible if (newModel.problemStatus() == 1) { delete [] listNonLinearColumn; return 0; } else if (newModel.problemStatus() == 2) { // unbounded - add bounds double * columnLower = newModel.columnLower(); double * columnUpper = newModel.columnUpper(); for (int i = 0; i < numberColumns_; i++) { columnLower[i] = CoinMax(-1.0e8, columnLower[i]); columnUpper[i] = CoinMin(1.0e8, columnUpper[i]); } newModel.primal(1); } int numberRows = newModel.numberRows(); double * columnLower = newModel.columnLower(); double * columnUpper = newModel.columnUpper(); double * objective = newModel.objective(); double * rowLower = newModel.rowLower(); double * rowUpper = newModel.rowUpper(); double * solution = newModel.primalColumnSolution(); int jNon; int * last[3]; double * trust = new double[numberNonLinearColumns]; double * trueLower = new double[numberNonLinearColumns]; double * trueUpper = new double[numberNonLinearColumns]; double objectiveOffset; double objectiveOffset2; getDblParam(ClpObjOffset, objectiveOffset); objectiveOffset *= whichWay; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; double upper = columnUpper[iColumn]; double lower = columnLower[iColumn]; if (solution[iColumn] < lower) solution[iColumn] = lower; else if (solution[iColumn] > upper) solution[iColumn] = upper; #if 0 double large = CoinMax(1000.0, 10.0 * fabs(solution[iColumn])); if (upper > 1.0e10) upper = solution[iColumn] + large; if (lower < -1.0e10) lower = solution[iColumn] - large; #else upper = solution[iColumn] + 0.5; lower = solution[iColumn] - 0.5; #endif //columnUpper[iColumn]=upper; trust[jNon] = 0.05 * (1.0 + upper - lower); trueLower[jNon] = columnLower[iColumn]; //trueUpper[jNon]=upper; trueUpper[jNon] = columnUpper[iColumn]; } bool tryFix = false; int iPass; double lastObjective = 1.0e31; double lastGoodObjective = 1.0e31; double * bestSolution = NULL; double * saveSolution = new double [numberColumns2+numberRows]; char * saveStatus = new char [numberColumns2+numberRows]; double targetDrop = 1.0e31; // 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; } int numberZeroPasses = 0; bool zeroTargetDrop = false; double * gradient = new double [numberColumns_]; bool goneFeasible = false; // keep sum of artificials #define KEEP_SUM 5 double sumArt[KEEP_SUM]; for (jNon = 0; jNon < KEEP_SUM; jNon++) sumArt[jNon] = COIN_DBL_MAX; #define SMALL_FIX 0.0 for (iPass = 0; iPass < numberPasses; iPass++) { objectiveOffset2 = objectiveOffset; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; if (solution[iColumn] < trueLower[jNon]) solution[iColumn] = trueLower[jNon]; else if (solution[iColumn] > trueUpper[jNon]) solution[iColumn] = trueUpper[jNon]; columnLower[iColumn] = CoinMax(solution[iColumn] - trust[jNon], trueLower[jNon]); if (!trueLower[jNon] && columnLower[iColumn] < SMALL_FIX) columnLower[iColumn] = SMALL_FIX; columnUpper[iColumn] = CoinMin(solution[iColumn] + trust[jNon], trueUpper[jNon]); if (!trueLower[jNon]) columnUpper[iColumn] = CoinMax(columnUpper[iColumn], columnLower[iColumn] + SMALL_FIX); if (!trueLower[jNon] && tryFix && columnLower[iColumn] == SMALL_FIX && columnUpper[iColumn] < 3.0 * SMALL_FIX) { columnLower[iColumn] = 0.0; solution[iColumn] = 0.0; columnUpper[iColumn] = 0.0; printf("fixing %d\n", iColumn); } } // redo matrix double offset; CoinPackedMatrix newMatrix(saveMatrix); // get matrix data pointers column = newMatrix.getIndices(); rowStart = newMatrix.getVectorStarts(); rowLength = newMatrix.getVectorLengths(); // make sure x updated if (numberConstraints) constraints[0]->newXValues(); else trueObjective->newXValues(); double * changeableElement = newMatrix.getMutableElements(); if (trueObjective) { CoinMemcpyN(trueObjective->gradient(this, solution, offset, true, 2), numberColumns_, objective); } else { CoinMemcpyN(objective_->gradient(this, solution, offset, true, 2), numberColumns_, objective); } if (whichWay < 0.0) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) objective[iColumn] = - objective[iColumn]; } for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; int iRow = constraint->rowNumber(); double functionValue; #ifndef NDEBUG int numberErrors = #endif constraint->gradient(&newModel, solution, gradient, functionValue, offset); assert (!numberErrors); // double dualValue = newModel.dualRowSolution()[iRow]; int numberCoefficients = constraint->numberCoefficients(); for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + numberCoefficients; j++) { int iColumn = column[j]; changeableElement[j] = gradient[iColumn]; //objective[iColumn] -= dualValue*gradient[iColumn]; gradient[iColumn] = 0.0; } for (int k = 0; k < numberColumns_; k++) assert (!gradient[k]); if (rowLower_[iRow] > -1.0e20) rowLower[iRow] = rowLower_[iRow] - offset; if (rowUpper_[iRow] < 1.0e20) rowUpper[iRow] = rowUpper_[iRow] - offset; } // Replace matrix // Get a column copy in standard format CoinPackedMatrix * columnCopy = new CoinPackedMatrix();; columnCopy->reverseOrderedCopyOf(newMatrix); newModel.replaceMatrix(columnCopy, true); // solve newModel.primal(1); if (newModel.status() == 1) { // Infeasible! newModel.allSlackBasis(); newModel.primal(); newModel.writeMps("infeas.mps"); assert(!newModel.status()); } double sumInfeas = 0.0; int numberInfeas = 0; for (iColumn = numberColumns_; iColumn < numberColumns2; iColumn++) { if (solution[iColumn] > 1.0e-8) { numberInfeas++; sumInfeas += solution[iColumn]; } } printf("%d artificial infeasibilities - summing to %g\n", numberInfeas, sumInfeas); for (jNon = 0; jNon < KEEP_SUM - 1; jNon++) sumArt[jNon] = sumArt[jNon+1]; sumArt[KEEP_SUM-1] = sumInfeas; if (sumInfeas > 0.01 && sumInfeas * 1.1 > sumArt[0] && penalties[1] < 1.0e7) { // not doing very well - increase - be more sophisticated later lastObjective = COIN_DBL_MAX; for (jNon = 0; jNon < KEEP_SUM; jNon++) sumArt[jNon] = COIN_DBL_MAX; //for (iColumn=numberColumns_;iColumn 0.1) trust[jNon] *= 2.0; else trust[jNon] = 0.1; } if (sumInfeas < 0.001 && !goneFeasible) { goneFeasible = true; penalties[0] = 1.0e-3; penalties[1] = 1.0e6; printf("Got feasible\n"); } double infValue = 0.0; double objValue = 0.0; // make sure x updated if (numberConstraints) constraints[0]->newXValues(); else trueObjective->newXValues(); if (trueObjective) { objValue = trueObjective->objectiveValue(this, solution); printf("objective offset %g\n", offset); objectiveOffset2 = objectiveOffset + offset; // ? sign newModel.setObjectiveOffset(objectiveOffset2); } else { objValue = objective_->objectiveValue(this, solution); } objValue *= whichWay; double infPenalty = 0.0; // This penalty is for target drop double infPenalty2 = 0.0; //const int * row = columnCopy->getIndices(); //const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); //const int * columnLength = columnCopy->getVectorLengths(); //const double * element = columnCopy->getElements(); double * cost = newModel.objective(); column = newMatrix.getIndices(); rowStart = newMatrix.getVectorStarts(); rowLength = newMatrix.getVectorLengths(); elementByRow = newMatrix.getElements(); int jColumn = numberColumns_; double objectiveAdjustment = 0.0; for (iConstraint = 0; iConstraint < numberConstraints; iConstraint++) { ClpConstraint * constraint = constraints[iConstraint]; int iRow = constraint->rowNumber(); double functionValue = constraint->functionValue(this, solution); double dualValue = newModel.dualRowSolution()[iRow]; if (numberConstraints < -50) printf("For row %d current value is %g (row activity %g) , dual is %g\n", iRow, functionValue, newModel.primalRowSolution()[iRow], dualValue); double movement = newModel.primalRowSolution()[iRow] + constraint->offset(); movement = fabs((movement - functionValue) * dualValue); infPenalty2 += movement; double sumOfActivities = 0.0; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; sumOfActivities += fabs(solution[iColumn] * elementByRow[j]); } if (rowLower_[iRow] > -1.0e20) { if (functionValue < rowLower_[iRow] - 1.0e-5) { double infeasibility = rowLower_[iRow] - functionValue; double thisPenalty = 0.0; infValue += infeasibility; int k; assert (dualValue >= -1.0e-5); dualValue = CoinMax(dualValue, 0.0); for ( k = 0; k < SEGMENTS; k++) { if (infeasibility <= 0) break; double thisPart = CoinMin(infeasibility, bounds[k]); thisPenalty += thisPart * cost[jColumn+k]; infeasibility -= thisPart; } infeasibility = functionValue - rowUpper_[iRow]; double newPenalty = 0.0; for ( k = 0; k < SEGMENTS; k++) { double thisPart = CoinMin(infeasibility, bounds[k]); cost[jColumn+k] = CoinMax(penalties[k], dualValue + 1.0e-3); newPenalty += thisPart * cost[jColumn+k]; infeasibility -= thisPart; } infPenalty += thisPenalty; objectiveAdjustment += CoinMax(0.0, newPenalty - thisPenalty); } jColumn += SEGMENTS; } if (rowUpper_[iRow] < 1.0e20) { if (functionValue > rowUpper_[iRow] + 1.0e-5) { double infeasibility = functionValue - rowUpper_[iRow]; double thisPenalty = 0.0; infValue += infeasibility; int k; dualValue = -dualValue; assert (dualValue >= -1.0e-5); dualValue = CoinMax(dualValue, 0.0); for ( k = 0; k < SEGMENTS; k++) { if (infeasibility <= 0) break; double thisPart = CoinMin(infeasibility, bounds[k]); thisPenalty += thisPart * cost[jColumn+k]; infeasibility -= thisPart; } infeasibility = functionValue - rowUpper_[iRow]; double newPenalty = 0.0; for ( k = 0; k < SEGMENTS; k++) { double thisPart = CoinMin(infeasibility, bounds[k]); cost[jColumn+k] = CoinMax(penalties[k], dualValue + 1.0e-3); newPenalty += thisPart * cost[jColumn+k]; infeasibility -= thisPart; } infPenalty += thisPenalty; objectiveAdjustment += CoinMax(0.0, newPenalty - thisPenalty); } jColumn += SEGMENTS; } } // adjust last objective value lastObjective += objectiveAdjustment; if (infValue) printf("Sum infeasibilities %g - penalty %g ", infValue, infPenalty); if (objectiveOffset2) printf("offset2 %g ", objectiveOffset2); objValue -= objectiveOffset2; printf("True objective %g or maybe %g (with penalty %g) -pen2 %g %g\n", objValue, objValue + objectiveOffset2, objValue + objectiveOffset2 + infPenalty, infPenalty2, penalties[1]); double useObjValue = objValue + objectiveOffset2 + infPenalty; objValue += infPenalty + infPenalty2; objValue = useObjValue; if (iPass) { double drop = lastObjective - objValue; std::cout << "True drop was " << drop << std::endl; if (drop < -0.05 * fabs(objValue) - 1.0e-4) { // pretty bad - go back and halve CoinMemcpyN(saveSolution, numberColumns2, solution); CoinMemcpyN(saveSolution + numberColumns2, numberRows, newModel.primalRowSolution()); CoinMemcpyN(reinterpret_cast (saveStatus), numberColumns2 + numberRows, newModel.statusArray()); for (jNon = 0; jNon < numberNonLinearColumns; jNon++) if (trust[jNon] > 0.1) trust[jNon] *= 0.5; else trust[jNon] *= 0.9; printf("** Halving trust\n"); objValue = lastObjective; continue; } else if ((iPass % 25) == -1) { for (jNon = 0; jNon < numberNonLinearColumns; jNon++) trust[jNon] *= 2.0; printf("** Doubling trust\n"); } 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; } } double maxDelta = 0.0; double smallestTrust = 1.0e31; double smallestNonLinearGap = 1.0e31; double smallestGap = 1.0e31; bool increasing = false; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double gap = columnUpper[iColumn] - columnLower[iColumn]; assert (gap >= 0.0); if (gap) smallestGap = CoinMin(smallestGap, gap); } for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; double gap = columnUpper[iColumn] - columnLower[iColumn]; assert (gap >= 0.0); if (gap) { smallestNonLinearGap = CoinMin(smallestNonLinearGap, gap); if (gap < 1.0e-7 && iPass == 1) { printf("Small gap %d %d %g %g %g\n", jNon, iColumn, columnLower[iColumn], columnUpper[iColumn], gap); //trueUpper[jNon]=trueLower[jNon]; //columnUpper[iColumn]=columnLower[iColumn]; } } maxDelta = CoinMax(maxDelta, fabs(solution[iColumn] - saveSolution[iColumn])); if (last[0][jNon]*last[1][jNon] < 0) { // halve if (trust[jNon] > 1.0) trust[jNon] *= 0.5; else trust[jNon] *= 0.7; } else { // ? only increase if +=1 ? if (last[0][jNon] == last[1][jNon] && last[0][jNon] == last[2][jNon] && last[0][jNon]) { trust[jNon] *= 1.8; increasing = true; } } smallestTrust = CoinMin(smallestTrust, trust[jNon]); } std::cout << "largest delta is " << maxDelta << ", smallest trust is " << smallestTrust << ", smallest gap is " << smallestGap << ", smallest nonlinear gap is " << smallestNonLinearGap << std::endl; if (iPass > 200) { //double useObjValue = objValue+objectiveOffset2+infPenalty; if (useObjValue + 1.0e-4 > lastGoodObjective && iPass > 250) { std::cout << "Exiting as objective not changing much" << std::endl; break; } else if (useObjValue < lastGoodObjective) { lastGoodObjective = useObjValue; if (!bestSolution) bestSolution = new double [numberColumns2]; CoinMemcpyN(solution, numberColumns2, bestSolution); } } if (maxDelta < deltaTolerance && !increasing && iPass > 100) { numberZeroPasses++; if (numberZeroPasses == 3) { if (tryFix) { std::cout << "Exiting" << std::endl; break; } else { tryFix = true; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) trust[jNon] = CoinMax(trust[jNon], 1.0e-1); numberZeroPasses = 0; } } } else { numberZeroPasses = 0; } } CoinMemcpyN(solution, numberColumns2, saveSolution); CoinMemcpyN(newModel.primalRowSolution(), numberRows, saveSolution + numberColumns2); CoinMemcpyN(newModel.statusArray(), numberColumns2 + numberRows, reinterpret_cast (saveStatus)); targetDrop = infPenalty + infPenalty2; if (iPass) { // get reduced costs const double * pi = newModel.dualRowSolution(); newModel.matrix()->transposeTimes(pi, newModel.dualColumnSolution()); double * r = newModel.dualColumnSolution(); for (iColumn = 0; iColumn < numberColumns_; iColumn++) r[iColumn] = objective[iColumn] - r[iColumn]; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; double dj = r[iColumn]; if (dj < -1.0e-6) { double drop = -dj * (columnUpper[iColumn] - solution[iColumn]); //double upper = CoinMin(trueUpper[jNon],solution[iColumn]+0.1); //double drop2 = -dj*(upper-solution[iColumn]); #if 0 if (drop > 1.0e8 || drop2 > 100.0 * drop || (drop > 1.0e-2 && iPass > 100)) printf("Big drop %d %g %g %g %g T %g\n", iColumn, columnLower[iColumn], solution[iColumn], columnUpper[iColumn], dj, trueUpper[jNon]); #endif targetDrop += drop; if (dj < -1.0e-1 && trust[jNon] < 1.0e-3 && trueUpper[jNon] - solution[iColumn] > 1.0e-2) { trust[jNon] *= 1.5; //printf("Increasing trust on %d to %g\n", // iColumn,trust[jNon]); } } else if (dj > 1.0e-6) { double drop = -dj * (columnLower[iColumn] - solution[iColumn]); //double lower = CoinMax(trueLower[jNon],solution[iColumn]-0.1); //double drop2 = -dj*(lower-solution[iColumn]); #if 0 if (drop > 1.0e8 || drop2 > 100.0 * drop || (drop > 1.0e-2)) printf("Big drop %d %g %g %g %g T %g\n", iColumn, columnLower[iColumn], solution[iColumn], columnUpper[iColumn], dj, trueLower[jNon]); #endif targetDrop += drop; if (dj > 1.0e-1 && trust[jNon] < 1.0e-3 && solution[iColumn] - trueLower[jNon] > 1.0e-2) { trust[jNon] *= 1.5; printf("Increasing trust on %d to %g\n", iColumn, trust[jNon]); } } } } std::cout << "Pass - " << iPass << ", target drop is " << targetDrop << std::endl; if (iPass > 1 && targetDrop < 1.0e-5 && zeroTargetDrop) break; if (iPass > 1 && targetDrop < 1.0e-5) zeroTargetDrop = true; else zeroTargetDrop = false; //if (iPass==5) //newModel.setLogLevel(63); lastObjective = objValue; // take out when ClpPackedMatrix changed //newModel.scaling(false); #if 0 CoinMpsIO writer; writer.setMpsData(*newModel.matrix(), COIN_DBL_MAX, newModel.getColLower(), newModel.getColUpper(), newModel.getObjCoefficients(), (const char*) 0 /*integrality*/, newModel.getRowLower(), newModel.getRowUpper(), NULL, NULL); writer.writeMps("xx.mps"); #endif } delete [] saveSolution; delete [] saveStatus; for (iPass = 0; iPass < 3; iPass++) delete [] last[iPass]; for (jNon = 0; jNon < numberNonLinearColumns; jNon++) { iColumn = listNonLinearColumn[jNon]; columnLower[iColumn] = trueLower[jNon]; columnUpper[iColumn] = trueUpper[jNon]; } delete [] trust; delete [] trueUpper; delete [] trueLower; objectiveValue_ = newModel.objectiveValue(); if (bestSolution) { CoinMemcpyN(bestSolution, numberColumns2, solution); delete [] bestSolution; printf("restoring objective of %g\n", lastGoodObjective); objectiveValue_ = lastGoodObjective; } // Simplest way to get true row activity ? double * rowActivity = newModel.primalRowSolution(); for (iRow = 0; iRow < numberRows; iRow++) { double difference; if (fabs(rowLower_[iRow]) < fabs(rowUpper_[iRow])) difference = rowLower_[iRow] - rowLower[iRow]; else difference = rowUpper_[iRow] - rowUpper[iRow]; rowLower[iRow] = rowLower_[iRow]; rowUpper[iRow] = rowUpper_[iRow]; if (difference) { if (numberRows < 50) printf("For row %d activity changes from %g to %g\n", iRow, rowActivity[iRow], rowActivity[iRow] + difference); rowActivity[iRow] += difference; } } delete [] listNonLinearColumn; delete [] gradient; printf("solution still in newModel - do objective etc!\n"); numberIterations_ = newModel.numberIterations(); problemStatus_ = newModel.problemStatus(); secondaryStatus_ = newModel.secondaryStatus(); CoinMemcpyN(newModel.primalColumnSolution(), numberColumns_, columnActivity_); // should do status region CoinZeroN(rowActivity_, numberRows_); matrix_->times(1.0, columnActivity_, rowActivity_); return 0; } Clp-1.15.10/src/CoinAbcSmallFactorization1.cpp0000644000076600007660000000103012101105055017433 0ustar coincoin/* $Id: CoinAbcSmallFactorization1.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization1.cpp" #endif Clp-1.15.10/src/ClpPrimalColumnDantzig.cpp0000644000076600007660000002043411571121105016725 0ustar coincoin/* $Id: ClpPrimalColumnDantzig.cpp 1732 2011-05-31 08:09: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). #include "CoinPragma.hpp" #include #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpFactorization.hpp" #include "ClpPackedMatrix.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPrimalColumnDantzig::ClpPrimalColumnDantzig () : ClpPrimalColumnPivot() { type_ = 1; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPrimalColumnDantzig::ClpPrimalColumnDantzig (const ClpPrimalColumnDantzig & source) : ClpPrimalColumnPivot(source) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPrimalColumnDantzig::~ClpPrimalColumnDantzig () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPrimalColumnDantzig & ClpPrimalColumnDantzig::operator=(const ClpPrimalColumnDantzig& rhs) { if (this != &rhs) { ClpPrimalColumnPivot::operator=(rhs); } return *this; } // Returns pivot column, -1 if none int ClpPrimalColumnDantzig::pivotColumn(CoinIndexedVector * updates, CoinIndexedVector * /*spareRow1*/, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { assert(model_); int iSection, j; int number; int * index; double * updateBy; double * reducedCost; bool anyUpdates; if (updates->getNumElements()) { anyUpdates = true; } else { // sub flip - nothing to do anyUpdates = false; } if (anyUpdates) { model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); } for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[j]; updateBy[j] = 0.0; reducedCost[iSequence] = value; } } updates->setNumElements(0); spareColumn1->setNumElements(0); } // update of duals finished - now do pricing double largest = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error if (model_->largestDualError() > 1.0e-8) largest *= model_->largestDualError() / 1.0e-8; double bestDj = model_->dualTolerance(); int bestSequence = -1; double bestFreeDj = model_->dualTolerance(); int bestFreeSequence = -1; number = model_->numberRows() + model_->numberColumns(); int iSequence; reducedCost = model_->djRegion(); #ifndef CLP_PRIMAL_SLACK_MULTIPLIER for (iSequence = 0; iSequence < number; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case ClpSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case ClpSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } #else // Columns int numberColumns = model_->numberColumns(); for (iSequence = 0; iSequence < numberColumns; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case ClpSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case ClpSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } // Rows for ( ; iSequence < number; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence] * CLP_PRIMAL_SLACK_MULTIPLIER; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case ClpSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case ClpSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } #endif // bias towards free if (bestFreeSequence >= 0 && bestFreeDj > 0.1 * bestDj) bestSequence = bestFreeSequence; return bestSequence; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpPrimalColumnPivot * ClpPrimalColumnDantzig::clone(bool CopyData) const { if (CopyData) { return new ClpPrimalColumnDantzig(*this); } else { return new ClpPrimalColumnDantzig(); } } Clp-1.15.10/src/ClpModel.hpp0000644000076600007660000014156112375044370014067 0ustar coincoin/* $Id: ClpModel.hpp 2047 2014-08-20 07:06:32Z 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 ClpModel_H #define ClpModel_H #include "ClpConfig.h" #include #include #include #include #include //#ifndef COIN_USE_CLP //#define COIN_USE_CLP //#endif #include "ClpPackedMatrix.hpp" #include "CoinMessageHandler.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTypes.hpp" #include "CoinFinite.hpp" #include "ClpParameters.hpp" #include "ClpObjective.hpp" class ClpEventHandler; /** This is the base class for Linear and quadratic Models This knows nothing about the algorithm, but it seems to have a reasonable amount of information I would welcome suggestions for what should be in this and how it relates to OsiSolverInterface. Some methods look very similar. */ class CoinBuild; class CoinModel; class ClpModel { public: /**@name Constructors and destructor Note - copy methods copy ALL data so can chew up memory until other copy is freed */ //@{ /// Default constructor ClpModel (bool emptyMessages = false ); /** Copy constructor. May scale depending on mode -1 leave mode as is 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 auto-but-as-initialSolve-in-bab */ ClpModel(const ClpModel & rhs, int scalingMode = -1); /// Assignment operator. This copies the data ClpModel & operator=(const ClpModel & rhs); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped */ ClpModel (const ClpModel * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true); /// Destructor ~ClpModel ( ); //@} /**@name Load model - loads some stuff and initializes others */ //@{ /** Loads a problem (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
*/ void loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); void loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /** Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ 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, const double * rowObjective = NULL); /** This loads a model from a coinModel object - returns number of errors. modelObject not const as may be changed as part of process If tryPlusMinusOne then will try adding as +-1 matrix */ int loadProblem ( CoinModel & modelObject, bool tryPlusMinusOne = false); /// This one is for after presolve to save memory void loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int * length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ void loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start, const int * column, const double * element); void loadQuadraticObjective ( const CoinPackedMatrix& matrix); /// Get rid of quadratic objective void deleteQuadraticObjective(); /// This just loads up a row objective void setRowObjective(const double * rowObjective); /// Read an mps file from the given filename int readMps(const char *filename, bool keepNames = false, bool ignoreErrors = false); /// Read GMPL files from the given filenames int readGMPL(const char *filename, const char * dataName, bool keepNames = false); /// Copy in integer informations void copyInIntegerInformation(const char * information); /// Drop integer informations void deleteIntegerInformation(); /** Set the index-th variable to be a continuous variable */ void setContinuous(int index); /** Set the index-th variable to be an integer variable */ void setInteger(int index); /** Return true if the index-th variable is an integer variable */ bool isInteger(int index) const; /// Resizes rim part of model void resize (int newNumberRows, int newNumberColumns); /// Deletes rows void deleteRows(int number, const int * which); /// Add one row void addRow(int numberInRow, const int * columns, const double * elements, double rowLower = -COIN_DBL_MAX, double rowUpper = COIN_DBL_MAX); /// Add rows void addRows(int number, const double * rowLower, const double * rowUpper, const CoinBigIndex * rowStarts, const int * columns, const double * elements); /// Add rows void addRows(int number, const double * rowLower, const double * rowUpper, const CoinBigIndex * rowStarts, const int * rowLengths, const int * columns, const double * elements); #ifndef CLP_NO_VECTOR void addRows(int number, const double * rowLower, const double * rowUpper, const CoinPackedVectorBase * const * rows); #endif /** Add rows from a build object. If tryPlusMinusOne then will try adding as +-1 matrix if no matrix exists. Returns number of errors e.g. duplicates */ int addRows(const CoinBuild & buildObject, bool tryPlusMinusOne = false, bool checkDuplicates = true); /** Add rows from a model object. returns -1 if object in bad state (i.e. has column information) otherwise number of errors. modelObject non const as can be regularized as part of build If tryPlusMinusOne then will try adding as +-1 matrix if no matrix exists. */ int addRows(CoinModel & modelObject, bool tryPlusMinusOne = false, bool checkDuplicates = true); /// Deletes columns void deleteColumns(int number, const int * which); /// Deletes rows AND columns (keeps old sizes) void deleteRowsAndColumns(int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); /// Add one column void addColumn(int numberInColumn, const int * rows, const double * elements, double columnLower = 0.0, double columnUpper = COIN_DBL_MAX, double objective = 0.0); /// Add columns void addColumns(int number, const double * columnLower, const double * columnUpper, const double * objective, const CoinBigIndex * columnStarts, const int * rows, const double * elements); void addColumns(int number, const double * columnLower, const double * columnUpper, const double * objective, const CoinBigIndex * columnStarts, const int * columnLengths, const int * rows, const double * elements); #ifndef CLP_NO_VECTOR void addColumns(int number, const double * columnLower, const double * columnUpper, const double * objective, const CoinPackedVectorBase * const * columns); #endif /** Add columns from a build object If tryPlusMinusOne then will try adding as +-1 matrix if no matrix exists. Returns number of errors e.g. duplicates */ int addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne = false, bool checkDuplicates = true); /** Add columns from a model object. returns -1 if object in bad state (i.e. has row information) otherwise number of errors modelObject non const as can be regularized as part of build If tryPlusMinusOne then will try adding as +-1 matrix if no matrix exists. */ int addColumns(CoinModel & modelObject, bool tryPlusMinusOne = false, bool checkDuplicates = true); /// Modify one element of a matrix inline void modifyCoefficient(int row, int column, double newElement, bool keepZero = false) { matrix_->modifyCoefficient(row, column, newElement, keepZero); } /** Change row lower bounds */ void chgRowLower(const double * rowLower); /** Change row upper bounds */ void chgRowUpper(const double * rowUpper); /** Change column lower bounds */ void chgColumnLower(const double * columnLower); /** Change column upper bounds */ void chgColumnUpper(const double * columnUpper); /** Change objective coefficients */ void chgObjCoefficients(const double * objIn); /** Borrow model. This is so we don't have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm */ void borrowModel(ClpModel & otherModel); /** Return model - nulls all arrays so can be deleted safely also updates any scalars */ void returnModel(ClpModel & otherModel); /// Create empty ClpPackedMatrix void createEmptyMatrix(); /** Really clean up matrix (if ClpPackedMatrix). a) eliminate all duplicate AND small elements in matrix b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 c) reallocate arrays and make max lengths equal to lengths d) orders elements returns number of elements eliminated or -1 if not ClpPackedMatrix */ int cleanMatrix(double threshold = 1.0e-20); /// Copy contents - resizing if necessary - otherwise re-use memory void copy(const ClpMatrixBase * from, ClpMatrixBase * & to); #ifndef CLP_NO_STD /// Drops names - makes lengthnames 0 and names empty void dropNames(); /// Copies in names void copyNames(const std::vector & rowNames, const std::vector & columnNames); /// Copies in Row names - modifies names first .. last-1 void copyRowNames(const std::vector & rowNames, int first, int last); /// Copies in Column names - modifies names first .. last-1 void copyColumnNames(const std::vector & columnNames, int first, int last); /// Copies in Row names - modifies names first .. last-1 void copyRowNames(const char * const * rowNames, int first, int last); /// Copies in Column names - modifies names first .. last-1 void copyColumnNames(const char * const * columnNames, int first, int last); /// Set name of row void setRowName(int rowIndex, std::string & name) ; /// Set name of col void setColumnName(int colIndex, std::string & name) ; #endif /** Find a network subset. rotate array should be numberRows. On output -1 not in network 0 in network as is 1 in network with signs swapped Returns number of network rows */ int findNetwork(char * rotate, double fractionNeeded = 0.75); /** This creates a coinModel object */ CoinModel * createCoinModel() const; /** Write the problem in MPS format to the specified file. Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex
Returns non-zero on I/O error */ int writeMps(const char *filename, int formatType = 0, int numberAcross = 2, double objSense = 0.0) const ; //@} /**@name gets and sets */ //@{ /// Number of rows inline int numberRows() const { return numberRows_; } inline int getNumRows() const { return numberRows_; } /// Number of columns inline int getNumCols() const { return numberColumns_; } inline int numberColumns() const { return numberColumns_; } /// Primal tolerance to use inline double primalTolerance() const { return dblParam_[ClpPrimalTolerance]; } void setPrimalTolerance( double value) ; /// Dual tolerance to use inline double dualTolerance() const { return dblParam_[ClpDualTolerance]; } void setDualTolerance( double value) ; /// Primal objective limit inline double primalObjectiveLimit() const { return dblParam_[ClpPrimalObjectiveLimit]; } void setPrimalObjectiveLimit(double value); /// Dual objective limit inline double dualObjectiveLimit() const { return dblParam_[ClpDualObjectiveLimit]; } void setDualObjectiveLimit(double value); /// Objective offset inline double objectiveOffset() const { return dblParam_[ClpObjOffset]; } void setObjectiveOffset(double value); /// Presolve tolerance to use inline double presolveTolerance() const { return dblParam_[ClpPresolveTolerance]; } #ifndef CLP_NO_STD inline const std::string & problemName() const { return strParam_[ClpProbName]; } #endif /// Number of iterations inline int numberIterations() const { return numberIterations_; } inline int getIterationCount() const { return numberIterations_; } inline void setNumberIterations(int numberIterationsNew) { numberIterations_ = numberIterationsNew; } /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ inline int solveType() const { return solveType_; } inline void setSolveType(int type) { solveType_ = type; } /// Maximum number of iterations inline int maximumIterations() const { return intParam_[ClpMaxNumIteration]; } void setMaximumIterations(int value); /// Maximum time in seconds (from when set called) inline double maximumSeconds() const { return dblParam_[ClpMaxSeconds]; } void setMaximumSeconds(double value); void setMaximumWallSeconds(double value); /// Returns true if hit maximum iterations (or time) bool hitMaximumIterations() const; /** Status of problem: -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()) */ inline int status() const { return problemStatus_; } inline int problemStatus() const { return problemStatus_; } /// Set problem status inline void setProblemStatus(int problemStatusNew) { problemStatus_ = problemStatusNew; } /** 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 was 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 10 - status was 3 and can't use objective as lb 100 up - translation of enum from ClpEventHandler */ inline int secondaryStatus() const { return secondaryStatus_; } inline void setSecondaryStatus(int newstatus) { secondaryStatus_ = newstatus; } /// Are there a numerical difficulties? inline bool isAbandoned() const { return problemStatus_ == 4; } /// Is optimality proven? inline bool isProvenOptimal() const { return problemStatus_ == 0; } /// Is primal infeasiblity proven? inline bool isProvenPrimalInfeasible() const { return problemStatus_ == 1; } /// Is dual infeasiblity proven? inline bool isProvenDualInfeasible() const { return problemStatus_ == 2; } /// Is the given primal objective limit reached? bool isPrimalObjectiveLimitReached() const ; /// Is the given dual objective limit reached? bool isDualObjectiveLimitReached() const ; /// Iteration limit reached? inline bool isIterationLimitReached() const { return problemStatus_ == 3; } /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore inline double optimizationDirection() const { return optimizationDirection_; } inline double getObjSense() const { return optimizationDirection_; } void setOptimizationDirection(double value); /// Primal row solution inline double * primalRowSolution() const { return rowActivity_; } inline const double * getRowActivity() const { return rowActivity_; } /// Primal column solution inline double * primalColumnSolution() const { return columnActivity_; } inline const double * getColSolution() const { return columnActivity_; } inline void setColSolution(const double * input) { memcpy(columnActivity_, input, numberColumns_ * sizeof(double)); } /// Dual row solution inline double * dualRowSolution() const { return dual_; } inline const double * getRowPrice() const { return dual_; } /// Reduced costs inline double * dualColumnSolution() const { return reducedCost_; } inline const double * getReducedCost() const { return reducedCost_; } /// Row lower inline double* rowLower() const { return rowLower_; } inline const double* getRowLower() const { return rowLower_; } /// Row upper inline double* rowUpper() const { return rowUpper_; } inline const double* getRowUpper() const { return rowUpper_; } //------------------------------------------------------------------------- /**@name Changing bounds on variables and constraints */ //@{ /** Set an objective function coefficient */ void setObjectiveCoefficient( int elementIndex, double elementValue ); /** Set an objective function coefficient */ inline void setObjCoeff( int elementIndex, double elementValue ) { setObjectiveCoefficient( elementIndex, elementValue); } /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ void setColumnLower( int elementIndex, double elementValue ); /** Set a single column upper bound
Use DBL_MAX for infinity. */ void setColumnUpper( int elementIndex, double elementValue ); /** Set a single column lower and upper bound */ void setColumnBounds( 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 */ void setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ inline void setColLower( int elementIndex, double elementValue ) { setColumnLower(elementIndex, elementValue); } /** Set a single column upper bound
Use DBL_MAX for infinity. */ inline void setColUpper( int elementIndex, double elementValue ) { setColumnUpper(elementIndex, elementValue); } /** Set a single column lower and upper bound */ inline void setColBounds( int elementIndex, double lower, double upper ) { setColumnBounds(elementIndex, lower, upper); } /** Set the bounds on a number of columns simultaneously
@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 */ inline void setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { setColumnSetBounds(indexFirst, indexLast, boundList); } /** Set a single row lower bound
Use -DBL_MAX for -infinity. */ void setRowLower( int elementIndex, double elementValue ); /** Set a single row upper bound
Use DBL_MAX for infinity. */ void setRowUpper( int elementIndex, double elementValue ) ; /** Set a single row lower and upper bound */ void setRowBounds( int elementIndex, double lower, double upper ) ; /** Set the bounds on a number of rows simultaneously
@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 */ void setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); //@} /// Scaling inline const double * rowScale() const { return rowScale_; } inline const double * columnScale() const { return columnScale_; } inline const double * inverseRowScale() const { return inverseRowScale_; } inline const double * inverseColumnScale() const { return inverseColumnScale_; } inline double * mutableRowScale() const { return rowScale_; } inline double * mutableColumnScale() const { return columnScale_; } inline double * mutableInverseRowScale() const { return inverseRowScale_; } inline double * mutableInverseColumnScale() const { return inverseColumnScale_; } inline double * swapRowScale(double * newScale) { double * oldScale = rowScale_; rowScale_ = newScale; return oldScale; } void setRowScale(double * scale) ; void setColumnScale(double * scale); /// Scaling of objective inline double objectiveScale() const { return objectiveScale_; } inline void setObjectiveScale(double value) { objectiveScale_ = value; } /// Scaling of rhs and bounds inline double rhsScale() const { return rhsScale_; } inline void setRhsScale(double value) { rhsScale_ = value; } /// Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 auto-but-as-initialSolve-in-bab void scaling(int mode = 1); /** If we constructed a "really" scaled model then this reverses the operation. Quantities may not be exactly as they were before due to rounding errors */ void unscale(); /// Gets scalingFlag inline int scalingFlag() const { return scalingFlag_; } /// Objective inline double * objective() const { if (objective_) { double offset; return objective_->gradient(NULL, NULL, offset, false); } else { return NULL; } } inline double * objective(const double * solution, double & offset, bool refresh = true) const { offset = 0.0; if (objective_) { return objective_->gradient(NULL, solution, offset, refresh); } else { return NULL; } } inline const double * getObjCoefficients() const { if (objective_) { double offset; return objective_->gradient(NULL, NULL, offset, false); } else { return NULL; } } /// Row Objective inline double * rowObjective() const { return rowObjective_; } inline const double * getRowObjCoefficients() const { return rowObjective_; } /// Column Lower inline double * columnLower() const { return columnLower_; } inline const double * getColLower() const { return columnLower_; } /// Column Upper inline double * columnUpper() const { return columnUpper_; } inline const double * getColUpper() const { return columnUpper_; } /// Matrix (if not ClpPackedmatrix be careful about memory leak inline CoinPackedMatrix * matrix() const { if ( matrix_ == NULL ) return NULL; else return matrix_->getPackedMatrix(); } /// Number of elements in matrix inline int getNumElements() const { return matrix_->getNumElements(); } /** Small element value - elements less than this set to zero, default is 1.0e-20 */ inline double getSmallElementValue() const { return smallElement_; } inline void setSmallElementValue(double value) { smallElement_ = value; } /// Row Matrix inline ClpMatrixBase * rowCopy() const { return rowCopy_; } /// Set new row matrix void setNewRowCopy(ClpMatrixBase * newCopy); /// Clp Matrix inline ClpMatrixBase * clpMatrix() const { return matrix_; } /// Scaled ClpPackedMatrix inline ClpPackedMatrix * clpScaledMatrix() const { return scaledMatrix_; } /// Sets pointer to scaled ClpPackedMatrix inline void setClpScaledMatrix(ClpPackedMatrix * scaledMatrix) { delete scaledMatrix_; scaledMatrix_ = scaledMatrix; } /// Swaps pointer to scaled ClpPackedMatrix inline ClpPackedMatrix * swapScaledMatrix(ClpPackedMatrix * scaledMatrix) { ClpPackedMatrix * oldMatrix = scaledMatrix_; scaledMatrix_ = scaledMatrix; return oldMatrix; } /** Replace Clp Matrix (current is not deleted unless told to and new is used) So up to user to delete current. This was used where matrices were being rotated. ClpModel takes ownership. */ void replaceMatrix(ClpMatrixBase * matrix, bool deleteCurrent = false); /** Replace Clp Matrix (current is not deleted unless told to and new is used) So up to user to delete current. This was used where matrices were being rotated. This version changes CoinPackedMatrix to ClpPackedMatrix. ClpModel takes ownership. */ inline void replaceMatrix(CoinPackedMatrix * newmatrix, bool deleteCurrent = false) { replaceMatrix(new ClpPackedMatrix(newmatrix), deleteCurrent); } /// Objective value inline double objectiveValue() const { return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; } inline void setObjectiveValue(double value) { objectiveValue_ = (value + dblParam_[ClpObjOffset]) / optimizationDirection_; } inline double getObjValue() const { return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; } /// Integer information inline char * integerInformation() const { return integerType_; } /** Infeasibility/unbounded ray (NULL returned if none/wrong) Up to user to use delete [] on these arrays. */ double * infeasibilityRay(bool fullRay=false) const; double * unboundedRay() const; /// For advanced users - no need to delete - sign not changed inline double * ray() const { return ray_;} /// just test if infeasibility or unbounded Ray exists inline bool rayExists() const { return (ray_!=NULL); } /// just delete ray if exists inline void deleteRay() { delete [] ray_; ray_=NULL; } /// Access internal ray storage. Users should call infeasibilityRay() or unboundedRay() instead. inline const double * internalRay() const { return ray_; } /// See if status (i.e. basis) array exists (partly for OsiClp) inline bool statusExists() const { return (status_ != NULL); } /// Return address of status (i.e. basis) array (char[numberRows+numberColumns]) inline unsigned char * statusArray() const { return status_; } /** Return copy of status (i.e. basis) array (char[numberRows+numberColumns]), use delete [] */ unsigned char * statusCopy() const; /// Copy in status (basis) vector void copyinStatus(const unsigned char * statusArray); /// User pointer for whatever reason inline void setUserPointer (void * pointer) { userPointer_ = pointer; } inline void * getUserPointer () const { return userPointer_; } /// Trusted user pointer inline void setTrustedUserPointer (ClpTrustedData * pointer) { trustedUserPointer_ = pointer; } inline ClpTrustedData * getTrustedUserPointer () const { return trustedUserPointer_; } /// What has changed in model (only for masochistic users) inline int whatsChanged() const { return whatsChanged_; } inline void setWhatsChanged(int value) { whatsChanged_ = value; } /// Number of threads (not really being used) inline int numberThreads() const { return numberThreads_; } inline void setNumberThreads(int value) { numberThreads_ = value; } //@} /**@name Message handling */ //@{ /// Pass in Message handler (not deleted at end) void passInMessageHandler(CoinMessageHandler * handler); /// Pass in Message handler (not deleted at end) and return current CoinMessageHandler * pushMessageHandler(CoinMessageHandler * handler, bool & oldDefault); /// back to previous message handler void popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault); /// Set language void newLanguage(CoinMessages::Language language); inline void setLanguage(CoinMessages::Language language) { newLanguage(language); } /// Overrides message handler with a default one void setDefaultMessageHandler(); /// Return handler inline CoinMessageHandler * messageHandler() const { return handler_; } /// Return messages inline CoinMessages messages() const { return messages_; } /// Return pointer to messages inline CoinMessages * messagesPointer() { return & messages_; } /// Return Coin messages inline CoinMessages coinMessages() const { return coinMessages_; } /// Return pointer to Coin messages inline CoinMessages * coinMessagesPointer() { return & coinMessages_; } /** 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 */ inline void setLogLevel(int value) { handler_->setLogLevel(value); } inline int logLevel() const { return handler_->logLevel(); } /// Return true if default handler inline bool defaultHandler() const { return defaultHandler_; } /// Pass in Event handler (cloned and deleted at end) void passInEventHandler(const ClpEventHandler * eventHandler); /// Event handler inline ClpEventHandler * eventHandler() const { return eventHandler_; } /// Thread specific random number generator inline CoinThreadRandom * randomNumberGenerator() { return &randomNumberGenerator_; } /// Thread specific random number generator inline CoinThreadRandom & mutableRandomNumberGenerator() { return randomNumberGenerator_; } /// Set seed for thread specific random number generator inline void setRandomSeed(int value) { randomNumberGenerator_.setSeed(value); } /// length of names (0 means no names0 inline int lengthNames() const { return lengthNames_; } #ifndef CLP_NO_STD /// length of names (0 means no names0 inline void setLengthNames(int value) { lengthNames_ = value; } /// Row names inline const std::vector * rowNames() const { return &rowNames_; } inline const std::string& rowName(int iRow) const { return rowNames_[iRow]; } /// Return name or Rnnnnnnn std::string getRowName(int iRow) const; /// Column names inline const std::vector * columnNames() const { return &columnNames_; } inline const std::string& columnName(int iColumn) const { return columnNames_[iColumn]; } /// Return name or Cnnnnnnn std::string getColumnName(int iColumn) const; #endif /// Objective methods inline ClpObjective * objectiveAsObject() const { return objective_; } void setObjective(ClpObjective * objective); inline void setObjectivePointer(ClpObjective * newobjective) { objective_ = newobjective; } /** Solve a problem with no elements - return status and dual and primal infeasibilites */ int emptyProblem(int * infeasNumber = NULL, double * infeasSum = NULL, bool printMessage = true); //@} /**@name Matrix times vector methods They can be faster if scalar is +- 1 These are covers so user need not worry about scaling Also for simplex I am not using basic/non-basic split */ //@{ /** Return y + A * x * scalar in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ void times(double scalar, const double * x, double * y) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ void transposeTimes(double scalar, const double * x, double * y) const ; //@} //--------------------------------------------------------------------------- /**@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 volume 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. ** once it has been decided where solver sits this may be redone */ //@{ /// Set an integer parameter bool setIntParam(ClpIntParam key, int value) ; /// Set an double parameter bool setDblParam(ClpDblParam key, double value) ; #ifndef CLP_NO_STD /// Set an string parameter bool setStrParam(ClpStrParam key, const std::string & value); #endif // Get an integer parameter inline bool getIntParam(ClpIntParam key, int& value) const { if (key < ClpLastIntParam) { value = intParam_[key]; return true; } else { return false; } } // Get an double parameter inline bool getDblParam(ClpDblParam key, double& value) const { if (key < ClpLastDblParam) { value = dblParam_[key]; return true; } else { return false; } } #ifndef CLP_NO_STD // Get a string parameter inline bool getStrParam(ClpStrParam key, std::string& value) const { if (key < ClpLastStrParam) { value = strParam_[key]; return true; } else { return false; } } #endif /// Create C++ lines to get to current state void generateCpp( FILE * fp); /** For advanced options 1 - Don't keep changing infeasibility weight 2 - Keep nonLinearCost round solves 4 - Force outgoing variables to exact bound (primal) 8 - Safe to use dense initial factorization 16 -Just use basic variables for operation if column generation 32 -Create ray even in BAB 64 -Treat problem as feasible until last minute (i.e. minimize infeasibilities) 128 - Switch off all matrix sanity checks 256 - No row copy 512 - If not in values pass, solution guaranteed, skip as much as possible 1024 - In branch and bound 2048 - Don't bother to re-factorize if < 20 iterations 4096 - Skip some optimality checks 8192 - Do Primal when cleaning up primal 16384 - In fast dual (so we can switch off things) 32768 - called from Osi 65536 - keep arrays around as much as possible (also use maximumR/C) 131072 - transposeTimes is -1.0 and can skip basic and fixed 262144 - extra copy of scaled matrix 524288 - Clp fast dual 1048576 - don't need to finish dual (can return 3) 2097152 - zero costs! NOTE - many applications can call Clp but there may be some short cuts which are taken which are not guaranteed safe from all applications. Vetted applications will have a bit set and the code may test this At present I expect a few such applications - if too many I will have to re-think. It is up to application owner to change the code if she/he needs these short cuts. I will not debug unless in Coin repository. See COIN_CLP_VETTED comments. 0x01000000 is Cbc (and in branch and bound) 0x02000000 is in a different branch and bound */ inline unsigned int specialOptions() const { return specialOptions_; } void setSpecialOptions(unsigned int value); #define COIN_CBC_USING_CLP 0x01000000 inline bool inCbcBranchAndBound() const { return (specialOptions_ & COIN_CBC_USING_CLP) != 0; } //@} /**@name private or protected methods */ //@{ protected: /// Does most of deletion (0 = all, 1 = most) void gutsOfDelete(int type); /** Does most of copying If trueCopy 0 then just points to arrays If -1 leaves as much as possible */ void gutsOfCopy(const ClpModel & rhs, int trueCopy = 1); /// gets lower and upper bounds on rows void getRowBound(int iRow, double& lower, double& upper) const; /// puts in format I like - 4 array matrix - may make row copy void gutsOfLoadModel ( int numberRows, int numberColumns, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /// Does much of scaling void gutsOfScaling(); /// Objective value - always minimize inline double rawObjectiveValue() const { return objectiveValue_; } /// If we are using maximumRows_ and Columns_ inline bool permanentArrays() const { return (specialOptions_ & 65536) != 0; } /// Start using maximumRows_ and Columns_ void startPermanentArrays(); /// Stop using maximumRows_ and Columns_ void stopPermanentArrays(); /// Create row names as char ** const char * const * rowNamesAsChar() const; /// Create column names as char ** const char * const * columnNamesAsChar() const; /// Delete char * version of names void deleteNamesAsChar(const char * const * names, int number) const; /// On stopped - sets secondary status void onStopped(); //@} ////////////////// data ////////////////// protected: /**@name data */ //@{ /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore double optimizationDirection_; /// Array of double parameters double dblParam_[ClpLastDblParam]; /// Objective value double objectiveValue_; /// Small element value double smallElement_; /// Scaling of objective double objectiveScale_; /// Scaling of rhs and bounds double rhsScale_; /// Number of rows int numberRows_; /// Number of columns int numberColumns_; /// Row activities double * rowActivity_; /// Column activities double * columnActivity_; /// Duals double * dual_; /// Reduced costs double * reducedCost_; /// Row lower double* rowLower_; /// Row upper double* rowUpper_; /// Objective ClpObjective * objective_; /// Row Objective (? sign) - may be NULL double * rowObjective_; /// Column Lower double * columnLower_; /// Column Upper double * columnUpper_; /// Packed matrix ClpMatrixBase * matrix_; /// Row copy if wanted ClpMatrixBase * rowCopy_; /// Scaled packed matrix ClpPackedMatrix * scaledMatrix_; /// Infeasible/unbounded ray double * ray_; /// Row scale factors for matrix double * rowScale_; /// Column scale factors double * columnScale_; /// Inverse row scale factors for matrix (end of rowScale_) double * inverseRowScale_; /// Inverse column scale factors for matrix (end of columnScale_) double * inverseColumnScale_; /** Scale flag, 0 none, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic, 5 geometric on rows */ int scalingFlag_; /** Status (i.e. basis) Region. I know that not all algorithms need a status array, but it made sense for things like crossover and put all permanent stuff in one place. No assumption is made about what is in status array (although it might be good to reserve bottom 3 bits (i.e. 0-7 numeric) for classic status). This is number of columns + number of rows long (in that order). */ unsigned char * status_; /// Integer information char * integerType_; /// User pointer for whatever reason void * userPointer_; /// Trusted user pointer e.g. for heuristics ClpTrustedData * trustedUserPointer_; /// Array of integer parameters int intParam_[ClpLastIntParam]; /// Number of iterations int numberIterations_; /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ int solveType_; /** Whats changed since last solve. This is a work in progress It is designed so careful people can make go faster. It is only used when startFinishOptions used in dual or primal. Bit 1 - number of rows/columns has not changed (so work arrays valid) 2 - matrix has not changed 4 - if matrix has changed only by adding rows 8 - if matrix has changed only by adding columns 16 - row lbs not changed 32 - row ubs not changed 64 - column objective not changed 128 - column lbs not changed 256 - column ubs not changed 512 - basis not changed (up to user to set this to 0) top bits may be used internally shift by 65336 is 3 all same, 1 all except col bounds */ #define ROW_COLUMN_COUNTS_SAME 1 #define MATRIX_SAME 2 #define MATRIX_JUST_ROWS_ADDED 4 #define MATRIX_JUST_COLUMNS_ADDED 8 #define ROW_LOWER_SAME 16 #define ROW_UPPER_SAME 32 #define OBJECTIVE_SAME 64 #define COLUMN_LOWER_SAME 128 #define COLUMN_UPPER_SAME 256 #define BASIS_SAME 512 #define ALL_SAME 65339 #define ALL_SAME_EXCEPT_COLUMN_BOUNDS 65337 unsigned int whatsChanged_; /// Status of problem int problemStatus_; /// Secondary status of problem int secondaryStatus_; /// length of names (0 means no names) int lengthNames_; /// Number of threads (not very operational) int numberThreads_; /** For advanced options See get and set for meaning */ unsigned int specialOptions_; /// Message handler CoinMessageHandler * handler_; /// Flag to say if default handler (so delete) bool defaultHandler_; /// Thread specific random number generator CoinThreadRandom randomNumberGenerator_; /// Event handler ClpEventHandler * eventHandler_; #ifndef CLP_NO_STD /// Row names std::vector rowNames_; /// Column names std::vector columnNames_; #endif /// Messages CoinMessages messages_; /// Coin messages CoinMessages coinMessages_; /// Maximum number of columns in model int maximumColumns_; /// Maximum number of rows in model int maximumRows_; /// Maximum number of columns (internal arrays) in model int maximumInternalColumns_; /// Maximum number of rows (internal arrays) in model int maximumInternalRows_; /// Base packed matrix CoinPackedMatrix baseMatrix_; /// Base row copy CoinPackedMatrix baseRowCopy_; /// Saved row scale factors for matrix double * savedRowScale_; /// Saved column scale factors double * savedColumnScale_; #ifndef CLP_NO_STD /// Array of string parameters std::string strParam_[ClpLastStrParam]; #endif //@} }; /** This is a tiny class where data can be saved round calls. */ class ClpDataSave { public: /**@name Constructors and destructor */ //@{ /// Default constructor ClpDataSave ( ); /// Copy constructor. ClpDataSave(const ClpDataSave &); /// Assignment operator. This copies the data ClpDataSave & operator=(const ClpDataSave & rhs); /// Destructor ~ClpDataSave ( ); //@} ////////////////// data ////////////////// public: /**@name data - with same names as in other classes*/ //@{ double dualBound_; double infeasibilityCost_; double pivotTolerance_; double zeroFactorizationTolerance_; double zeroSimplexTolerance_; double acceptablePivot_; double objectiveScale_; int sparseThreshold_; int perturbation_; int forceFactorization_; int scalingFlag_; unsigned int specialOptions_; //@} }; #endif Clp-1.15.10/src/ClpGubDynamicMatrix.hpp0000644000076600007660000002004011510657452016223 0ustar coincoin/* $Id: ClpGubDynamicMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpGubDynamicMatrix_H #define ClpGubDynamicMatrix_H #include "CoinPragma.hpp" #include "ClpGubMatrix.hpp" /** This implements Gub rows plus a ClpPackedMatrix. This a dynamic version which stores the gub part and dynamically creates matrix. All bounds are assumed to be zero and infinity This is just a simple example for real column generation */ class ClpGubDynamicMatrix : public ClpGubMatrix { public: /**@name Main functions provided */ //@{ /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /** This is local to Gub to allow synchronization: mode=0 when status of basis is good mode=1 when variable is flagged mode=2 when all variables unflagged (returns number flagged) mode=3 just reset costs (primal) mode=4 correct number of dual infeasibilities mode=5 return 4 if time to re-factorize mode=8 - make sure set is clean mode=9 - adjust lower, upper on set by incoming */ virtual int synchronize(ClpSimplex * model, int mode); /// Sets up an effective RHS and does gub crash if needed virtual void useEffectiveRhs(ClpSimplex * model, bool cheapest = true); /** update information for a pivot (and effective rhs) */ virtual int updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue); /// Add a new variable to a set void insertNonBasic(int sequence, int iSet); /** Returns effective RHS offset if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ virtual double * rhsOffset(ClpSimplex * model, bool forceRefresh = false, bool check = false); using ClpPackedMatrix::times ; /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /** Just for debug Returns sum and number of primal infeasibilities. Recomputes keys */ virtual int checkFeasible(ClpSimplex * model, double & sum) const; /// Cleans data after setWarmStart void cleanData(ClpSimplex * model); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpGubDynamicMatrix(); /** Destructor */ virtual ~ClpGubDynamicMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpGubDynamicMatrix(const ClpGubDynamicMatrix&); /** This is the real constructor. It assumes factorization frequency will not be changed. This resizes model !!!! */ ClpGubDynamicMatrix(ClpSimplex * model, int numberSets, int numberColumns, const int * starts, const double * lower, const double * upper, const int * startColumn, const int * row, const double * element, const double * cost, const double * lowerColumn = NULL, const double * upperColumn = NULL, const unsigned char * status = NULL); ClpGubDynamicMatrix& operator=(const ClpGubDynamicMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; //@} /**@name gets and sets */ //@{ /// enums for status of various sorts enum DynamicStatus { inSmall = 0x01, atUpperBound = 0x02, atLowerBound = 0x03 }; /// Whether flagged inline bool flagged(int i) const { return (dynamicStatus_[i] & 8) != 0; } inline void setFlagged(int i) { dynamicStatus_[i] = static_cast(dynamicStatus_[i] | 8); } inline void unsetFlagged(int i) { dynamicStatus_[i] = static_cast(dynamicStatus_[i] & ~8); } inline void setDynamicStatus(int sequence, DynamicStatus status) { unsigned char & st_byte = dynamicStatus_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | status); } inline DynamicStatus getDynamicStatus(int sequence) const { return static_cast (dynamicStatus_[sequence] & 7); } /// Saved value of objective offset inline double objectiveOffset() const { return objectiveOffset_; } /// Starts of each column inline CoinBigIndex * startColumn() const { return startColumn_; } /// rows inline int * row() const { return row_; } /// elements inline double * element() const { return element_; } /// costs inline double * cost() const { return cost_; } /// full starts inline int * fullStart() const { return fullStart_; } /// ids of active columns (just index here) inline int * id() const { return id_; } /// Optional lower bounds on columns inline double * lowerColumn() const { return lowerColumn_; } /// Optional upper bounds on columns inline double * upperColumn() const { return upperColumn_; } /// Optional true lower bounds on sets inline double * lowerSet() const { return lowerSet_; } /// Optional true upper bounds on sets inline double * upperSet() const { return upperSet_; } /// size inline int numberGubColumns() const { return numberGubColumns_; } /// first free inline int firstAvailable() const { return firstAvailable_; } /// set first free inline void setFirstAvailable(int value) { firstAvailable_ = value; } /// first dynamic inline int firstDynamic() const { return firstDynamic_; } /// number of columns in dynamic model inline int lastDynamic() const { return lastDynamic_; } /// size of working matrix (max) inline int numberElements() const { return numberElements_; } /// Status region for gub slacks inline unsigned char * gubRowStatus() const { return status_; } /// Status region for gub variables inline unsigned char * dynamicStatus() const { return dynamicStatus_; } /// Returns which set a variable is in int whichSet (int sequence) const; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Saved value of objective offset double objectiveOffset_; /// Starts of each column CoinBigIndex * startColumn_; /// rows int * row_; /// elements double * element_; /// costs double * cost_; /// full starts int * fullStart_; /// ids of active columns (just index here) int * id_; /// for status and which bound unsigned char * dynamicStatus_; /// Optional lower bounds on columns double * lowerColumn_; /// Optional upper bounds on columns double * upperColumn_; /// Optional true lower bounds on sets double * lowerSet_; /// Optional true upper bounds on sets double * upperSet_; /// size int numberGubColumns_; /// first free int firstAvailable_; /// saved first free int savedFirstAvailable_; /// first dynamic int firstDynamic_; /// number of columns in dynamic model int lastDynamic_; /// size of working matrix (max) int numberElements_; //@} }; #endif Clp-1.15.10/src/ClpPackedMatrix.hpp0000644000076600007660000006720711672453417015414 0ustar coincoin/* $Id: ClpPackedMatrix.hpp 1836 2011-12-15 20:22:39Z 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 ClpPackedMatrix_H #define ClpPackedMatrix_H #include "CoinPragma.hpp" #include "ClpMatrixBase.hpp" // Compilers can produce better code if they know about __restrict #ifndef COIN_RESTRICT #ifdef COIN_USE_RESTRICT #define COIN_RESTRICT __restrict #else #define COIN_RESTRICT #endif #endif /** This implements CoinPackedMatrix as derived from ClpMatrixBase. It adds a few methods that know about model as well as matrix For details see CoinPackedMatrix */ class ClpPackedMatrix2; class ClpPackedMatrix3; class ClpPackedMatrix : public ClpMatrixBase { public: /**@name Useful methods */ //@{ /// Return a complete CoinPackedMatrix virtual CoinPackedMatrix * getPackedMatrix() const { return matrix_; } /** Whether the packed matrix is column major ordered or not. */ virtual bool isColOrdered() const { return matrix_->isColOrdered(); } /** Number of entries in the packed matrix. */ virtual CoinBigIndex getNumElements() const { return matrix_->getNumElements(); } /** Number of columns. */ virtual int getNumCols() const { return matrix_->getNumCols(); } /** Number of rows. */ virtual int getNumRows() const { return matrix_->getNumRows(); } /** A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const double * getElements() const { return matrix_->getElements(); } /// Mutable elements inline double * getMutableElements() const { return matrix_->getMutableElements(); } /** A vector containing the minor indices of the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const int * getIndices() const { return matrix_->getIndices(); } virtual const CoinBigIndex * getVectorStarts() const { return matrix_->getVectorStarts(); } /** The lengths of the major-dimension vectors. */ virtual const int * getVectorLengths() const { return matrix_->getVectorLengths(); } /** The length of a single major-dimension vector. */ virtual int getVectorLength(int index) const { return matrix_->getVectorSize(index); } /** Delete the columns whose indices are listed in indDel. */ virtual void deleteCols(const int numDel, const int * indDel); /** Delete the rows whose indices are listed in indDel. */ virtual void deleteRows(const int numDel, const int * indDel); #ifndef CLP_NO_VECTOR /// Append Columns virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); /// Append Rows virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); #endif /** Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ virtual int appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther = -1); /** Replace the elements of a vector. The indices remain the same. This is only needed if scaling and a row copy is used. At most the number specified will be replaced. The index is between 0 and major dimension of matrix */ virtual void replaceVector(const int index, const int numReplace, const double * newElements) { matrix_->replaceVector(index, numReplace, newElements); } /** Modify one element of packed matrix. An element may be added. This works for either ordering If the new element is zero it will be deleted unless keepZero true */ virtual void modifyCoefficient(int row, int column, double newElement, bool keepZero = false) { matrix_->modifyCoefficient(row, column, newElement, keepZero); } /** Returns a new matrix in reverse order without gaps */ virtual ClpMatrixBase * reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis(const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element); /** Creates scales for column copy (rowCopy in model may be modified) returns non-zero if no scaling done */ virtual int scale(ClpModel * model, const ClpSimplex * baseModel = NULL) const ; /** Scales rowCopy if column copy scaled Only called if scales already exist */ virtual void scaleRowCopy(ClpModel * model) const ; /// Creates scaled column copy if scales exist void createScaledMatrix(ClpSimplex * model) const; /** Realy really scales column copy Only called if scales already exist. Up to user ro delete */ virtual ClpMatrixBase * scaledColumnCopy(ClpModel * model) const ; /** Checks if all elements are in valid range. Can just return true if you are not paranoid. For Clp I will probably expect no zeros. Code can modify matrix to get rid of small elements. check bits (can be turned off to save time) : 1 - check if matrix has gaps 2 - check if zero elements 4 - check and compress duplicates 8 - report on large and small */ virtual bool allElementsInRange(ClpModel * model, double smallest, double largest, int check = 15); /** Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ virtual void rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const ; /** Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const ; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const; /// Allow any parts of a created CoinPackedMatrix to be deleted virtual void releasePackedMatrix() const { } /** Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; /// Says whether it can do partial pricing virtual bool canDoPartialPricing() const; /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /// makes sure active columns correct virtual int refresh(ClpSimplex * model); // Really scale matrix virtual void reallyScale(const double * rowScale, const double * columnScale); /** Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ virtual void setDimensions(int numrows, int numcols); //@} /**@name Matrix times vector methods */ //@{ /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /// And for scaling virtual void times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ virtual void transposeTimes(double scalar, const double * x, double * y) const; /// And for scaling virtual void transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale, double * spare = NULL) const; /** Return y - pi * A in y. @pre pi must be of size numRows() @pre y must be of size numColumns() This just does subset (but puts in correct place in y) */ void transposeTimesSubset( int number, const int * which, const double * pi, double * y, const double * rowScale, const double * columnScale, double * spare = NULL) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x * scalar * A + y in z. Note - If x packed mode - then z packed mode This does by column and knows no gaps Squashes small elements and knows about ClpSimplex */ void transposeTimesByColumn(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex. This version uses row copy*/ virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x *A in z but just for indices in y. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const; /** Returns true if can combine transposeTimes and subsetTransposeTimes and if it would be faster */ virtual bool canCombine(const ClpSimplex * model, const CoinIndexedVector * pi) const; /// Updates two arrays for steepest virtual void transposeTimes2(const ClpSimplex * model, const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * spare, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); /// Updates second array for steepest and does devex weights virtual void subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); /// Sets up an effective RHS void useEffectiveRhs(ClpSimplex * model); #if COIN_LONG_WORK // For long double versions virtual void times(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const ; virtual void transposeTimes(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const ; #endif //@} /**@name Other */ //@{ /// Returns CoinPackedMatrix (non const) inline CoinPackedMatrix * matrix() const { return matrix_; } /** Just sets matrix_ to NULL so it can be used elsewhere. used in GUB */ inline void setMatrixNull() { matrix_ = NULL; } /// Say we want special column copy inline void makeSpecialColumnCopy() { flags_ |= 16; } /// Say we don't want special column copy void releaseSpecialColumnCopy(); /// Are there zeros? inline bool zeros() const { return ((flags_ & 1) != 0); } /// Do we want special column copy inline bool wantsSpecialColumnCopy() const { return ((flags_ & 16) != 0); } /// Flags inline int flags() const { return flags_; } /// Sets flags_ correctly inline void checkGaps() { flags_ = (matrix_->hasGaps()) ? (flags_ | 2) : (flags_ & (~2)); } /// number of active columns (normally same as number of columns) inline int numberActiveColumns() const { return numberActiveColumns_;} /// Set number of active columns (normally same as number of columns) inline void setNumberActiveColumns(int value) { numberActiveColumns_ = value;} //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpPackedMatrix(); /** Destructor */ virtual ~ClpPackedMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpPackedMatrix(const ClpPackedMatrix&); /** The copy constructor from an CoinPackedMatrix. */ ClpPackedMatrix(const CoinPackedMatrix&); /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpPackedMatrix (const ClpPackedMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); ClpPackedMatrix (const CoinPackedMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); /** This takes over ownership (for space reasons) */ ClpPackedMatrix(CoinPackedMatrix * matrix); ClpPackedMatrix& operator=(const ClpPackedMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; /// Copy contents - resizing if necessary - otherwise re-use memory virtual void copy(const ClpPackedMatrix * from); /** Subset clone (without gaps). Duplicates are allowed and order is as given */ virtual ClpMatrixBase * subsetClone ( int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const ; /// make special row copy void specialRowCopy(ClpSimplex * model, const ClpMatrixBase * rowCopy); /// make special column copy void specialColumnCopy(ClpSimplex * model); /// Correct sequence in and out to give true value virtual void correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) ; //@} private: /// Meat of transposeTimes by column when not scaled int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const double tolerance) const; /// Meat of transposeTimes by column when scaled int gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, const double * COIN_RESTRICT columnScale, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const double tolerance) const; /// Meat of transposeTimes by column when not scaled and skipping int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * status, const double tolerance) const; /** Meat of transposeTimes by column when not scaled and skipping and doing part of dualColumn */ int gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * status, int * COIN_RESTRICT spareIndex, double * COIN_RESTRICT spareArray, const double * COIN_RESTRICT reducedCost, double & upperTheta, double & bestPossible, double acceptablePivot, double dualTolerance, int & numberRemaining, const double zeroTolerance) const; /// Meat of transposeTimes by column when scaled and skipping int gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, const double * COIN_RESTRICT columnScale, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * status, const double tolerance) const; /// Meat of transposeTimes by row n > K if packed - returns number nonzero int gutsOfTransposeTimesByRowGEK(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, int numberColumns, const double tolerance, const double scalar) const; /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero int gutsOfTransposeTimesByRowGE3(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, double * COIN_RESTRICT array2, const double tolerance, const double scalar) const; /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero int gutsOfTransposeTimesByRowGE3a(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, int * COIN_RESTRICT lookup, char * COIN_RESTRICT marked, const double tolerance, const double scalar) const; /// Meat of transposeTimes by row n == 2 if packed void gutsOfTransposeTimesByRowEQ2(const CoinIndexedVector * piVector, CoinIndexedVector * output, CoinIndexedVector * spareVector, const double tolerance, const double scalar) const; /// Meat of transposeTimes by row n == 1 if packed void gutsOfTransposeTimesByRowEQ1(const CoinIndexedVector * piVector, CoinIndexedVector * output, const double tolerance, const double scalar) const; /// Gets rid of special copies void clearCopies(); protected: /// Check validity void checkFlags(int type) const; /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Data CoinPackedMatrix * matrix_; /// number of active columns (normally same as number of columns) int numberActiveColumns_; /** Flags - 1 - has zero elements 2 - has gaps 4 - has special row copy 8 - has special column copy 16 - wants special column copy */ mutable int flags_; /// Special row copy ClpPackedMatrix2 * rowCopy_; /// Special column copy ClpPackedMatrix3 * columnCopy_; //@} }; #ifdef THREAD #include typedef struct { double acceptablePivot; const ClpSimplex * model; double * spare; int * spareIndex; double * arrayTemp; int * indexTemp; int * numberInPtr; double * bestPossiblePtr; double * upperThetaPtr; int * posFreePtr; double * freePivotPtr; int * numberOutPtr; const unsigned short * count; const double * pi; const CoinBigIndex * rowStart; const double * element; const unsigned short * column; int offset; int numberInRowArray; int numberLook; } dualColumn0Struct; #endif class ClpPackedMatrix2 { public: /**@name Useful methods */ //@{ /** Return x * -1 * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about ClpSimplex */ void transposeTimes(const ClpSimplex * model, const CoinPackedMatrix * rowCopy, const CoinIndexedVector * x, CoinIndexedVector * spareArray, CoinIndexedVector * z) const; /// Returns true if copy has useful information inline bool usefulInfo() const { return rowStart_ != NULL; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpPackedMatrix2(); /** Constructor from copy. */ ClpPackedMatrix2(ClpSimplex * model, const CoinPackedMatrix * rowCopy); /** Destructor */ virtual ~ClpPackedMatrix2(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpPackedMatrix2(const ClpPackedMatrix2&); ClpPackedMatrix2& operator=(const ClpPackedMatrix2&); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Number of blocks int numberBlocks_; /// Number of rows int numberRows_; /// Column offset for each block (plus one at end) int * offset_; /// Counts of elements in each part of row mutable unsigned short * count_; /// Row starts mutable CoinBigIndex * rowStart_; /// columns within block unsigned short * column_; /// work arrays double * work_; #ifdef THREAD pthread_t * threadId_; dualColumn0Struct * info_; #endif //@} }; typedef struct { CoinBigIndex startElements_; // point to data int startIndices_; // point to column_ int numberInBlock_; int numberPrice_; // at beginning int numberElements_; // number elements per column } blockStruct; class ClpPackedMatrix3 { public: /**@name Useful methods */ //@{ /** Return x * -1 * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about ClpSimplex */ void transposeTimes(const ClpSimplex * model, const double * pi, CoinIndexedVector * output) const; /// Updates two arrays for steepest void transposeTimes2(const ClpSimplex * model, const double * pi, CoinIndexedVector * dj1, const double * piWeight, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpPackedMatrix3(); /** Constructor from copy. */ ClpPackedMatrix3(ClpSimplex * model, const CoinPackedMatrix * columnCopy); /** Destructor */ virtual ~ClpPackedMatrix3(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpPackedMatrix3(const ClpPackedMatrix3&); ClpPackedMatrix3& operator=(const ClpPackedMatrix3&); //@} /**@name Sort methods */ //@{ /** Sort blocks */ void sortBlocks(const ClpSimplex * model); /// Swap one variable void swapOne(const ClpSimplex * model, const ClpPackedMatrix * matrix, int iColumn); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Number of blocks int numberBlocks_; /// Number of columns int numberColumns_; /// Column indices and reverse lookup (within block) int * column_; /// Starts for odd/long vectors CoinBigIndex * start_; /// Rows int * row_; /// Elements double * element_; /// Blocks (ordinary start at 0 and go to first block) blockStruct * block_; //@} }; #endif Clp-1.15.10/src/ClpNetworkBasis.hpp0000644000076600007660000001112511552534715015435 0ustar coincoin/* $Id: ClpNetworkBasis.hpp 1722 2011-04-17 09:58:37Z 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). /* Authors John Forrest */ #ifndef ClpNetworkBasis_H #define ClpNetworkBasis_H class ClpMatrixBase; class CoinIndexedVector; class ClpSimplex; #include "CoinTypes.hpp" #ifndef COIN_FAST_CODE #define COIN_FAST_CODE #endif /** This deals with Factorization and Updates for network structures */ class ClpNetworkBasis { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpNetworkBasis ( ); /// Constructor from CoinFactorization ClpNetworkBasis(const ClpSimplex * model, int numberRows, const CoinFactorizationDouble * pivotRegion, const int * permuteBack, const CoinBigIndex * startColumn, const int * numberInColumn, const int * indexRow, const CoinFactorizationDouble * element); /// Copy constructor ClpNetworkBasis ( const ClpNetworkBasis &other); /// Destructor ~ClpNetworkBasis ( ); /// = copy ClpNetworkBasis & operator = ( const ClpNetworkBasis & other ); //@} /**@name Do factorization */ //@{ /** When part of LP - given by basic variables. Actually does factorization. Arrays passed in have non negative value to say basic. If status is okay, basic variables have pivot row - this is only needed if increasingRows_ >1. If status is singular, then basic variables have pivot row and ones thrown out have -1 returns 0 -okay, -1 singular, -2 too many in basis */ int factorize ( const ClpMatrixBase * matrix, int rowIsBasic[], int columnIsBasic[]); //@} /**@name rank one updates which do exist */ //@{ /** Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular!! */ int replaceColumn ( CoinIndexedVector * column, int pivotRow); //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ //@{ /** Updates one column (FTRAN) from region, Returns pivot value if "pivotRow" >=0 */ double updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, int pivotRow); /** Updates one column (FTRAN) to/from array ** For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. rhs) */ int updateColumn ( CoinIndexedVector * regionSparse, double array[] ) const; /** Updates one column transpose (BTRAN) ** For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. dense objective) returns number of nonzeros */ int updateColumnTranspose ( CoinIndexedVector * regionSparse, double array[] ) const; /** Updates one column (BTRAN) from region2 */ int updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const; //@} ////////////////// data ////////////////// private: // checks looks okay void check(); // prints data void print(); /**@name data */ //@{ #ifndef COIN_FAST_CODE /// Whether slack value is +1 or -1 double slackValue_; #endif /// Number of Rows in factorization int numberRows_; /// Number of Columns in factorization int numberColumns_; /// model const ClpSimplex * model_; /// Parent for each column int * parent_; /// Descendant int * descendant_; /// Pivot row int * pivot_; /// Right sibling int * rightSibling_; /// Left sibling int * leftSibling_; /// Sign of pivot double * sign_; /// Stack int * stack_; /// Permute into array int * permute_; /// Permute back array int * permuteBack_; /// Second stack int * stack2_; /// Depth int * depth_; /// To mark rows char * mark_; //@} }; #endif Clp-1.15.10/src/Idiot.cpp0000644000076600007660000024037012252354371013430 0ustar coincoin/* $Id: Idiot.cpp 2006 2013-12-12 15:40: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). #include "CoinPragma.hpp" #include #include #include #include #include "ClpPresolve.hpp" #include "Idiot.hpp" #include "CoinTime.hpp" #include "CoinSort.hpp" #include "CoinMessageHandler.hpp" #include "CoinHelperFunctions.hpp" #include "AbcCommon.hpp" // Redefine stuff for Clp #ifndef OSI_IDIOT #include "ClpMessage.hpp" #define OsiObjOffset ClpObjOffset #endif /**** strategy 4 - drop, exitDrop and djTolerance all relative: For first two major iterations these are small. Then: drop - exit a major iteration if drop over 5*checkFrequency < this is used as info->drop*(10.0+fabs(last weighted objective)) exitDrop - exit idiot if feasible and drop < this is used as info->exitDrop*(10.0+fabs(last objective)) djExit - exit a major iteration if largest dj (averaged over 5 checks) drops below this - used as info->djTolerance*(10.0+fabs(last weighted objective) djFlag - mostly skip variables with bad dj worse than this => 2*djExit djTol - only look at variables with dj better than this => 0.01*djExit ****************/ #define IDIOT_FIX_TOLERANCE 1e-6 #define SMALL_IDIOT_FIX_TOLERANCE 1e-10 int Idiot::dropping(IdiotResult result, double tolerance, double small, int *nbad) { if (result.infeas <= small) { double value = CoinMax(fabs(result.objval), fabs(result.dropThis)) + 1.0; if (result.dropThis > tolerance * value) { *nbad = 0; return 1; } else { (*nbad)++; if (*nbad > 4) { return 0; } else { return 1; } } } else { *nbad = 0; return 1; } } // Deals with whenUsed and slacks int Idiot::cleanIteration(int iteration, int ordinaryStart, int ordinaryEnd, double * colsol, const double * lower, const double * upper, const double * rowLower, const double * rowUpper, const double * cost, const double * element, double fixTolerance, double & objValue, double & infValue) { int n = 0; if ((strategy_ & 16384) == 0) { for (int i = ordinaryStart; i < ordinaryEnd; i++) { if (colsol[i] > lower[i] + fixTolerance) { if (colsol[i] < upper[i] - fixTolerance) { n++; } else { colsol[i] = upper[i]; } whenUsed_[i] = iteration; } else { colsol[i] = lower[i]; } } return n; } else { #ifdef COIN_DEVELOP printf("entering inf %g, obj %g\n", infValue, objValue); #endif int nrows = model_->getNumRows(); int ncols = model_->getNumCols(); int * posSlack = whenUsed_ + ncols; int * negSlack = posSlack + nrows; int * nextSlack = negSlack + nrows; double * rowsol = reinterpret_cast (nextSlack + ncols); memset(rowsol, 0, nrows * sizeof(double)); #ifdef OSI_IDIOT const CoinPackedMatrix * matrix = model_->getMatrixByCol(); #else ClpMatrixBase * matrix = model_->clpMatrix(); #endif const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); //const double * element = matrix->getElements(); int i; objValue = 0.0; infValue = 0.0; for ( i = 0; i < ncols; i++) { if (nextSlack[i] == -1) { // not a slack if (colsol[i] > lower[i] + fixTolerance) { if (colsol[i] < upper[i] - fixTolerance) { n++; whenUsed_[i] = iteration; } else { colsol[i] = upper[i]; } whenUsed_[i] = iteration; } else { colsol[i] = lower[i]; } double value = colsol[i]; if (value) { objValue += cost[i] * value; CoinBigIndex j; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowsol[iRow] += value * element[j]; } } } } // temp fix for infinite lbs - just limit to -1000 for (i = 0; i < nrows; i++) { double rowSave = rowsol[i]; int iCol; iCol = posSlack[i]; if (iCol >= 0) { // slide all slack down double rowValue = rowsol[i]; CoinBigIndex j = columnStart[iCol]; double lowerValue = CoinMax(CoinMin(colsol[iCol], 0.0) - 1000.0, lower[iCol]); rowSave += (colsol[iCol] - lowerValue) * element[j]; colsol[iCol] = lowerValue; while (nextSlack[iCol] >= 0) { iCol = nextSlack[iCol]; double lowerValue = CoinMax(CoinMin(colsol[iCol], 0.0) - 1000.0, lower[iCol]); j = columnStart[iCol]; rowSave += (colsol[iCol] - lowerValue) * element[j]; colsol[iCol] = lowerValue; } iCol = posSlack[i]; while (rowValue < rowLower[i] && iCol >= 0) { // want to increase double distance = rowLower[i] - rowValue; double value = element[columnStart[iCol]]; double thisCost = cost[iCol]; if (distance <= value*(upper[iCol] - colsol[iCol])) { // can get there double movement = distance / value; objValue += movement * thisCost; rowValue = rowLower[i]; colsol[iCol] += movement; } else { // can't get there double movement = upper[iCol] - colsol[iCol]; objValue += movement * thisCost; rowValue += movement * value; colsol[iCol] = upper[iCol]; iCol = nextSlack[iCol]; } } if (iCol >= 0) { // may want to carry on - because of cost? while (iCol >= 0 && cost[iCol] < 0 && rowValue < rowUpper[i]) { // want to increase double distance = rowUpper[i] - rowValue; double value = element[columnStart[iCol]]; double thisCost = cost[iCol]; if (distance <= value*(upper[iCol] - colsol[iCol])) { // can get there double movement = distance / value; objValue += movement * thisCost; rowValue = rowUpper[i]; colsol[iCol] += movement; iCol = -1; } else { // can't get there double movement = upper[iCol] - colsol[iCol]; objValue += movement * thisCost; rowValue += movement * value; colsol[iCol] = upper[iCol]; iCol = nextSlack[iCol]; } } if (iCol >= 0 && colsol[iCol] > lower[iCol] + fixTolerance && colsol[iCol] < upper[iCol] - fixTolerance) { whenUsed_[i] = iteration; n++; } } rowsol[i] = rowValue; } iCol = negSlack[i]; if (iCol >= 0) { // slide all slack down double rowValue = rowsol[i]; CoinBigIndex j = columnStart[iCol]; double lowerValue = CoinMax(CoinMin(colsol[iCol], 0.0) - 1000.0, lower[iCol]); rowSave += (colsol[iCol] - lowerValue) * element[j]; colsol[iCol] = lowerValue; while (nextSlack[iCol] >= 0) { iCol = nextSlack[iCol]; j = columnStart[iCol]; double lowerValue = CoinMax(CoinMin(colsol[iCol], 0.0) - 1000.0, lower[iCol]); rowSave += (colsol[iCol] - lowerValue) * element[j]; colsol[iCol] = lowerValue; } iCol = negSlack[i]; while (rowValue > rowUpper[i] && iCol >= 0) { // want to increase double distance = -(rowUpper[i] - rowValue); double value = -element[columnStart[iCol]]; double thisCost = cost[iCol]; if (distance <= value*(upper[iCol] - lower[iCol])) { // can get there double movement = distance / value; objValue += movement * thisCost; rowValue = rowUpper[i]; colsol[iCol] += movement; } else { // can't get there double movement = upper[iCol] - lower[iCol]; objValue += movement * thisCost; rowValue -= movement * value; colsol[iCol] = upper[iCol]; iCol = nextSlack[iCol]; } } if (iCol >= 0) { // may want to carry on - because of cost? while (iCol >= 0 && cost[iCol] < 0 && rowValue > rowLower[i]) { // want to increase double distance = -(rowLower[i] - rowValue); double value = -element[columnStart[iCol]]; double thisCost = cost[iCol]; if (distance <= value*(upper[iCol] - colsol[iCol])) { // can get there double movement = distance / value; objValue += movement * thisCost; rowValue = rowLower[i]; colsol[iCol] += movement; iCol = -1; } else { // can't get there double movement = upper[iCol] - colsol[iCol]; objValue += movement * thisCost; rowValue -= movement * value; colsol[iCol] = upper[iCol]; iCol = nextSlack[iCol]; } } if (iCol >= 0 && colsol[iCol] > lower[iCol] + fixTolerance && colsol[iCol] < upper[iCol] - fixTolerance) { whenUsed_[i] = iteration; n++; } } rowsol[i] = rowValue; } infValue += CoinMax(CoinMax(0.0, rowLower[i] - rowsol[i]), rowsol[i] - rowUpper[i]); // just change rowsol[i] -= rowSave; } return n; } } /* returns -1 if none or start of costed slacks or -2 if there are costed slacks but it is messy */ static int countCostedSlacks(OsiSolverInterface * model) { #ifdef OSI_IDIOT const CoinPackedMatrix * matrix = model->getMatrixByCol(); #else ClpMatrixBase * matrix = model->clpMatrix(); #endif const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); const double * rowupper = model->getRowUpper(); int nrows = model->getNumRows(); int ncols = model->getNumCols(); int slackStart = ncols - nrows; int nSlacks = nrows; int i; if (ncols <= nrows) return -1; while (1) { for (i = 0; i < nrows; i++) { int j = i + slackStart; CoinBigIndex k = columnStart[j]; if (columnLength[j] == 1) { if (row[k] != i || element[k] != 1.0) { nSlacks = 0; break; } } else { nSlacks = 0; break; } if (rowupper[i] <= 0.0) { nSlacks = 0; break; } } if (nSlacks || !slackStart) break; slackStart = 0; } if (!nSlacks) slackStart = -1; return slackStart; } void Idiot::crash(int numberPass, CoinMessageHandler * handler, const CoinMessages *messages, bool doCrossover) { // lightweight options int numberColumns = model_->getNumCols(); const double * objective = model_->getObjCoefficients(); int nnzero = 0; double sum = 0.0; int i; for (i = 0; i < numberColumns; i++) { if (objective[i]) { sum += fabs(objective[i]); nnzero++; } } sum /= static_cast (nnzero + 1); if (maxIts_ == 5) maxIts_ = 2; if (numberPass <= 0) majorIterations_ = static_cast(2 + log10(static_cast(numberColumns + 1))); else majorIterations_ = numberPass; // If mu not changed then compute if (mu_ == 1e-4) mu_ = CoinMax(1.0e-3, sum * 1.0e-5); if (maxIts2_ == 100) { if (!lightWeight_) { maxIts2_ = 105; } else if (lightWeight_ == 1) { mu_ *= 1000.0; maxIts2_ = 23; } else if (lightWeight_ == 2) { maxIts2_ = 11; } else { maxIts2_ = 23; } } //printf("setting mu to %g and doing %d passes\n",mu_,majorIterations_); solve2(handler, messages); #ifndef OSI_IDIOT if (doCrossover) { double averageInfeas = model_->sumPrimalInfeasibilities() / static_cast (model_->numberRows()); if ((averageInfeas < 0.01 && (strategy_ & 512) != 0) || (strategy_ & 8192) != 0) crossOver(16 + 1); else crossOver(majorIterations_ < 1000000 ? 3 : 2); } #endif } void Idiot::solve() { CoinMessages dummy; solve2(NULL, &dummy); } void Idiot::solve2(CoinMessageHandler * handler, const CoinMessages * messages) { int strategy = 0; double d2; int i, n; int allOnes = 1; int iteration = 0; int iterationTotal = 0; int nTry = 0; /* number of tries at same weight */ double fixTolerance = IDIOT_FIX_TOLERANCE; int maxBigIts = maxBigIts_; int maxIts = maxIts_; int logLevel = logLevel_; int saveMajorIterations = majorIterations_; majorIterations_ = majorIterations_ % 1000000; if (handler) { if (handler->logLevel() > 0 && handler->logLevel() < 3) logLevel = 1; else if (!handler->logLevel()) logLevel = 0; else logLevel = 7; } double djExit = djTolerance_; double djFlag = 1.0 + 100.0 * djExit; double djTol = 0.00001; double mu = mu_; double drop = drop_; int maxIts2 = maxIts2_; double factor = muFactor_; double smallInfeas = smallInfeas_; double reasonableInfeas = reasonableInfeas_; double stopMu = stopMu_; double maxmin, offset; double lastWeighted = 1.0e50; double exitDrop = exitDrop_; double fakeSmall = smallInfeas; double firstInfeas; int badIts = 0; int slackStart, ordStart, ordEnd; int checkIteration = 0; int lambdaIteration = 0; int belowReasonable = 0; /* set if ever gone below reasonable infeas */ double bestWeighted = 1.0e60; double bestFeasible = 1.0e60; /* best solution while feasible */ IdiotResult result, lastResult; int saveStrategy = strategy_; const int strategies[] = {0, 2, 128}; double saveLambdaScale = 0.0; if ((saveStrategy & 128) != 0) { fixTolerance = SMALL_IDIOT_FIX_TOLERANCE; } #ifdef OSI_IDIOT const CoinPackedMatrix * matrix = model_->getMatrixByCol(); #else ClpMatrixBase * matrix = model_->clpMatrix(); #endif const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); int nrows = model_->getNumRows(); int ncols = model_->getNumCols(); double * rowsol, * colsol; double * pi, * dj; #ifndef OSI_IDIOT double * cost = model_->objective(); double * lower = model_->columnLower(); double * upper = model_->columnUpper(); #else double * cost = new double [ncols]; CoinMemcpyN( model_->getObjCoefficients(), ncols, cost); const double * lower = model_->getColLower(); const double * upper = model_->getColUpper(); #endif const double *elemXX; double * saveSol; double * rowupper = new double[nrows]; // not const as modified CoinMemcpyN(model_->getRowUpper(), nrows, rowupper); double * rowlower = new double[nrows]; // not const as modified CoinMemcpyN(model_->getRowLower(), nrows, rowlower); CoinThreadRandom * randomNumberGenerator = model_->randomNumberGenerator(); int * whenUsed; double * lambda; saveSol = new double[ncols]; lambda = new double [nrows]; rowsol = new double[nrows]; colsol = new double [ncols]; CoinMemcpyN(model_->getColSolution(), ncols, colsol); pi = new double[nrows]; dj = new double[ncols]; delete [] whenUsed_; bool oddSlacks = false; // See if any costed slacks int numberSlacks = 0; for (i = 0; i < ncols; i++) { if (columnLength[i] == 1) numberSlacks++; } if (!numberSlacks) { whenUsed_ = new int[ncols]; } else { #ifdef COIN_DEVELOP printf("%d slacks\n", numberSlacks); #endif oddSlacks = true; int extra = static_cast (nrows * sizeof(double) / sizeof(int)); whenUsed_ = new int[2*ncols+2*nrows+extra]; int * posSlack = whenUsed_ + ncols; int * negSlack = posSlack + nrows; int * nextSlack = negSlack + nrows; for (i = 0; i < nrows; i++) { posSlack[i] = -1; negSlack[i] = -1; } for (i = 0; i < ncols; i++) nextSlack[i] = -1; for (i = 0; i < ncols; i++) { if (columnLength[i] == 1) { CoinBigIndex j = columnStart[i]; int iRow = row[j]; if (element[j] > 0.0) { if (posSlack[iRow] == -1) { posSlack[iRow] = i; } else { int iCol = posSlack[iRow]; while (nextSlack[iCol] >= 0) iCol = nextSlack[iCol]; nextSlack[iCol] = i; } } else { if (negSlack[iRow] == -1) { negSlack[iRow] = i; } else { int iCol = negSlack[iRow]; while (nextSlack[iCol] >= 0) iCol = nextSlack[iCol]; nextSlack[iCol] = i; } } } } // now sort for (i = 0; i < nrows; i++) { int iCol; iCol = posSlack[i]; if (iCol >= 0) { CoinBigIndex j = columnStart[iCol]; #ifndef NDEBUG int iRow = row[j]; #endif assert (element[j] > 0.0); assert (iRow == i); dj[0] = cost[iCol] / element[j]; whenUsed_[0] = iCol; int n = 1; while (nextSlack[iCol] >= 0) { iCol = nextSlack[iCol]; CoinBigIndex j = columnStart[iCol]; #ifndef NDEBUG int iRow = row[j]; #endif assert (element[j] > 0.0); assert (iRow == i); dj[n] = cost[iCol] / element[j]; whenUsed_[n++] = iCol; } for (j = 0; j < n; j++) { int jCol = whenUsed_[j]; nextSlack[jCol] = -2; } CoinSort_2(dj, dj + n, whenUsed_); // put back iCol = whenUsed_[0]; posSlack[i] = iCol; for (j = 1; j < n; j++) { int jCol = whenUsed_[j]; nextSlack[iCol] = jCol; iCol = jCol; } } iCol = negSlack[i]; if (iCol >= 0) { CoinBigIndex j = columnStart[iCol]; #ifndef NDEBUG int iRow = row[j]; #endif assert (element[j] < 0.0); assert (iRow == i); dj[0] = -cost[iCol] / element[j]; whenUsed_[0] = iCol; int n = 1; while (nextSlack[iCol] >= 0) { iCol = nextSlack[iCol]; CoinBigIndex j = columnStart[iCol]; #ifndef NDEBUG int iRow = row[j]; #endif assert (element[j] < 0.0); assert (iRow == i); dj[n] = -cost[iCol] / element[j]; whenUsed_[n++] = iCol; } for (j = 0; j < n; j++) { int jCol = whenUsed_[j]; nextSlack[jCol] = -2; } CoinSort_2(dj, dj + n, whenUsed_); // put back iCol = whenUsed_[0]; negSlack[i] = iCol; for (j = 1; j < n; j++) { int jCol = whenUsed_[j]; nextSlack[iCol] = jCol; iCol = jCol; } } } } whenUsed = whenUsed_; if (model_->getObjSense() == -1.0) { maxmin = -1.0; } else { maxmin = 1.0; } model_->getDblParam(OsiObjOffset, offset); if (!maxIts2) maxIts2 = maxIts; strategy = strategy_; strategy &= 3; memset(lambda, 0, nrows * sizeof(double)); slackStart = countCostedSlacks(model_); if (slackStart >= 0) { COIN_DETAIL_PRINT(printf("This model has costed slacks\n")); if (slackStart) { ordStart = 0; ordEnd = slackStart; } else { ordStart = nrows; ordEnd = ncols; } } else { ordStart = 0; ordEnd = ncols; } if (offset && logLevel > 2) { printf("** Objective offset is %g\n", offset); } /* compute reasonable solution cost */ for (i = 0; i < nrows; i++) { rowsol[i] = 1.0e31; } for (i = 0; i < ncols; i++) { CoinBigIndex j; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { if (element[j] != 1.0) { allOnes = 0; break; } } } if (allOnes) { elemXX = NULL; } else { elemXX = element; } // Do scaling if wanted bool scaled = false; #ifndef OSI_IDIOT if ((strategy_ & 32) != 0 && !allOnes) { if (model_->scalingFlag() > 0) scaled = model_->clpMatrix()->scale(model_) == 0; if (scaled) { const double * rowScale = model_->rowScale(); const double * columnScale = model_->columnScale(); double * oldLower = lower; double * oldUpper = upper; double * oldCost = cost; lower = new double[ncols]; upper = new double[ncols]; cost = new double[ncols]; CoinMemcpyN(oldLower, ncols, lower); CoinMemcpyN(oldUpper, ncols, upper); CoinMemcpyN(oldCost, ncols, cost); int icol, irow; for (icol = 0; icol < ncols; icol++) { double multiplier = 1.0 / columnScale[icol]; if (lower[icol] > -1.0e50) lower[icol] *= multiplier; if (upper[icol] < 1.0e50) upper[icol] *= multiplier; colsol[icol] *= multiplier; cost[icol] *= columnScale[icol]; } CoinMemcpyN(model_->rowLower(), nrows, rowlower); for (irow = 0; irow < nrows; irow++) { double multiplier = rowScale[irow]; if (rowlower[irow] > -1.0e50) rowlower[irow] *= multiplier; if (rowupper[irow] < 1.0e50) rowupper[irow] *= multiplier; rowsol[irow] *= multiplier; } int length = columnStart[ncols-1] + columnLength[ncols-1]; double * elemYY = new double[length]; for (i = 0; i < ncols; i++) { CoinBigIndex j; double scale = columnScale[i]; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; elemYY[j] = element[j] * scale * rowScale[irow]; } } elemXX = elemYY; } } #endif for (i = 0; i < ncols; i++) { CoinBigIndex j; double dd = columnLength[i]; dd = cost[i] / dd; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; if (dd < rowsol[irow]) { rowsol[irow] = dd; } } } d2 = 0.0; for (i = 0; i < nrows; i++) { d2 += rowsol[i]; } d2 *= 2.0; /* for luck */ d2 = d2 / static_cast (4 * nrows + 8000); d2 *= 0.5; /* halve with more flexible method */ if (d2 < 5.0) d2 = 5.0; if (djExit == 0.0) { djExit = d2; } if ((saveStrategy & 4) != 0) { /* go to relative tolerances - first small */ djExit = 1.0e-10; djFlag = 1.0e-5; drop = 1.0e-10; } memset(whenUsed, 0, ncols * sizeof(int)); strategy = strategies[strategy]; if ((saveStrategy & 8) != 0) strategy |= 64; /* don't allow large theta */ CoinMemcpyN(colsol, ncols, saveSol); lastResult = IdiSolve(nrows, ncols, rowsol , colsol, pi, dj, cost, rowlower, rowupper, lower, upper, elemXX, row, columnStart, columnLength, lambda, 0, mu, drop, maxmin, offset, strategy, djTol, djExit, djFlag, randomNumberGenerator); // update whenUsed_ n = cleanIteration(iteration, ordStart, ordEnd, colsol, lower, upper, rowlower, rowupper, cost, elemXX, fixTolerance, lastResult.objval, lastResult.infeas); if ((strategy_ & 16384) != 0) { int * posSlack = whenUsed_ + ncols; int * negSlack = posSlack + nrows; int * nextSlack = negSlack + nrows; double * rowsol2 = reinterpret_cast (nextSlack + ncols); for (i = 0; i < nrows; i++) rowsol[i] += rowsol2[i]; } if ((logLevel_ & 1) != 0) { #ifndef OSI_IDIOT if (!handler) { #endif printf("Iteration %d infeasibility %g, objective %g - mu %g, its %d, %d interior\n", iteration, lastResult.infeas, lastResult.objval, mu, lastResult.iteration, n); #ifndef OSI_IDIOT } else { handler->message(CLP_IDIOT_ITERATION, *messages) << iteration << lastResult.infeas << lastResult.objval << mu << lastResult.iteration << n << CoinMessageEol; } #endif } int numberBaseTrys = 0; // for first time int numberAway = -1; iterationTotal = lastResult.iteration; firstInfeas = lastResult.infeas; if ((strategy_ & 1024) != 0) reasonableInfeas = 0.5 * firstInfeas; if (lastResult.infeas < reasonableInfeas) lastResult.infeas = reasonableInfeas; double keepinfeas = 1.0e31; double lastInfeas = 1.0e31; double bestInfeas = 1.0e31; while ((mu > stopMu && lastResult.infeas > smallInfeas) || (lastResult.infeas <= smallInfeas && dropping(lastResult, exitDrop, smallInfeas, &badIts)) || checkIteration < 2 || lambdaIteration < lambdaIterations_) { if (lastResult.infeas <= exitFeasibility_) break; iteration++; checkIteration++; if (lastResult.infeas <= smallInfeas && lastResult.objval < bestFeasible) { bestFeasible = lastResult.objval; } if (lastResult.infeas + mu * lastResult.objval < bestWeighted) { bestWeighted = lastResult.objval + mu * lastResult.objval; } if ((saveStrategy & 4096)) strategy |= 256; if ((saveStrategy & 4) != 0 && iteration > 2) { /* go to relative tolerances */ double weighted = 10.0 + fabs(lastWeighted); djExit = djTolerance_ * weighted; djFlag = 2.0 * djExit; drop = drop_ * weighted; djTol = 0.01 * djExit; } CoinMemcpyN(colsol, ncols, saveSol); result = IdiSolve(nrows, ncols, rowsol , colsol, pi, dj, cost, rowlower, rowupper, lower, upper, elemXX, row, columnStart, columnLength, lambda, maxIts, mu, drop, maxmin, offset, strategy, djTol, djExit, djFlag, randomNumberGenerator); n = cleanIteration(iteration, ordStart, ordEnd, colsol, lower, upper, rowlower, rowupper, cost, elemXX, fixTolerance, result.objval, result.infeas); if ((strategy_ & 16384) != 0) { int * posSlack = whenUsed_ + ncols; int * negSlack = posSlack + nrows; int * nextSlack = negSlack + nrows; double * rowsol2 = reinterpret_cast (nextSlack + ncols); for (i = 0; i < nrows; i++) rowsol[i] += rowsol2[i]; } if ((logLevel_ & 1) != 0) { #ifndef OSI_IDIOT if (!handler) { #endif printf("Iteration %d infeasibility %g, objective %g - mu %g, its %d, %d interior\n", iteration, result.infeas, result.objval, mu, result.iteration, n); #ifndef OSI_IDIOT } else { handler->message(CLP_IDIOT_ITERATION, *messages) << iteration << result.infeas << result.objval << mu << result.iteration << n << CoinMessageEol; } #endif } if (iteration > 50 && n == numberAway ) { if((result.infeas < 1.0e-4 && majorIterations_<200)||result.infeas<1.0e-8) { #ifdef CLP_INVESTIGATE printf("infeas small %g\n", result.infeas); #endif break; // not much happening } } if (lightWeight_ == 1 && iteration > 10 && result.infeas > 1.0 && maxIts != 7) { if (lastInfeas != bestInfeas && CoinMin(result.infeas, lastInfeas) > 0.95 * bestInfeas) majorIterations_ = CoinMin(majorIterations_, iteration); // not getting feasible } lastInfeas = result.infeas; numberAway = n; keepinfeas = result.infeas; lastWeighted = result.weighted; iterationTotal += result.iteration; if (iteration == 1) { if ((strategy_ & 1024) != 0 && mu < 1.0e-10) result.infeas = firstInfeas * 0.8; if (majorIterations_ >= 50 || dropEnoughFeasibility_ <= 0.0) result.infeas *= 0.8; if (result.infeas > firstInfeas * 0.9 && result.infeas > reasonableInfeas) { iteration--; if (majorIterations_ < 50) mu *= 1.0e-1; else mu *= 0.7; bestFeasible = 1.0e31; bestWeighted = 1.0e60; numberBaseTrys++; if (mu < 1.0e-30 || (numberBaseTrys > 10 && lightWeight_)) { // back to all slack basis lightWeight_ = 2; break; } CoinMemcpyN(saveSol, ncols, colsol); } else { maxIts = maxIts2; checkIteration = 0; if ((strategy_ & 1024) != 0) mu *= 1.0e-1; } } else { } bestInfeas = CoinMin(bestInfeas, result.infeas); if (majorIterations_>100&&majorIterations_<200) { if (iteration==majorIterations_-100) { // redo double muX=mu*10.0; bestInfeas=1.0e3; mu=muX; nTry=0; } } if (iteration) { /* this code is in to force it to terminate sometime */ double changeMu = factor; if ((saveStrategy & 64) != 0) { keepinfeas = 0.0; /* switch off ranga's increase */ fakeSmall = smallInfeas; } else { fakeSmall = -1.0; } saveLambdaScale = 0.0; if (result.infeas > reasonableInfeas || (nTry + 1 == maxBigIts && result.infeas > fakeSmall)) { if (result.infeas > lastResult.infeas*(1.0 - dropEnoughFeasibility_) || nTry + 1 == maxBigIts || (result.infeas > lastResult.infeas * 0.9 && result.weighted > lastResult.weighted - dropEnoughWeighted_ * CoinMax(fabs(lastResult.weighted), fabs(result.weighted)))) { mu *= changeMu; if ((saveStrategy & 32) != 0 && result.infeas < reasonableInfeas && 0) { reasonableInfeas = CoinMax(smallInfeas, reasonableInfeas * sqrt(changeMu)); COIN_DETAIL_PRINT(printf("reasonable infeas now %g\n", reasonableInfeas)); } result.weighted = 1.0e60; nTry = 0; bestFeasible = 1.0e31; bestWeighted = 1.0e60; checkIteration = 0; lambdaIteration = 0; #define LAMBDA #ifdef LAMBDA if ((saveStrategy & 2048) == 0) { memset(lambda, 0, nrows * sizeof(double)); } #else memset(lambda, 0, nrows * sizeof(double)); #endif } else { nTry++; } } else if (lambdaIterations_ >= 0) { /* update lambda */ double scale = 1.0 / mu; int i, nnz = 0; saveLambdaScale = scale; lambdaIteration++; if ((saveStrategy & 4) == 0) drop = drop_ / 50.0; if (lambdaIteration > 4 && (((lambdaIteration % 10) == 0 && smallInfeas < keepinfeas) || ((lambdaIteration % 5) == 0 && 1.5 * smallInfeas < keepinfeas))) { //printf(" Increasing smallInfeas from %f to %f\n",smallInfeas,1.5*smallInfeas); smallInfeas *= 1.5; } if ((saveStrategy & 2048) == 0) { for (i = 0; i < nrows; i++) { if (lambda[i]) nnz++; lambda[i] += scale * rowsol[i]; } } else { nnz = 1; #ifdef LAMBDA for (i = 0; i < nrows; i++) { lambda[i] += scale * rowsol[i]; } #else for (i = 0; i < nrows; i++) { lambda[i] = scale * rowsol[i]; } for (i = 0; i < ncols; i++) { CoinBigIndex j; double value = cost[i] * maxmin; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; value += element[j] * lambda[irow]; } cost[i] = value * maxmin; } for (i = 0; i < nrows; i++) { offset += lambda[i] * rowupper[i]; lambda[i] = 0.0; } #ifdef DEBUG printf("offset %g\n", offset); #endif model_->setDblParam(OsiObjOffset, offset); #endif } nTry++; if (!nnz) { bestFeasible = 1.0e32; bestWeighted = 1.0e60; checkIteration = 0; result.weighted = 1.0e31; } #ifdef DEBUG double trueCost = 0.0; for (i = 0; i < ncols; i++) { int j; trueCost += cost[i] * colsol[i]; } printf("True objective %g\n", trueCost - offset); #endif } else { nTry++; } lastResult = result; if (result.infeas < reasonableInfeas && !belowReasonable) { belowReasonable = 1; bestFeasible = 1.0e32; bestWeighted = 1.0e60; checkIteration = 0; result.weighted = 1.0e31; } } if (iteration >= majorIterations_) { // If not feasible and crash then dive dive dive if (mu > 1.0e-12 && result.infeas > 1.0 && majorIterations_ < 40) { mu = 1.0e-30; majorIterations_ = iteration + 1; stopMu = 0.0; } else { if (logLevel > 2) printf("Exiting due to number of major iterations\n"); break; } } } majorIterations_ = saveMajorIterations; #ifndef OSI_IDIOT if (scaled) { // Scale solution and free arrays const double * rowScale = model_->rowScale(); const double * columnScale = model_->columnScale(); int icol, irow; for (icol = 0; icol < ncols; icol++) { colsol[icol] *= columnScale[icol]; saveSol[icol] *= columnScale[icol]; dj[icol] /= columnScale[icol]; } for (irow = 0; irow < nrows; irow++) { rowsol[irow] /= rowScale[irow]; pi[irow] *= rowScale[irow]; } // Don't know why getting Microsoft problems #if defined (_MSC_VER) delete [] ( double *) elemXX; #else delete [] elemXX; #endif model_->setRowScale(NULL); model_->setColumnScale(NULL); delete [] lower; delete [] upper; delete [] cost; lower = model_->columnLower(); upper = model_->columnUpper(); cost = model_->objective(); //rowlower = model_->rowLower(); } #endif #define TRYTHIS #ifdef TRYTHIS if ((saveStrategy & 2048) != 0) { double offset; model_->getDblParam(OsiObjOffset, offset); for (i = 0; i < ncols; i++) { CoinBigIndex j; double djval = cost[i] * maxmin; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; djval -= element[j] * lambda[irow]; } cost[i] = djval; } for (i = 0; i < nrows; i++) { offset += lambda[i] * rowupper[i]; } model_->setDblParam(OsiObjOffset, offset); } #endif if (saveLambdaScale) { /* back off last update */ for (i = 0; i < nrows; i++) { lambda[i] -= saveLambdaScale * rowsol[i]; } } muAtExit_ = mu; // For last iteration make as feasible as possible if (oddSlacks && (strategy_&32768)==0) strategy_ |= 16384; // not scaled n = cleanIteration(iteration, ordStart, ordEnd, colsol, lower, upper, model_->rowLower(), model_->rowUpper(), cost, element, fixTolerance, lastResult.objval, lastResult.infeas); #if 0 if ((logLevel & 1) == 0 || (strategy_ & 16384) != 0) { printf( "%d - mu %g, infeasibility %g, objective %g, %d interior\n", iteration, mu, lastResult.infeas, lastResult.objval, n); } #endif #ifndef OSI_IDIOT model_->setSumPrimalInfeasibilities(lastResult.infeas); #endif // Put back more feasible solution double saveInfeas[] = {0.0, 0.0}; for (int iSol = 0; iSol < 3; iSol++) { const double * solution = iSol ? colsol : saveSol; if (iSol == 2 && saveInfeas[0] < saveInfeas[1]) { // put back best solution CoinMemcpyN(saveSol, ncols, colsol); } double large = 0.0; int i; memset(rowsol, 0, nrows * sizeof(double)); for (i = 0; i < ncols; i++) { CoinBigIndex j; double value = solution[i]; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; rowsol[irow] += element[j] * value; } } for (i = 0; i < nrows; i++) { if (rowsol[i] > rowupper[i]) { double diff = rowsol[i] - rowupper[i]; if (diff > large) large = diff; } else if (rowsol[i] < rowlower[i]) { double diff = rowlower[i] - rowsol[i]; if (diff > large) large = diff; } } if (iSol < 2) saveInfeas[iSol] = large; if (logLevel > 2) printf("largest infeasibility is %g\n", large); } /* subtract out lambda */ for (i = 0; i < nrows; i++) { pi[i] -= lambda[i]; } for (i = 0; i < ncols; i++) { CoinBigIndex j; double djval = cost[i] * maxmin; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; djval -= element[j] * pi[irow]; } dj[i] = djval; } if ((strategy_ & 1024) != 0) { double ratio = static_cast (ncols) / static_cast (nrows); COIN_DETAIL_PRINT(printf("col/row ratio %g infeas ratio %g\n", ratio, lastResult.infeas / firstInfeas)); if (lastResult.infeas > 0.01 * firstInfeas * ratio) { strategy_ &= (~1024); COIN_DETAIL_PRINT(printf(" - layer off\n")); } else { COIN_DETAIL_PRINT(printf(" - layer on\n")); } } delete [] saveSol; delete [] lambda; // save solution // duals not much use - but save anyway #ifndef OSI_IDIOT CoinMemcpyN(rowsol, nrows, model_->primalRowSolution()); CoinMemcpyN(colsol, ncols, model_->primalColumnSolution()); CoinMemcpyN(pi, nrows, model_->dualRowSolution()); CoinMemcpyN(dj, ncols, model_->dualColumnSolution()); #else model_->setColSolution(colsol); model_->setRowPrice(pi); delete [] cost; #endif delete [] rowsol; delete [] colsol; delete [] pi; delete [] dj; delete [] rowlower; delete [] rowupper; return ; } #ifndef OSI_IDIOT void Idiot::crossOver(int mode) { if (lightWeight_ == 2) { // total failure model_->allSlackBasis(); return; } double fixTolerance = IDIOT_FIX_TOLERANCE; #ifdef COIN_DEVELOP double startTime = CoinCpuTime(); #endif ClpSimplex * saveModel = NULL; ClpMatrixBase * matrix = model_->clpMatrix(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); const double * rowupper = model_->getRowUpper(); int nrows = model_->getNumRows(); int ncols = model_->getNumCols(); double * rowsol, * colsol; // different for Osi double * lower = model_->columnLower(); double * upper = model_->columnUpper(); const double * rowlower = model_->getRowLower(); int * whenUsed = whenUsed_; rowsol = model_->primalRowSolution(); colsol = model_->primalColumnSolution();; double * cost = model_->objective(); int slackEnd, ordStart, ordEnd; int slackStart = countCostedSlacks(model_); int addAll = mode & 7; int presolve = 0; double djTolerance = djTolerance_; if (djTolerance > 0.0 && djTolerance < 1.0) djTolerance = 1.0; int iteration; int i, n = 0; double ratio = 1.0; double objValue = 0.0; if ((strategy_ & 128) != 0) { fixTolerance = SMALL_IDIOT_FIX_TOLERANCE; } if ((mode & 16) != 0 && addAll < 3) presolve = 1; double * saveUpper = NULL; double * saveLower = NULL; double * saveRowUpper = NULL; double * saveRowLower = NULL; bool allowInfeasible = ((strategy_ & 8192) != 0) || (majorIterations_ > 1000000); if (addAll < 3) { saveUpper = new double [ncols]; saveLower = new double [ncols]; CoinMemcpyN(upper, ncols, saveUpper); CoinMemcpyN(lower, ncols, saveLower); if (allowInfeasible) { saveRowUpper = new double [nrows]; saveRowLower = new double [nrows]; CoinMemcpyN(rowupper, nrows, saveRowUpper); CoinMemcpyN(rowlower, nrows, saveRowLower); double averageInfeas = model_->sumPrimalInfeasibilities() / static_cast (model_->numberRows()); fixTolerance = CoinMax(fixTolerance, 1.0e-5 * averageInfeas); } } if (slackStart >= 0) { slackEnd = slackStart + nrows; if (slackStart) { ordStart = 0; ordEnd = slackStart; } else { ordStart = nrows; ordEnd = ncols; } } else { slackEnd = slackStart; ordStart = 0; ordEnd = ncols; } /* get correct rowsol (without known slacks) */ memset(rowsol, 0, nrows * sizeof(double)); for (i = ordStart; i < ordEnd; i++) { CoinBigIndex j; double value = colsol[i]; if (value < lower[i] + fixTolerance) { value = lower[i]; colsol[i] = value; } for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int irow = row[j]; rowsol[irow] += value * element[j]; } } if (slackStart >= 0) { for (i = 0; i < nrows; i++) { if (ratio * rowsol[i] > rowlower[i] && rowsol[i] > 1.0e-8) { ratio = rowlower[i] / rowsol[i]; } } for (i = 0; i < nrows; i++) { rowsol[i] *= ratio; } for (i = ordStart; i < ordEnd; i++) { double value = colsol[i] * ratio; colsol[i] = value; objValue += value * cost[i]; } for (i = 0; i < nrows; i++) { double value = rowlower[i] - rowsol[i]; colsol[i+slackStart] = value; objValue += value * cost[i+slackStart]; } COIN_DETAIL_PRINT(printf("New objective after scaling %g\n", objValue)); } #if 0 maybe put back - but just get feasible ? // If not many fixed then just exit int numberFixed = 0; for (i = ordStart; i < ordEnd; i++) { if (colsol[i] < lower[i] + fixTolerance) numberFixed++; else if (colsol[i] > upper[i] - fixTolerance) numberFixed++; } if (numberFixed < ncols / 2) { addAll = 3; presolve = 0; } #endif #ifdef FEB_TRY int savePerturbation = model_->perturbation(); int saveOptions = model_->specialOptions(); model_->setSpecialOptions(saveOptions | 8192); if (savePerturbation_ == 50) model_->setPerturbation(56); #endif model_->createStatus(); /* addAll 0 - chosen,all used, all 1 - chosen, all 2 - all 3 - do not do anything - maybe basis */ for (i = ordStart; i < ordEnd; i++) { if (addAll < 2) { if (colsol[i] < lower[i] + fixTolerance) { upper[i] = lower[i]; colsol[i] = lower[i]; } else if (colsol[i] > upper[i] - fixTolerance) { lower[i] = upper[i]; colsol[i] = upper[i]; } } model_->setColumnStatus(i, ClpSimplex::superBasic); } if ((strategy_ & 16384) != 0) { // put in basis int * posSlack = whenUsed_ + ncols; int * negSlack = posSlack + nrows; int * nextSlack = negSlack + nrows; /* Laci - try both ways - to see what works - you can change second part as much as you want */ #ifndef LACI_TRY // was #if 1 // Array for sorting out slack values double * ratio = new double [ncols]; int * which = new int [ncols]; for (i = 0; i < nrows; i++) { if (posSlack[i] >= 0 || negSlack[i] >= 0) { int iCol; int nPlus = 0; int nMinus = 0; bool possible = true; // Get sum double sum = 0.0; iCol = posSlack[i]; while (iCol >= 0) { double value = element[columnStart[iCol]]; sum += value * colsol[iCol]; if (lower[iCol]) { possible = false; break; } else { nPlus++; } iCol = nextSlack[iCol]; } iCol = negSlack[i]; while (iCol >= 0) { double value = -element[columnStart[iCol]]; sum -= value * colsol[iCol]; if (lower[iCol]) { possible = false; break; } else { nMinus++; } iCol = nextSlack[iCol]; } //printf("%d plus, %d minus",nPlus,nMinus); //printf("\n"); if ((rowsol[i] - rowlower[i] < 1.0e-7 || rowupper[i] - rowsol[i] < 1.0e-7) && nPlus + nMinus < 2) possible = false; if (possible) { // Amount contributed by other varaibles sum = rowsol[i] - sum; double lo = rowlower[i]; if (lo > -1.0e20) lo -= sum; double up = rowupper[i]; if (up < 1.0e20) up -= sum; //printf("row bounds %g %g\n",lo,up); if (0) { double sum = 0.0; double x = 0.0; for (int k = 0; k < ncols; k++) { CoinBigIndex j; double value = colsol[k]; x += value * cost[k]; for (j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int irow = row[j]; if (irow == i) sum += element[j] * value; } } printf("Before sum %g <= %g <= %g cost %.18g\n", rowlower[i], sum, rowupper[i], x); } // set all to zero iCol = posSlack[i]; while (iCol >= 0) { colsol[iCol] = 0.0; iCol = nextSlack[iCol]; } iCol = negSlack[i]; while (iCol >= 0) { colsol[iCol] = 0.0; iCol = nextSlack[iCol]; } { int iCol; iCol = posSlack[i]; while (iCol >= 0) { //printf("col %d el %g sol %g bounds %g %g cost %g\n", // iCol,element[columnStart[iCol]], // colsol[iCol],lower[iCol],upper[iCol],cost[iCol]); iCol = nextSlack[iCol]; } iCol = negSlack[i]; while (iCol >= 0) { //printf("col %d el %g sol %g bounds %g %g cost %g\n", // iCol,element[columnStart[iCol]], // colsol[iCol],lower[iCol],upper[iCol],cost[iCol]); iCol = nextSlack[iCol]; } } //printf("now what?\n"); int n = 0; bool basic = false; if (lo > 0.0) { // Add in positive iCol = posSlack[i]; while (iCol >= 0) { double value = element[columnStart[iCol]]; ratio[n] = cost[iCol] / value; which[n++] = iCol; iCol = nextSlack[iCol]; } CoinSort_2(ratio, ratio + n, which); for (int i = 0; i < n; i++) { iCol = which[i]; double value = element[columnStart[iCol]]; if (lo >= upper[iCol]*value) { value *= upper[iCol]; sum += value; lo -= value; colsol[iCol] = upper[iCol]; } else { value = lo / value; sum += lo; lo = 0.0; colsol[iCol] = value; model_->setColumnStatus(iCol, ClpSimplex::basic); basic = true; } if (lo < 1.0e-7) break; } } else if (up < 0.0) { // Use lo so coding is more similar lo = -up; // Add in negative iCol = negSlack[i]; while (iCol >= 0) { double value = -element[columnStart[iCol]]; ratio[n] = cost[iCol] / value; which[n++] = iCol; iCol = nextSlack[iCol]; } CoinSort_2(ratio, ratio + n, which); for (int i = 0; i < n; i++) { iCol = which[i]; double value = -element[columnStart[iCol]]; if (lo >= upper[iCol]*value) { value *= upper[iCol]; sum += value; lo -= value; colsol[iCol] = upper[iCol]; } else { value = lo / value; sum += lo; lo = 0.0; colsol[iCol] = value; model_->setColumnStatus(iCol, ClpSimplex::basic); basic = true; } if (lo < 1.0e-7) break; } } if (0) { double sum2 = 0.0; double x = 0.0; for (int k = 0; k < ncols; k++) { CoinBigIndex j; double value = colsol[k]; x += value * cost[k]; for (j = columnStart[k]; j < columnStart[k] + columnLength[k]; j++) { int irow = row[j]; if (irow == i) sum2 += element[j] * value; } } printf("after sum %g <= %g <= %g cost %.18g (sum = %g)\n", rowlower[i], sum2, rowupper[i], x, sum); } rowsol[i] = sum; if (basic) { if (fabs(rowsol[i] - rowlower[i]) < fabs(rowsol[i] - rowupper[i])) model_->setRowStatus(i, ClpSimplex::atLowerBound); else model_->setRowStatus(i, ClpSimplex::atUpperBound); } } else { int n = 0; int iCol; iCol = posSlack[i]; while (iCol >= 0) { if (colsol[iCol] > lower[iCol] + 1.0e-8 && colsol[iCol] < upper[iCol] - 1.0e-8) { model_->setColumnStatus(iCol, ClpSimplex::basic); n++; } iCol = nextSlack[iCol]; } iCol = negSlack[i]; while (iCol >= 0) { if (colsol[iCol] > lower[iCol] + 1.0e-8 && colsol[iCol] < upper[iCol] - 1.0e-8) { model_->setColumnStatus(iCol, ClpSimplex::basic); n++; } iCol = nextSlack[iCol]; } if (n) { if (fabs(rowsol[i] - rowlower[i]) < fabs(rowsol[i] - rowupper[i])) model_->setRowStatus(i, ClpSimplex::atLowerBound); else model_->setRowStatus(i, ClpSimplex::atUpperBound); #ifdef CLP_INVESTIGATE if (n > 1) printf("%d basic on row %d!\n", n, i); #endif } } } } delete [] ratio; delete [] which; #else for (i = 0; i < nrows; i++) { int n = 0; int iCol; iCol = posSlack[i]; while (iCol >= 0) { if (colsol[iCol] > lower[iCol] + 1.0e-8 && colsol[iCol] < upper[iCol] - 1.0e-8) { model_->setColumnStatus(iCol, ClpSimplex::basic); n++; } iCol = nextSlack[iCol]; } iCol = negSlack[i]; while (iCol >= 0) { if (colsol[iCol] > lower[iCol] + 1.0e-8 && colsol[iCol] < upper[iCol] - 1.0e-8) { model_->setColumnStatus(iCol, ClpSimplex::basic); n++; } iCol = nextSlack[iCol]; } if (n) { if (fabs(rowsol[i] - rowlower[i]) < fabs(rowsol[i] - rowupper[i])) model_->setRowStatus(i, ClpSimplex::atLowerBound); else model_->setRowStatus(i, ClpSimplex::atUpperBound); #ifdef CLP_INVESTIGATE if (n > 1) printf("%d basic on row %d!\n", n, i); #endif } } #endif } double maxmin; if (model_->getObjSense() == -1.0) { maxmin = -1.0; } else { maxmin = 1.0; } bool justValuesPass = majorIterations_ > 1000000; if (slackStart >= 0) { for (i = 0; i < nrows; i++) { model_->setRowStatus(i, ClpSimplex::superBasic); } for (i = slackStart; i < slackEnd; i++) { model_->setColumnStatus(i, ClpSimplex::basic); } } else { /* still try and put singletons rather than artificials in basis */ int ninbas = 0; for (i = 0; i < nrows; i++) { model_->setRowStatus(i, ClpSimplex::basic); } for (i = 0; i < ncols; i++) { if (columnLength[i] == 1 && upper[i] > lower[i] + 1.0e-5) { CoinBigIndex j = columnStart[i]; double value = element[j]; int irow = row[j]; double rlo = rowlower[irow]; double rup = rowupper[irow]; double clo = lower[i]; double cup = upper[i]; double csol = colsol[i]; /* adjust towards feasibility */ double move = 0.0; if (rowsol[irow] > rup) { move = (rup - rowsol[irow]) / value; if (value > 0.0) { /* reduce */ if (csol + move < clo) move = CoinMin(0.0, clo - csol); } else { /* increase */ if (csol + move > cup) move = CoinMax(0.0, cup - csol); } } else if (rowsol[irow] < rlo) { move = (rlo - rowsol[irow]) / value; if (value > 0.0) { /* increase */ if (csol + move > cup) move = CoinMax(0.0, cup - csol); } else { /* reduce */ if (csol + move < clo) move = CoinMin(0.0, clo - csol); } } else { /* move to improve objective */ if (cost[i]*maxmin > 0.0) { if (value > 0.0) { move = (rlo - rowsol[irow]) / value; /* reduce */ if (csol + move < clo) move = CoinMin(0.0, clo - csol); } else { move = (rup - rowsol[irow]) / value; /* increase */ if (csol + move > cup) move = CoinMax(0.0, cup - csol); } } else if (cost[i]*maxmin < 0.0) { if (value > 0.0) { move = (rup - rowsol[irow]) / value; /* increase */ if (csol + move > cup) move = CoinMax(0.0, cup - csol); } else { move = (rlo - rowsol[irow]) / value; /* reduce */ if (csol + move < clo) move = CoinMin(0.0, clo - csol); } } } rowsol[irow] += move * value; colsol[i] += move; /* put in basis if row was artificial */ if (rup - rlo < 1.0e-7 && model_->getRowStatus(irow) == ClpSimplex::basic) { model_->setRowStatus(irow, ClpSimplex::superBasic); model_->setColumnStatus(i, ClpSimplex::basic); ninbas++; } } } /*printf("%d in basis\n",ninbas);*/ } bool wantVector = false; if (dynamic_cast< ClpPackedMatrix*>(model_->clpMatrix())) { // See if original wanted vector ClpPackedMatrix * clpMatrixO = dynamic_cast< ClpPackedMatrix*>(model_->clpMatrix()); wantVector = clpMatrixO->wantsSpecialColumnCopy(); } if (addAll < 3) { ClpPresolve pinfo; if (presolve) { if (allowInfeasible) { // fix up so will be feasible double * rhs = new double[nrows]; memset(rhs, 0, nrows * sizeof(double)); model_->clpMatrix()->times(1.0, colsol, rhs); double * rowupper = model_->rowUpper(); double * rowlower = model_->rowLower(); saveRowUpper = CoinCopyOfArray(rowupper, nrows); saveRowLower = CoinCopyOfArray(rowlower, nrows); double sum = 0.0; for (i = 0; i < nrows; i++) { if (rhs[i] > rowupper[i]) { sum += rhs[i] - rowupper[i]; rowupper[i] = rhs[i]; } if (rhs[i] < rowlower[i]) { sum += rowlower[i] - rhs[i]; rowlower[i] = rhs[i]; } } COIN_DETAIL_PRINT(printf("sum of infeasibilities %g\n", sum)); delete [] rhs; } saveModel = model_; pinfo.setPresolveActions(pinfo.presolveActions() | 16384); model_ = pinfo.presolvedModel(*model_, 1.0e-8, false, 5); } if (model_) { if (!wantVector) { //#define TWO_GOES #ifdef ABC_INHERIT #ifndef TWO_GOES model_->dealWithAbc(1,justValuesPass ? 2 : 1); #else model_->dealWithAbc(1,1 + 11); #endif #else #ifndef TWO_GOES model_->primal(justValuesPass ? 2 : 1); #else model_->primal(1 + 11); #endif #endif } else { ClpMatrixBase * matrix = model_->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); assert (clpMatrix); clpMatrix->makeSpecialColumnCopy(); #ifdef ABC_INHERIT model_->dealWithAbc(1,1); #else model_->primal(1); #endif clpMatrix->releaseSpecialColumnCopy(); } if (presolve) { model_->primal(); pinfo.postsolve(true); delete model_; model_ = saveModel; saveModel = NULL; } } else { // not feasible addAll = 1; presolve = 0; model_ = saveModel; saveModel = NULL; if (justValuesPass) #ifdef ABC_INHERIT model_->dealWithAbc(1,2); #else model_->primal(2); #endif } if (allowInfeasible) { CoinMemcpyN(saveRowUpper, nrows, model_->rowUpper()); CoinMemcpyN(saveRowLower, nrows, model_->rowLower()); delete [] saveRowUpper; delete [] saveRowLower; saveRowUpper = NULL; saveRowLower = NULL; } if (addAll < 2) { n = 0; if (!addAll ) { /* could do scans to get a good number */ iteration = 1; for (i = ordStart; i < ordEnd; i++) { if (whenUsed[i] >= iteration) { if (upper[i] - lower[i] < 1.0e-5 && saveUpper[i] - saveLower[i] > 1.0e-5) { n++; upper[i] = saveUpper[i]; lower[i] = saveLower[i]; } } } } else { for (i = ordStart; i < ordEnd; i++) { if (upper[i] - lower[i] < 1.0e-5 && saveUpper[i] - saveLower[i] > 1.0e-5) { n++; upper[i] = saveUpper[i]; lower[i] = saveLower[i]; } } delete [] saveUpper; delete [] saveLower; saveUpper = NULL; saveLower = NULL; } #ifdef COIN_DEVELOP printf("Time so far %g, %d now added from previous iterations\n", CoinCpuTime() - startTime, n); #endif if (justValuesPass) return; if (addAll) presolve = 0; if (presolve) { saveModel = model_; model_ = pinfo.presolvedModel(*model_, 1.0e-8, false, 5); } else { presolve = 0; } if (!wantVector) { #ifdef ABC_INHERIT model_->dealWithAbc(1,1); #else model_->primal(1); #endif } else { ClpMatrixBase * matrix = model_->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); assert (clpMatrix); clpMatrix->makeSpecialColumnCopy(); #ifdef ABC_INHERIT model_->dealWithAbc(1,1); #else model_->primal(1); #endif clpMatrix->releaseSpecialColumnCopy(); } if (presolve) { pinfo.postsolve(true); delete model_; model_ = saveModel; saveModel = NULL; } if (!addAll) { n = 0; for (i = ordStart; i < ordEnd; i++) { if (upper[i] - lower[i] < 1.0e-5 && saveUpper[i] - saveLower[i] > 1.0e-5) { n++; upper[i] = saveUpper[i]; lower[i] = saveLower[i]; } } delete [] saveUpper; delete [] saveLower; saveUpper = NULL; saveLower = NULL; #ifdef COIN_DEVELOP printf("Time so far %g, %d now added from previous iterations\n", CoinCpuTime() - startTime, n); #endif } if (presolve) { saveModel = model_; model_ = pinfo.presolvedModel(*model_, 1.0e-8, false, 5); } else { presolve = 0; } if (!wantVector) { #ifdef ABC_INHERIT model_->dealWithAbc(1,1); #else model_->primal(1); #endif } else { ClpMatrixBase * matrix = model_->clpMatrix(); ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); assert (clpMatrix); clpMatrix->makeSpecialColumnCopy(); #ifdef ABC_INHERIT model_->dealWithAbc(1,1); #else model_->primal(1); #endif clpMatrix->releaseSpecialColumnCopy(); } if (presolve) { pinfo.postsolve(true); delete model_; model_ = saveModel; saveModel = NULL; } } #ifdef COIN_DEVELOP printf("Total time in crossover %g\n", CoinCpuTime() - startTime); #endif delete [] saveUpper; delete [] saveLower; } #ifdef FEB_TRY model_->setSpecialOptions(saveOptions); model_->setPerturbation(savePerturbation); #endif return ; } #endif /*****************************************************************************/ // Default contructor Idiot::Idiot() { model_ = NULL; maxBigIts_ = 3; maxIts_ = 5; logLevel_ = 1; logFreq_ = 100; maxIts2_ = 100; djTolerance_ = 1e-1; mu_ = 1e-4; drop_ = 5.0; exitDrop_ = -1.0e20; muFactor_ = 0.3333; stopMu_ = 1e-12; smallInfeas_ = 1e-1; reasonableInfeas_ = 1e2; muAtExit_ = 1.0e31; strategy_ = 8; lambdaIterations_ = 0; checkFrequency_ = 100; whenUsed_ = NULL; majorIterations_ = 30; exitFeasibility_ = -1.0; dropEnoughFeasibility_ = 0.02; dropEnoughWeighted_ = 0.01; // adjust double nrows = 10000.0; int baseIts = static_cast (sqrt(static_cast(nrows))); baseIts = baseIts / 10; baseIts *= 10; maxIts2_ = 200 + baseIts + 5; maxIts2_ = 100; reasonableInfeas_ = static_cast (nrows) * 0.05; lightWeight_ = 0; } // Constructor from model Idiot::Idiot(OsiSolverInterface &model) { model_ = & model; maxBigIts_ = 3; maxIts_ = 5; logLevel_ = 1; logFreq_ = 100; maxIts2_ = 100; djTolerance_ = 1e-1; mu_ = 1e-4; drop_ = 5.0; exitDrop_ = -1.0e20; muFactor_ = 0.3333; stopMu_ = 1e-12; smallInfeas_ = 1e-1; reasonableInfeas_ = 1e2; muAtExit_ = 1.0e31; strategy_ = 8; lambdaIterations_ = 0; checkFrequency_ = 100; whenUsed_ = NULL; majorIterations_ = 30; exitFeasibility_ = -1.0; dropEnoughFeasibility_ = 0.02; dropEnoughWeighted_ = 0.01; // adjust double nrows; if (model_) nrows = model_->getNumRows(); else nrows = 10000.0; int baseIts = static_cast (sqrt(static_cast(nrows))); baseIts = baseIts / 10; baseIts *= 10; maxIts2_ = 200 + baseIts + 5; maxIts2_ = 100; reasonableInfeas_ = static_cast (nrows) * 0.05; lightWeight_ = 0; } // Copy constructor. Idiot::Idiot(const Idiot &rhs) { model_ = rhs.model_; if (model_ && rhs.whenUsed_) { int numberColumns = model_->getNumCols(); whenUsed_ = new int [numberColumns]; CoinMemcpyN(rhs.whenUsed_, numberColumns, whenUsed_); } else { whenUsed_ = NULL; } djTolerance_ = rhs.djTolerance_; mu_ = rhs.mu_; drop_ = rhs.drop_; muFactor_ = rhs.muFactor_; stopMu_ = rhs.stopMu_; smallInfeas_ = rhs.smallInfeas_; reasonableInfeas_ = rhs.reasonableInfeas_; exitDrop_ = rhs.exitDrop_; muAtExit_ = rhs.muAtExit_; exitFeasibility_ = rhs.exitFeasibility_; dropEnoughFeasibility_ = rhs.dropEnoughFeasibility_; dropEnoughWeighted_ = rhs.dropEnoughWeighted_; maxBigIts_ = rhs.maxBigIts_; maxIts_ = rhs.maxIts_; majorIterations_ = rhs.majorIterations_; logLevel_ = rhs.logLevel_; logFreq_ = rhs.logFreq_; checkFrequency_ = rhs.checkFrequency_; lambdaIterations_ = rhs.lambdaIterations_; maxIts2_ = rhs.maxIts2_; strategy_ = rhs.strategy_; lightWeight_ = rhs.lightWeight_; } // Assignment operator. This copies the data Idiot & Idiot::operator=(const Idiot & rhs) { if (this != &rhs) { delete [] whenUsed_; model_ = rhs.model_; if (model_ && rhs.whenUsed_) { int numberColumns = model_->getNumCols(); whenUsed_ = new int [numberColumns]; CoinMemcpyN(rhs.whenUsed_, numberColumns, whenUsed_); } else { whenUsed_ = NULL; } djTolerance_ = rhs.djTolerance_; mu_ = rhs.mu_; drop_ = rhs.drop_; muFactor_ = rhs.muFactor_; stopMu_ = rhs.stopMu_; smallInfeas_ = rhs.smallInfeas_; reasonableInfeas_ = rhs.reasonableInfeas_; exitDrop_ = rhs.exitDrop_; muAtExit_ = rhs.muAtExit_; exitFeasibility_ = rhs.exitFeasibility_; dropEnoughFeasibility_ = rhs.dropEnoughFeasibility_; dropEnoughWeighted_ = rhs.dropEnoughWeighted_; maxBigIts_ = rhs.maxBigIts_; maxIts_ = rhs.maxIts_; majorIterations_ = rhs.majorIterations_; logLevel_ = rhs.logLevel_; logFreq_ = rhs.logFreq_; checkFrequency_ = rhs.checkFrequency_; lambdaIterations_ = rhs.lambdaIterations_; maxIts2_ = rhs.maxIts2_; strategy_ = rhs.strategy_; lightWeight_ = rhs.lightWeight_; } return *this; } Idiot::~Idiot() { delete [] whenUsed_; } Clp-1.15.10/src/CoinAbcBaseFactorization.hpp0000644000076600007660000012156212101105055017176 0ustar coincoin/* $Id: CoinAbcBaseFactorization.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ /** This deals with Factorization and Updates I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex may be redefined to get 64 bits. */ #include "AbcCommon.hpp" #include "CoinAbcHelperFunctions.hpp" #if ABC_PARALLEL #define FACTOR_CPU 4 #else #define FACTOR_CPU 1 #endif #define LARGE_SET COIN_INT_MAX-10 #define LARGE_UNSET (LARGE_SET+1) class CoinAbcTypeFactorization : public CoinAbcAnyFactorization { friend void CoinAbcFactorizationUnitTest( const std::string & mpsDir ); public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor CoinAbcTypeFactorization ( ); /// Copy constructor CoinAbcTypeFactorization ( const CoinAbcTypeFactorization &other); /// Copy constructor CoinAbcTypeFactorization ( const CoinFactorization &other); /// Destructor virtual ~CoinAbcTypeFactorization ( ); /// Clone virtual CoinAbcAnyFactorization * clone() const ; /// Delete all stuff (leaves as after CoinAbcFactorization()) void almostDestructor(); /// Debug show object (shows one representation) void show_self ( ) const; /// Debug - sort so can compare void sort ( ) const; /// = copy CoinAbcTypeFactorization & operator = ( const CoinAbcTypeFactorization & other ); //@} /**@name Do factorization */ //@{ /// Condition number - product of pivots after factorization CoinSimplexDouble conditionNumber() const; //@} /**@name general stuff such as permutation or status */ //@{ /// Returns address of permute region inline CoinSimplexInt *permute ( ) const { return NULL; //permute_.array(); } /// Returns array to put basis indices in virtual inline CoinSimplexInt * indices() const { return indexRowU_.array();} /// Returns address of pivotColumn region (also used for permuting) virtual inline CoinSimplexInt *pivotColumn ( ) const { return pivotColumn_.array(); } /// Returns address of pivot region virtual inline CoinFactorizationDouble *pivotRegion ( ) const { return pivotRegionAddress_; } #if ABC_SMALL<2 /// Start of each row in L inline CoinBigIndex * startRowL() const { return startRowL_.array();} #endif /// Start of each column in L inline CoinBigIndex * startColumnL() const { return startColumnL_.array();} #if ABC_SMALL<2 /// Index of column in row for L inline CoinSimplexInt * indexColumnL() const { return indexColumnL_.array();} #endif /// Row indices of L inline CoinSimplexInt * indexRowL() const { return indexRowL_.array();} #if ABC_SMALL<2 /// Elements in L (row copy) inline CoinFactorizationDouble * elementByRowL() const { return elementByRowL_.array();} #endif /** Forward and backward linked lists (numberRows_+2) **/ inline CoinSimplexInt * pivotLinkedBackwards() const { return firstCount_.array()+numberRows_+1;} inline CoinSimplexInt * pivotLinkedForwards() const { return firstCount_.array()+2*numberRows_+3;} inline CoinSimplexInt * pivotLOrder() const { return firstCount_.array();} #if ABC_SMALL<0 #define ABC_USE_FUNCTION_POINTERS 0 #define SMALL_PERMUTE #endif #ifdef ABC_USE_FUNCTION_POINTERS typedef void (*scatterUpdate) (int,CoinFactorizationDouble,const CoinFactorizationDouble *, CoinFactorizationDouble *); #if ABC_USE_FUNCTION_POINTERS typedef struct { scatterUpdate functionPointer; CoinBigIndex offset; int number; } scatterStruct; #else typedef struct { CoinBigIndex offset; int number; } scatterStruct; #endif /// Array of function pointers PLUS for U Column inline scatterStruct * scatterUColumn() const { return scatterPointersUColumnAddress_;} #endif /// For equal counts in factorization /** First Row/Column with count of k, can tell which by offset - Rows then Columns actually comes before nextCount*/ inline CoinSimplexInt * firstCount() const { return firstCount_.array();} /// Next Row/Column with count inline CoinSimplexInt * nextCount() const { return firstCount_.array()+numberRows_+2;} /// Previous Row/Column with count inline CoinSimplexInt * lastCount() const { return firstCount_.array()+3*numberRows_+2;} /// Number of Rows after iterating inline CoinSimplexInt numberRowsExtra ( ) const { return numberRowsExtra_; } /// Number in L inline CoinBigIndex numberL() const { return numberL_;} /// Base of L inline CoinBigIndex baseL() const { return baseL_;} /// Maximum of Rows after iterating inline CoinSimplexInt maximumRowsExtra ( ) const { return maximumRowsExtra_; } /// Total number of elements in factorization virtual inline CoinBigIndex numberElements ( ) const { return totalElements_; } /// Length of FT vector inline CoinSimplexInt numberForrestTomlin ( ) const { return numberInColumn_.array()[numberRowsExtra_]; } /// Returns areaFactor but adjusted for dense CoinSimplexDouble adjustedAreaFactor() const; /// Level of detail of messages inline CoinSimplexInt messageLevel ( ) const { return messageLevel_ ; } void messageLevel ( CoinSimplexInt value ); /// Set maximum pivots virtual void maximumPivots ( CoinSimplexInt value ); #if ABC_SMALL<4 /// Gets dense threshold inline CoinSimplexInt denseThreshold() const { return denseThreshold_;} /// Sets dense threshold inline void setDenseThreshold(CoinSimplexInt value) { denseThreshold_ = value;} #endif /// Returns maximum absolute value in factorization CoinSimplexDouble maximumCoefficient() const; #if 0 /// true if Forrest Tomlin update, false if PFI inline bool forrestTomlin() const { return doForrestTomlin_;} inline void setForrestTomlin(bool value) { doForrestTomlin_=value;} #endif /// True if FT update and space inline bool spaceForForrestTomlin() const { CoinBigIndex start = lastEntryByColumnU_; CoinBigIndex space = lengthAreaU_ - ( start + numberRowsExtra_ ); return (space>=0); //&&doForrestTomlin_; } //@} /**@name some simple stuff */ //@{ /// Returns number in U area inline CoinBigIndex numberElementsU ( ) const { return lengthU_; } /// Setss number in U area inline void setNumberElementsU(CoinBigIndex value) { lengthU_ = value; } /// Returns length of U area inline CoinBigIndex lengthAreaU ( ) const { return lengthAreaU_; } /// Returns number in L area inline CoinBigIndex numberElementsL ( ) const { return lengthL_; } /// Returns length of L area inline CoinBigIndex lengthAreaL ( ) const { return lengthAreaL_; } /// Returns number in R area inline CoinBigIndex numberElementsR ( ) const { return lengthR_; } /// Number of compressions done inline CoinBigIndex numberCompressions() const { return numberCompressions_;} /// Returns pivot row //virtual CoinSimplexInt * pivotRow() const; /// Returns work area //virtual CoinFactorizationDouble * workArea() const; /// Returns CoinSimplexInt work area //virtual CoinSimplexInt * intWorkArea() const; /// Returns array to put basis starts in virtual inline CoinBigIndex * starts() const { return startColumnU_.array();} /// Number of entries in each row virtual inline CoinSimplexInt * numberInRow() const { return numberInRow_.array();} /// Number of entries in each column virtual inline CoinSimplexInt * numberInColumn() const { return numberInColumn_.array();} /// Returns array to put basis elements in virtual inline CoinFactorizationDouble * elements() const { return elementU_.array();} /// Start of columns for R inline CoinBigIndex * startColumnR() const {return reinterpret_cast(firstCount_.array()+3*numberRows_+4);} /// Elements of U inline CoinFactorizationDouble * elementU() const { return elementU_.array();} /// Row indices of U inline CoinSimplexInt * indexRowU() const { return indexRowU_.array();} /// Start of each column in U inline CoinBigIndex * startColumnU() const { return startColumnU_.array();} #if COIN_BIG_DOUBLE==1 /// To a work array and associate vector void toLongArray(CoinIndexedVector * vector,int which) const; /// From a work array and dis-associate vector void fromLongArray(CoinIndexedVector * vector) const; /// From a work array and dis-associate vector void fromLongArray(int which) const; /// Returns long double * associated with vector long double * denseVector(CoinIndexedVector * vector) const; /// Returns long double * associated with vector long double * denseVector(CoinIndexedVector & vector) const; /// Returns long double * associated with vector const long double * denseVector(const CoinIndexedVector * vector) const; /// Returns long double * associated with vector const long double * denseVector(const CoinIndexedVector & vector) const; /// Scans region to find nonzeros void scan(CoinIndexedVector * vector) const; /// Clear all hidden arrays void clearHiddenArrays(); #else /// Returns double * associated with vector inline double * denseVector(CoinIndexedVector * vector) const {return vector->denseVector();} inline double * denseVector(CoinIndexedVector & vector) const {return vector.denseVector();} /// Returns double * associated with vector inline const double * denseVector(const CoinIndexedVector * vector) const {return vector->denseVector();} inline const double * denseVector(const CoinIndexedVector & vector) const {return vector.denseVector();} /// To a work array and associate vector inline void toLongArray(CoinIndexedVector * vector,int which) const {} /// From a work array and dis-associate vector inline void fromLongArray(CoinIndexedVector * vector) const {} /// From a work array and dis-associate vector inline void fromLongArray(int which) const {} /// Scans region to find nonzeros inline void scan(CoinIndexedVector * vector) const {vector->scan(0,numberRows_,zeroTolerance_);} #endif #ifdef ABC_ORDERED_FACTORIZATION /// Permute in for Ftran void permuteInForFtran(CoinIndexedVector & regionSparse,bool full=false) const ; /// Permute in for Btran and multiply by pivot Region void permuteInForBtranAndMultiply(CoinIndexedVector & regionSparse, bool full=false) const ; /// Permute out for Btran void permuteOutForBtran(CoinIndexedVector & regionSparse) const ; #endif /** Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ //inline CoinSimplexInt persistenceFlag() const //{ return persistenceFlag_;} //@} /**@name rank one updates which do exist */ //@{ #if 0 /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots Fills in region for use later partial update already in U */ virtual int checkReplace ( const AbcSimplex * model, CoinIndexedVector * regionSparse, int pivotRow, CoinSimplexDouble & pivotCheck, double acceptablePivot = 1.0e-8); /** Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If skipBtranU is false will do btran part partial update already in U */ virtual CoinSimplexInt replaceColumn ( CoinIndexedVector * regionSparse, CoinSimplexInt pivotRow, CoinSimplexDouble pivotCheck , bool skipBtranU=false, CoinSimplexDouble acceptablePivot=1.0e-8); #endif /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update already in U */ virtual #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * regionSparse, int pivotRow); /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update in vector */ virtual #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * regionSparse, CoinIndexedVector * partialUpdate, int pivotRow); #ifdef MOVE_REPLACE_PART1A /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update already in U */ virtual void checkReplacePart1a ( CoinIndexedVector * regionSparse, int pivotRow); virtual #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1b ( CoinIndexedVector * regionSparse, int pivotRow); #endif /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ virtual int checkReplacePart2 ( int pivotRow, CoinSimplexDouble btranAlpha, double ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha, double acceptablePivot = 1.0e-8); /** Replaces one Column to basis, partial update already in U */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ); /** Replaces one Column to basis, partial update in vector */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, CoinIndexedVector * partialUpdate, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ); #ifdef EARLY_FACTORIZE /// 0 success, -1 can't +1 accuracy problems virtual int replaceColumns ( const AbcSimplex * model, CoinIndexedVector & stuff, int firstPivot,int lastPivot,bool cleanUp); #endif /// Update partial Ftran by R update void updatePartialUpdate(CoinIndexedVector & partialUpdate); /// Returns true if wants tableauColumn in replaceColumn inline virtual bool wantsTableauColumn() const {return false;} /** Combines BtranU and store which elements are to be deleted returns number to be deleted */ int replaceColumnU ( CoinIndexedVector * regionSparse, CoinBigIndex * deletedPosition, CoinSimplexInt * deletedColumns, CoinSimplexInt pivotRow); //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ /// Later take out return codes (apart from +- 1 on FT) //@{ /** Updates one column (FTRAN) from regionSparse2 Tries to do FT update number returned is negative if no room regionSparse starts as zero and is zero at end. Note - if regionSparse2 packed on input - will be packed on output */ virtual CoinSimplexInt updateColumnFT ( CoinIndexedVector & regionSparse); virtual int updateColumnFTPart1 ( CoinIndexedVector & regionSparse) ; virtual void updateColumnFTPart2 ( CoinIndexedVector & regionSparse) ; /** Updates one column (FTRAN) Tries to do FT update puts partial update in vector */ virtual void updateColumnFT ( CoinIndexedVector & regionSparseFT, CoinIndexedVector & partialUpdate, int which); /** This version has same effect as above with FTUpdate==false so number returned is always >=0 */ virtual CoinSimplexInt updateColumn ( CoinIndexedVector & regionSparse) const; /** Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ virtual CoinSimplexInt updateTwoColumnsFT ( CoinIndexedVector & regionFT, CoinIndexedVector & regionOther); /** Updates one column (BTRAN) from regionSparse2 regionSparse starts as zero and is zero at end Note - if regionSparse2 packed on input - will be packed on output */ virtual CoinSimplexInt updateColumnTranspose ( CoinIndexedVector & regionSparse) const; /** Updates one full column (FTRAN) */ virtual void updateFullColumn ( CoinIndexedVector & regionSparse) const; /** Updates one full column (BTRAN) */ virtual void updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const; /** Updates one column for dual steepest edge weights (FTRAN) */ virtual void updateWeights ( CoinIndexedVector & regionSparse) const; /** Updates one column (FTRAN) */ virtual void updateColumnCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; /** Updates one column (BTRAN) */ virtual void updateColumnTransposeCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; void unpack ( CoinIndexedVector * regionFrom, CoinIndexedVector * regionTo) const; void pack ( CoinIndexedVector * regionFrom, CoinIndexedVector * regionTo) const; /** makes a row copy of L for speed and to allow very sparse problems */ inline void goSparse() {} void goSparse2(); #ifndef NDEBUG virtual void checkMarkArrays() const; #endif #if ABC_SMALL<2 /** get sparse threshold */ inline CoinSimplexInt sparseThreshold ( ) const { return sparseThreshold_;} #endif /** set sparse threshold */ void sparseThreshold ( CoinSimplexInt value ); //@} /// *** Below this user may not want to know about /**@name various uses of factorization (return code number elements) which user may not want to know about (left over from my LP code) */ //@{ /// Get rid of all memory inline void clearArrays() { gutsOfDestructor();} //@} /**@name used by ClpFactorization */ /// See if worth going sparse void checkSparse(); /// The real work of constructors etc 0 just scalars, 1 bit normal void gutsOfDestructor(CoinSimplexInt type=1); /// 1 bit - tolerances etc, 2 more, 4 dummy arrays void gutsOfInitialize(CoinSimplexInt type); void gutsOfCopy(const CoinAbcTypeFactorization &other); /// Reset all sparsity etc statistics void resetStatistics(); void printRegion(const CoinIndexedVector & vector, const char * where) const; //@} /**@name used by factorization */ /// Gets space for a factorization, called by constructors virtual void getAreas ( CoinSimplexInt numberRows, CoinSimplexInt numberColumns, CoinBigIndex maximumL, CoinBigIndex maximumU ); /// PreProcesses column ordered copy of basis virtual void preProcess ( ); void preProcess (CoinSimplexInt ); /// Return largest element double preProcess3 ( ); void preProcess4 ( ); /// Does most of factorization virtual CoinSimplexInt factor (AbcSimplex * model); #ifdef EARLY_FACTORIZE /// Returns -2 if can't, -1 if singular, -99 memory, 0 OK virtual int factorize (AbcSimplex * model, CoinIndexedVector & stuff); #endif /// Does post processing on valid factorization - putting variables on correct rows virtual void postProcess(const CoinSimplexInt * sequence, CoinSimplexInt * pivotVariable); /// Makes a non-singular basis by replacing variables virtual void makeNonSingular(CoinSimplexInt * sequence); protected: /** Does sparse phase of factorization return code is <0 error, 0= finished */ CoinSimplexInt factorSparse ( ); /** Does dense phase of factorization return code is <0 error, 0= finished */ CoinSimplexInt factorDense ( ); /// Pivots when just one other row so faster? bool pivotOneOtherRow ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ); /// Does one pivot on Row Singleton in factorization bool pivotRowSingleton ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ); /// Does one pivot on Column Singleton in factorization (can't return false) void pivotColumnSingleton ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ); /// After pivoting void afterPivot( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn ); /// After pivoting - returns true if need to go dense int wantToGoDense(); /** Gets space for one Column with given length, may have to do compression (returns True if successful), also moves existing vector, extraNeeded is over and above present */ bool getColumnSpace ( CoinSimplexInt iColumn, CoinSimplexInt extraNeeded ); /** Reorders U so contiguous and in order (if there is space) Returns true if it could */ bool reorderU(); /** getColumnSpaceIterateR. Gets space for one extra R element in Column may have to do compression (returns true) also moves existing vector */ bool getColumnSpaceIterateR ( CoinSimplexInt iColumn, CoinFactorizationDouble value, CoinSimplexInt iRow); /** getColumnSpaceIterate. Gets space for one extra U element in Column may have to do compression (returns true) also moves existing vector. Returns -1 if no memory or where element was put Used by replaceRow (turns off R version) */ CoinBigIndex getColumnSpaceIterate ( CoinSimplexInt iColumn, CoinFactorizationDouble value, CoinSimplexInt iRow); /** Gets space for one Row with given length, may have to do compression (returns True if successful), also moves existing vector */ bool getRowSpace ( CoinSimplexInt iRow, CoinSimplexInt extraNeeded ); /** Gets space for one Row with given length while iterating, may have to do compression (returns True if successful), also moves existing vector */ bool getRowSpaceIterate ( CoinSimplexInt iRow, CoinSimplexInt extraNeeded ); /// Checks that row and column copies look OK void checkConsistency ( ); //#define CHECK_LINKS #ifdef CHECK_LINKS void checkLinks(int x=0); #else # define checkLinks(x) #endif /// Adds a link in chain of equal counts inline void addLink ( CoinSimplexInt index, CoinSimplexInt count ) { CoinSimplexInt * COIN_RESTRICT nextCount = nextCountAddress_; CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCount(); CoinSimplexInt * COIN_RESTRICT lastCount = lastCountAddress_; CoinSimplexInt next = firstCount[count]; firstCount[count] = index; nextCount[index] = next; lastCount[index] = count-numberRows_-2; // points to firstCount[count] if (next>=0) lastCount[next] = index; } /// Deletes a link in chain of equal counts inline void deleteLink ( CoinSimplexInt index ) { CoinSimplexInt * COIN_RESTRICT nextCount = nextCountAddress_; CoinSimplexInt * COIN_RESTRICT lastCount = lastCountAddress_; CoinSimplexInt next = nextCount[index]; CoinSimplexInt last = lastCount[index]; assert (next!=index); assert (last!=index); if (next>=0) lastCount[next] = last; if (last>=0) { nextCount[last] = next; } else { int count=last+numberRows_+2; CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCount(); firstCount[count]=next; } } /// Modifies links in chain of equal counts inline void modifyLink ( CoinSimplexInt index, CoinSimplexInt count ) { CoinSimplexInt * COIN_RESTRICT nextCount = nextCountAddress_; CoinSimplexInt * COIN_RESTRICT lastCount = lastCountAddress_; CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCount(); CoinSimplexInt next2 = firstCount[count]; if (next2==index) return; firstCount[count] = index; CoinSimplexInt next = nextCount[index]; CoinSimplexInt last = lastCount[index]; assert (next!=index); assert (last!=index); nextCount[index] = next2; lastCount[index] = count-numberRows_-2; // points to firstCount[count] if (next>=0) lastCount[next] = last; if (next2>=0) lastCount[next2] = index; if (last>=0) { nextCount[last] = next; } else { int count=last+numberRows_+2; firstCount[count]=next; } } /// Separate out links with same row/column count void separateLinks(); void separateLinks(CoinSimplexInt,CoinSimplexInt); /// Cleans up at end of factorization void cleanup ( ); /// Set up addresses from arrays void doAddresses(); /// Updates part of column (FTRANL) void updateColumnL ( CoinIndexedVector * region #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse=0 #endif ) const; /// Updates part of column (FTRANL) when densish void updateColumnLDensish ( CoinIndexedVector * region ) const; /// Updates part of column (FTRANL) when dense (i.e. do as inner products) void updateColumnLDense ( CoinIndexedVector * region ) const; /// Updates part of column (FTRANL) when sparse void updateColumnLSparse ( CoinIndexedVector * region #if ABC_PARALLEL ,int whichSparse #endif ) const; /// Updates part of column (FTRANR) without FT update void updateColumnR ( CoinIndexedVector * region #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse=0 #endif ) const; /// Store update after doing L and R - retuns false if no room bool storeFT( #if ABC_SMALL<3 const #endif CoinIndexedVector * regionFT); /// Updates part of column (FTRANU) void updateColumnU ( CoinIndexedVector * region #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse=0 #endif ) const; /// Updates part of column (FTRANU) when sparse void updateColumnUSparse ( CoinIndexedVector * regionSparse #if ABC_PARALLEL ,int whichSparse #endif ) const; /// Updates part of column (FTRANU) void updateColumnUDensish ( CoinIndexedVector * regionSparse) const; /// Updates part of column (FTRANU) when dense (i.e. do as inner products) void updateColumnUDense ( CoinIndexedVector * regionSparse) const; /// Updates part of 2 columns (FTRANU) real work void updateTwoColumnsUDensish ( CoinSimplexInt & numberNonZero1, CoinFactorizationDouble * COIN_RESTRICT region1, CoinSimplexInt * COIN_RESTRICT index1, CoinSimplexInt & numberNonZero2, CoinFactorizationDouble * COIN_RESTRICT region2, CoinSimplexInt * COIN_RESTRICT index2) const; /// Updates part of column PFI (FTRAN) (after rest) void updateColumnPFI ( CoinIndexedVector * regionSparse) const; /// Updates part of column transpose PFI (BTRAN) (before rest) void updateColumnTransposePFI ( CoinIndexedVector * region) const; /** Updates part of column transpose (BTRANU), assumes index is sorted i.e. region is correct */ void updateColumnTransposeU ( CoinIndexedVector * region, CoinSimplexInt smallestIndex #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichCpu #endif ) const; /** Updates part of column transpose (BTRANU) when densish, assumes index is sorted i.e. region is correct */ void updateColumnTransposeUDensish ( CoinIndexedVector * region, CoinSimplexInt smallestIndex) const; /** Updates part of column transpose (BTRANU) when sparse, assumes index is sorted i.e. region is correct */ void updateColumnTransposeUSparse ( CoinIndexedVector * region #if ABC_PARALLEL ,int whichSparse #endif ) const; /** Updates part of column transpose (BTRANU) by column assumes index is sorted i.e. region is correct */ void updateColumnTransposeUByColumn ( CoinIndexedVector * region, CoinSimplexInt smallestIndex) const; /// Updates part of column transpose (BTRANR) void updateColumnTransposeR ( CoinIndexedVector * region #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif ) const; /// Updates part of column transpose (BTRANR) when dense void updateColumnTransposeRDensish ( CoinIndexedVector * region ) const; /// Updates part of column transpose (BTRANR) when sparse void updateColumnTransposeRSparse ( CoinIndexedVector * region ) const; /// Updates part of column transpose (BTRANL) void updateColumnTransposeL ( CoinIndexedVector * region #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse #endif ) const; /// Updates part of column transpose (BTRANL) when densish by column void updateColumnTransposeLDensish ( CoinIndexedVector * region ) const; /// Updates part of column transpose (BTRANL) when densish by row void updateColumnTransposeLByRow ( CoinIndexedVector * region ) const; /// Updates part of column transpose (BTRANL) when sparse (by Row) void updateColumnTransposeLSparse ( CoinIndexedVector * region #if ABC_PARALLEL ,int whichSparse #endif ) const; public: /** Replaces one Column to basis for PFI returns 0=OK, 1=Probably OK, 2=singular, 3=no room. In this case region is not empty - it is incoming variable (updated) */ CoinSimplexInt replaceColumnPFI ( CoinIndexedVector * regionSparse, CoinSimplexInt pivotRow, CoinSimplexDouble alpha); protected: /** Returns accuracy status of replaceColumn returns 0=OK, 1=Probably OK, 2=singular */ CoinSimplexInt checkPivot(CoinSimplexDouble saveFromU, CoinSimplexDouble oldPivot) const; /// 0 fine, -99 singular, 2 dense int pivot ( CoinSimplexInt pivotRow, CoinSimplexInt pivotColumn, CoinBigIndex pivotRowPosition, CoinBigIndex pivotColumnPosition, CoinFactorizationDouble * COIN_RESTRICT work, CoinSimplexUnsignedInt * COIN_RESTRICT workArea2, CoinSimplexInt increment2, int * COIN_RESTRICT markRow ); int pivot ( CoinSimplexInt & pivotRow, CoinSimplexInt & pivotColumn, CoinBigIndex pivotRowPosition, CoinBigIndex pivotColumnPosition, int * COIN_RESTRICT markRow ); #if ABC_SMALL<2 #define CONVERTROW 2 #elif ABC_SMALL<4 #else #undef ABC_DENSE_CODE #define ABC_DENSE_CODE 0 #endif //@} ////////////////// data ////////////////// protected: /**@name data */ //@{ CoinSimplexInt * pivotColumnAddress_; CoinSimplexInt * permuteAddress_; CoinFactorizationDouble * pivotRegionAddress_; CoinFactorizationDouble * elementUAddress_; CoinSimplexInt * indexRowUAddress_; CoinSimplexInt * numberInColumnAddress_; CoinSimplexInt * numberInColumnPlusAddress_; #ifdef ABC_USE_FUNCTION_POINTERS /// Array of function pointers scatterStruct * scatterPointersUColumnAddress_; CoinFactorizationDouble * elementUColumnPlusAddress_; #endif CoinBigIndex * startColumnUAddress_; #if CONVERTROW CoinBigIndex * convertRowToColumnUAddress_; #if CONVERTROW>1 CoinBigIndex * convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * elementRowUAddress_; #endif CoinBigIndex * startRowUAddress_; CoinSimplexInt * numberInRowAddress_; CoinSimplexInt * indexColumnUAddress_; CoinSimplexInt * firstCountAddress_; /// Next Row/Column with count CoinSimplexInt * nextCountAddress_; /// Previous Row/Column with count CoinSimplexInt * lastCountAddress_; CoinSimplexInt * nextColumnAddress_; CoinSimplexInt * lastColumnAddress_; CoinSimplexInt * nextRowAddress_; CoinSimplexInt * lastRowAddress_; CoinSimplexInt * saveColumnAddress_; //CoinSimplexInt * saveColumnAddress2_; CoinCheckZero * markRowAddress_; CoinSimplexInt * listAddress_; CoinFactorizationDouble * elementLAddress_; CoinSimplexInt * indexRowLAddress_; CoinBigIndex * startColumnLAddress_; #if ABC_SMALL<2 CoinBigIndex * startRowLAddress_; #endif CoinSimplexInt * pivotLinkedBackwardsAddress_; CoinSimplexInt * pivotLinkedForwardsAddress_; CoinSimplexInt * pivotLOrderAddress_; CoinBigIndex * startColumnRAddress_; /// Elements of R CoinFactorizationDouble *elementRAddress_; /// Row indices for R CoinSimplexInt *indexRowRAddress_; CoinSimplexInt * indexColumnLAddress_; CoinFactorizationDouble * elementByRowLAddress_; #if ABC_SMALL<4 CoinFactorizationDouble * denseAreaAddress_; #endif CoinFactorizationDouble * workAreaAddress_; CoinSimplexUnsignedInt * workArea2Address_; mutable CoinSimplexInt * sparseAddress_; #ifdef SMALL_PERMUTE CoinSimplexInt * fromSmallToBigRow_; CoinSimplexInt * fromSmallToBigColumn_; #endif /// Number of Rows after iterating CoinSimplexInt numberRowsExtra_; /// Maximum number of Rows after iterating CoinSimplexInt maximumRowsExtra_; /// Size of small inverse CoinSimplexInt numberRowsSmall_; /// Number factorized in L CoinSimplexInt numberGoodL_; /// Number Rows left (numberRows-numberGood) CoinSimplexInt numberRowsLeft_; /// Number of elements in U (to go) /// or while iterating total overall CoinBigIndex totalElements_; /// First place in funny copy zeroed out CoinBigIndex firstZeroed_; #if ABC_SMALL<2 /// Below this use sparse technology - if 0 then no L row copy CoinSimplexInt sparseThreshold_; #endif /// Number in R CoinSimplexInt numberR_; /// Length of R stuff CoinBigIndex lengthR_; /// length of area reserved for R CoinBigIndex lengthAreaR_; /// Number in L CoinBigIndex numberL_; /// Base of L CoinBigIndex baseL_; /// Length of L CoinBigIndex lengthL_; /// Length of area reserved for L CoinBigIndex lengthAreaL_; /// Number in U CoinSimplexInt numberU_; /// Maximum space used in U CoinBigIndex maximumU_; /// Length of U CoinBigIndex lengthU_; /// Length of area reserved for U CoinBigIndex lengthAreaU_; /// Last entry by column for U CoinBigIndex lastEntryByColumnU_; #ifdef ABC_USE_FUNCTION_POINTERS /// Last entry by column for U CoinBigIndex lastEntryByColumnUPlus_; /// Length of U CoinBigIndex lengthAreaUPlus_; #endif /// Last entry by row for U CoinBigIndex lastEntryByRowU_; /// Number of trials before rejection CoinSimplexInt numberTrials_; #if ABC_SMALL<4 /// Leading dimension for dense CoinSimplexInt leadingDimension_; #endif #if COIN_BIG_DOUBLE==1 /// Work arrays mutable CoinFactorizationLongDoubleArrayWithLength longArray_[FACTOR_CPU]; /// Associated CoinIndexedVector mutable CoinIndexedVector * associatedVector_[FACTOR_CPU]; #endif /// Pivot order for each Column CoinIntArrayWithLength pivotColumn_; /// Permutation vector for pivot row order CoinIntArrayWithLength permute_; /// Start of each Row as pointer CoinBigIndexArrayWithLength startRowU_; /// Number in each Row CoinIntArrayWithLength numberInRow_; /// Number in each Column CoinIntArrayWithLength numberInColumn_; /// Number in each Column including pivoted CoinIntArrayWithLength numberInColumnPlus_; /** First Row/Column with count of k, can tell which by offset - Rows then Columns */ CoinIntArrayWithLength firstCount_; /// Next Column in memory order CoinIntArrayWithLength nextColumn_; /// Previous Column in memory order CoinIntArrayWithLength lastColumn_; /// Next Row in memory order CoinIntArrayWithLength nextRow_; /// Previous Row in memory order CoinIntArrayWithLength lastRow_; /// Columns left to do in a single pivot CoinIntArrayWithLength saveColumn_; /// Marks rows to be updated CoinIntArrayWithLength markRow_; /// Base address for U (may change) CoinIntArrayWithLength indexColumnU_; /// Inverses of pivot values CoinFactorizationDoubleArrayWithLength pivotRegion_; /// Elements of U CoinFactorizationDoubleArrayWithLength elementU_; /// Row indices of U CoinIntArrayWithLength indexRowU_; /// Start of each column in U CoinBigIndexArrayWithLength startColumnU_; #ifdef ABC_USE_FUNCTION_POINTERS /// Array of structs for U Column CoinArbitraryArrayWithLength scatterUColumn_; #endif #if CONVERTROW /// Converts rows to columns in U CoinBigIndexArrayWithLength convertRowToColumnU_; #if CONVERTROW>1 /// Converts columns to rows in U CoinBigIndexArrayWithLength convertColumnToRowU_; #endif #endif #if ABC_SMALL<2 /// Elements of U by row CoinFactorizationDoubleArrayWithLength elementRowU_; #endif /// Elements of L CoinFactorizationDoubleArrayWithLength elementL_; /// Row indices of L CoinIntArrayWithLength indexRowL_; /// Start of each column in L CoinBigIndexArrayWithLength startColumnL_; #if ABC_SMALL<4 /// Dense area CoinFactorizationDoubleArrayWithLength denseArea_; #endif /// First work area CoinFactorizationDoubleArrayWithLength workArea_; /// Second work area CoinUnsignedIntArrayWithLength workArea2_; #if ABC_SMALL<2 /// Start of each row in L CoinBigIndexArrayWithLength startRowL_; /// Index of column in row for L CoinIntArrayWithLength indexColumnL_; /// Elements in L (row copy) CoinFactorizationDoubleArrayWithLength elementByRowL_; /// Sparse regions mutable CoinIntArrayWithLength sparse_; #endif /// Detail in messages CoinSimplexInt messageLevel_; /// Number of compressions done CoinBigIndex numberCompressions_; // last slack pivot row CoinSimplexInt lastSlack_; #if ABC_SMALL<2 /// To decide how to solve mutable double ftranCountInput_; mutable double ftranCountAfterL_; mutable double ftranCountAfterR_; mutable double ftranCountAfterU_; double ftranAverageAfterL_; double ftranAverageAfterR_; double ftranAverageAfterU_; #if FACTORIZATION_STATISTICS double ftranTwiddleFactor1_; double ftranTwiddleFactor2_; #endif mutable CoinSimplexInt numberFtranCounts_; #endif /// Maximum rows (ever) (here to use double alignment) CoinSimplexInt maximumRows_; #if ABC_SMALL<2 mutable double ftranFTCountInput_; mutable double ftranFTCountAfterL_; mutable double ftranFTCountAfterR_; mutable double ftranFTCountAfterU_; double ftranFTAverageAfterL_; double ftranFTAverageAfterR_; double ftranFTAverageAfterU_; #if FACTORIZATION_STATISTICS double ftranFTTwiddleFactor1_; double ftranFTTwiddleFactor2_; #endif mutable CoinSimplexInt numberFtranFTCounts_; #endif #if ABC_SMALL<4 /// Dense threshold (here to use double alignment) CoinSimplexInt denseThreshold_; #endif #if ABC_SMALL<2 mutable double btranCountInput_; mutable double btranCountAfterU_; mutable double btranCountAfterR_; mutable double btranCountAfterL_; double btranAverageAfterU_; double btranAverageAfterR_; double btranAverageAfterL_; #if FACTORIZATION_STATISTICS double btranTwiddleFactor1_; double btranTwiddleFactor2_; #endif mutable CoinSimplexInt numberBtranCounts_; #endif /// Maximum maximum pivots CoinSimplexInt maximumMaximumPivots_; #if ABC_SMALL<2 /// To decide how to solve mutable double ftranFullCountInput_; mutable double ftranFullCountAfterL_; mutable double ftranFullCountAfterR_; mutable double ftranFullCountAfterU_; double ftranFullAverageAfterL_; double ftranFullAverageAfterR_; double ftranFullAverageAfterU_; #if FACTORIZATION_STATISTICS double ftranFullTwiddleFactor1_; double ftranFullTwiddleFactor2_; #endif mutable CoinSimplexInt numberFtranFullCounts_; #endif /// Rows first time nonzero CoinSimplexInt initialNumberRows_; #if ABC_SMALL<2 /// To decide how to solve mutable double btranFullCountInput_; mutable double btranFullCountAfterL_; mutable double btranFullCountAfterR_; mutable double btranFullCountAfterU_; double btranFullAverageAfterL_; double btranFullAverageAfterR_; double btranFullAverageAfterU_; #if FACTORIZATION_STATISTICS double btranFullTwiddleFactor1_; double btranFullTwiddleFactor2_; #endif mutable CoinSimplexInt numberBtranFullCounts_; #endif /** State of saved version and what can be done 0 - nothing saved 1 - saved and can go back to previous save by unwinding 2 - saved - getting on for a full copy higher bits - see ABC_FAC.... */ CoinSimplexInt state_; /// Size in bytes of a sparseArray CoinBigIndex sizeSparseArray_; public: #if ABC_SMALL<2 #if ABC_SMALL>=0 inline bool gotLCopy() const {return ((state_&ABC_FAC_GOT_LCOPY)!=0);} inline void setNoGotLCopy() {state_ &= ~ABC_FAC_GOT_LCOPY;} inline void setYesGotLCopy() {state_ |= ABC_FAC_GOT_LCOPY;} inline bool gotRCopy() const {return ((state_&ABC_FAC_GOT_RCOPY)!=0);} inline void setNoGotRCopy() {state_ &= ~ABC_FAC_GOT_RCOPY;} inline void setYesGotRCopy() {state_ |= ABC_FAC_GOT_RCOPY;} inline bool gotUCopy() const {return ((state_&ABC_FAC_GOT_UCOPY)!=0);} inline void setNoGotUCopy() {state_ &= ~ABC_FAC_GOT_UCOPY;} inline void setYesGotUCopy() {state_ |= ABC_FAC_GOT_UCOPY;} inline bool gotSparse() const {return ((state_&ABC_FAC_GOT_SPARSE)!=0);} inline void setNoGotSparse() {state_ &= ~ABC_FAC_GOT_SPARSE;} inline void setYesGotSparse() {state_ |= ABC_FAC_GOT_SPARSE;} #else // force use of copies inline bool gotLCopy() const {return true;} inline void setNoGotLCopy() {} inline void setYesGotLCopy() {} inline bool gotRCopy() const {return true;} inline void setNoGotRCopy() {} inline void setYesGotRCopy() {} inline bool gotUCopy() const {return true;} inline void setNoGotUCopy() {} inline void setYesGotUCopy() {} inline bool gotSparse() const {return true;} inline void setNoGotSparse() {} inline void setYesGotSparse() {} #endif #else // force no use of copies inline bool gotLCopy() const {return false;} inline void setNoGotLCopy() {} inline void setYesGotLCopy() {} inline bool gotRCopy() const {return false;} inline void setNoGotRCopy() {} inline void setYesGotRCopy() {} inline bool gotUCopy() const {return false;} inline void setNoGotUCopy() {} inline void setYesGotUCopy() {} inline bool gotSparse() const {return false;} inline void setNoGotSparse() {} inline void setYesGotSparse() {} #endif /** Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ //CoinSimplexInt persistenceFlag_; //@} }; Clp-1.15.10/src/CoinAbcBaseFactorization4.cpp0000644000076600007660000045420512101105055017260 0ustar coincoin/* $Id: CoinAbcBaseFactorization4.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #if CILK_CONFLICT>0 // for conflicts extern int cilk_conflict; #endif //:class CoinAbcTypeFactorization. Deals with Factorization and Updates #if ABC_SMALL<2 // getColumnSpaceIterateR. Gets space for one extra R element in Column //may have to do compression (returns true) //also moves existing vector bool CoinAbcTypeFactorization::getColumnSpaceIterateR ( CoinSimplexInt iColumn, CoinFactorizationDouble value, CoinSimplexInt iRow) { CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_ + lengthAreaR_; CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_ + lengthAreaR_; CoinBigIndex * COIN_RESTRICT startR = startColumnRAddress_+maximumPivots_+1; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; CoinSimplexInt number = numberInColumnPlus[iColumn]; //*** modify so sees if can go in //see if it can go in at end CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; if (lengthAreaR_-startR[maximumRowsExtra_] (put + 4) ,lengthAreaR_); return true; } #endif CoinSimplexInt CoinAbcTypeFactorization::checkPivot(CoinSimplexDouble saveFromU, CoinSimplexDouble oldPivot) const { CoinSimplexInt status; if ( fabs ( saveFromU ) > 1.0e-8 ) { CoinFactorizationDouble checkTolerance; if ( numberRowsExtra_ < numberRows_ + 2 ) { checkTolerance = 1.0e-5; } else if ( numberRowsExtra_ < numberRows_ + 10 ) { checkTolerance = 1.0e-6; } else if ( numberRowsExtra_ < numberRows_ + 50 ) { checkTolerance = 1.0e-8; } else { checkTolerance = 1.0e-10; } checkTolerance *= relaxCheck_; if ( fabs ( 1.0 - fabs ( saveFromU / oldPivot ) ) < checkTolerance ) { status = 0; } else { #if COIN_DEBUG std::cout <<"inaccurate pivot "<< oldPivot << " " << saveFromU << std::endl; #endif if ( fabs ( fabs ( oldPivot ) - fabs ( saveFromU ) ) < 1.0e-12 || fabs ( 1.0 - fabs ( saveFromU / oldPivot ) ) < 1.0e-8 ) { status = 1; } else { status = 2; } } } else { //error status = 2; #if COIN_DEBUG std::cout <<"inaccurate pivot "<< saveFromU / oldPivot << " " << saveFromU << std::endl; #endif } return status; } #define INLINE_IT #define INLINE_IT2 #define INLINE_IT3 #define UNROLL 0 inline void scatterUpdateInline(CoinSimplexInt number, CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL==0 for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL==1 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL==2 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(number) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { CoinFactorizationDouble pivotValue=0.0; for (CoinBigIndex j = 0; j < number; j ++ ) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; } inline void multiplyIndexed(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT multiplier, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { for (CoinSimplexInt i = 0; i < number; i ++ ) { CoinSimplexInt iRow = thisIndex[i]; CoinSimplexDouble value = region[iRow]; value *= multiplier[iRow]; region[iRow] = value; } } #if 0 /* Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots Fills in region for use later partial update already in U */ int CoinAbcTypeFactorization::checkReplace ( const AbcSimplex * model, CoinIndexedVector * regionSparse, int pivotRow, CoinSimplexDouble &pivotCheck, double acceptablePivot) { if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 3; } #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room return 3; } #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check pivotCheck = pivotCheck / oldPivot; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow; #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); } } else { #endif #if ABC_SMALL>=0 // No row copy check space CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL<2 } #endif numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } //check accuracy status = checkPivot(saveFromU,pivotCheck); if (status==1&&!numberPivots_) { printf("check status ok\n"); status=2; } pivotCheck=saveFromU; return status; } // replaceColumn. Replaces one Column to basis // returns 0=OK, 1=Probably OK, 2=singular, 3=no room //partial update already in U CoinSimplexInt CoinAbcTypeFactorization::replaceColumn ( CoinIndexedVector * regionSparse, CoinSimplexInt pivotRow, CoinSimplexDouble pivotCheck , bool skipBtranU, CoinSimplexDouble ) { assert (numberU_<=numberRowsExtra_); #ifndef ALWAYS_SKIP_BTRAN //return at once if too many iterations if ( numberRowsExtra_ >= maximumRowsExtra_ ) { return 5; } if ( lengthAreaU_ < lastEntryByColumnU_ ) { return 3; } #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif CoinSimplexInt * COIN_RESTRICT permuteLookup = pivotColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; #else scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset=startU; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #endif #ifndef ALWAYS_SKIP_BTRAN #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow; #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; } #endif CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ALWAYS_SKIP_BTRAN if (!skipBtranU) { CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check pivotCheck = pivotCheck / oldPivot; #if ABC_SMALL<2 if (gotUCopy()) { CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); } } else { #endif #if ABC_SMALL>=0 // No row copy check space if ( lengthR_ + numberRows_>= lengthAreaR_ ) { //not enough room return 3; } CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL<2 } #endif } #endif numberNonZero = regionSparse->getNumElements ( ); CoinFactorizationDouble saveFromU = 0.0; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow]=startU; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #else //CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; #endif instrument_do("CoinAbcFactorizationReplaceColumn",2*numberRows_+4*numberInColumnU2); #ifndef ALWAYS_SKIP_BTRAN if (!skipBtranU) { for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } //check accuracy status = checkPivot(saveFromU,pivotCheck); } else { status=0; saveFromU=pivotCheck; } //regionSparse->print(); #endif if (status>1||(status==1&&!numberPivots_)) { // restore some things //pivotRegion[pivotRow] = oldPivot; CoinSimplexInt number = saveEnd-saveStart; totalElements_ += number; //numberInColumn[pivotRow]=number; regionSparse->clear(); return status; } else { pivotValue = 1.0 / saveFromU; // do what we would have done by now #if ABC_SMALL<2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j=0;j(area+k+1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j=0;j=0 // no row copy CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); for (CoinSimplexInt i = 0; i < nInRow ; i ++ ) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn]-1; numberInColumn[jColumn]=k; CoinBigIndex k2 = k+startColumnU[jColumn]; int kRow2=indexRowU[k2]; indexRowU[j]=kRow2; CoinFactorizationDouble value2=elementU[k2]; elementU[j]=value2; } #endif #if ABC_SMALL<2 } #endif } #if ABC_SMALL<2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble * COIN_RESTRICT elementU = elementUColumnPlus+saveStart; saveStart=0; CoinSimplexInt * COIN_RESTRICT indexRowU = reinterpret_cast(elementU+saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd ; i ++ ) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow=indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end ; j ++ ) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn==pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j]=elementRowU[end-1]; #if CONVERTROW convertRowToColumn[j]=convertRowToColumn[end-1]; #endif indexColumnU[j]=indexColumnU[end-1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex * COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; if ( lengthR_ >= lengthAreaR_ ) { //not enough room regionSparse->clear(); return 3; } if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room regionSparse->clear(); return 3; } #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextRow=NULL; CoinSimplexInt * COIN_RESTRICT lastRow=NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow]=0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value=elementU2[i]; assert (value); if ( !TEST_LESS_THAN_TOLERANCE(value ) ) { if ( iRow != pivotRow ) { //modify by pivot CoinFactorizationDouble value2 = value*pivotValue; indexU2[n]=iRow; elementU2[n++] = value2; #if ABC_SMALL<2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if ( space <= 0 ) { getRowSpaceIterate ( iRow, iNumberInRow + 4 ); put = startRowU[iRow] + iNumberInRow; } else if (next==numberRows_) { lastEntryByRowU_=put+1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } else { // swap indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } numberInColumnU2=n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL<2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow]=numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2<9) { scatter[pivotRow].functionPointer=AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer=AbcScatterHighSubtract[numberInColumnU2&3]; } #endif assert(scatter[pivotRow].offset==lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2(area)>=0); for (int i=0;i>1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;ipivotLinkedForwardsAddress_[-1]); assert (pivotLinkedBackwardsAddress_[numberRows_]>=0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if ( numberRowsExtra_ > numberRows_ + 50 ) { CoinBigIndex extra = factorElements_ >> 1; if ( numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500 ) { if ( extra < 2 * numberRows_ ) { extra = 2 * numberRows_; } } else { if ( extra < 5 * numberRows_ ) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if ( added > extra && added > ( factorElements_ ) << 1 && !status && 3*totalElements_ > 2*(lengthAreaU_+lengthAreaL_)) { status = 3; if ( messageLevel_ & 4 ) { std::cout << "Factorization has "<< totalElements_ << ", basis had " << factorElements_ <numberInR) { // there is space CoinBigIndex put=startRR[iRow]+numberInR; numberInColumnPlus[iRow]=numberInR+1; indexRowRR[put]=pivotRow; elementRR[put]=value; //add 4 for luck if (next==maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast (put + 4) ,lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow,value,pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_=NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL<0 status=3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++ ) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow]=0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL<2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); //for (int i=0;i(elementU2+numberInColumnU2); #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region toLongArray(regionSparse,3); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif #if ABC_PARALLEL==0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ); #else assert (FACTOR_CPU>3); updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ,3 ); #endif } } else { #endif #if ABC_SMALL>=0 // No row copy check space CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL<2 } #endif if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 0.0; } #ifdef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #endif if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room return 0.0; } //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector ( ); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } return saveFromU; } /* Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update in vector */ #ifdef ABC_LONG_FACTORIZATION long #endif double CoinAbcTypeFactorization::checkReplacePart1 (CoinIndexedVector * regionSparse, CoinIndexedVector * partialUpdate, int pivotRow) { #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt * COIN_RESTRICT indexU2 = partialUpdate->getIndices(); CoinFactorizationDouble * COIN_RESTRICT elementU2 = denseVector(partialUpdate); CoinSimplexInt numberInColumnU2 = partialUpdate->getNumElements(); #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region toLongArray(regionSparse,3); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif #if ABC_PARALLEL==0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ); #else assert (FACTOR_CPU>3); updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ,3 ); #endif } } else { #endif #if ABC_SMALL>=0 // No row copy check space CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL<2 } #endif if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 0.0; } if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room partialUpdate->clear(); return 0.0; } //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector ( ); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[iRow] * region[iRow]; } else { saveFromU += elementU2[iRow]; } } return saveFromU; } #ifdef MOVE_REPLACE_PART1A /* Checks if can replace one Column in basis, returns update alpha Fills in region for use later partial update already in U */ void CoinAbcTypeFactorization::checkReplacePart1a (CoinIndexedVector * regionSparse, int pivotRow) { #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; //CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif #if ABC_PARALLEL==0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ); #else assert (FACTOR_CPU>3); updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ,3 ); #endif } } else { #endif #if ABC_SMALL>=0 // No row copy check space CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL<2 } #endif } #ifdef ABC_LONG_FACTORIZATION long #endif double CoinAbcTypeFactorization::checkReplacePart1b (CoinIndexedVector * regionSparse, int pivotRow) { if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 0.0; } #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room return 0.0; } CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } return saveFromU; } #endif #include "AbcSimplex.hpp" /* Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ int CoinAbcTypeFactorization::checkReplacePart2 ( int pivotRow, CoinSimplexDouble /*btranAlpha*/, CoinSimplexDouble ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha, double /*acceptablePivot*/) { if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 3; } CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check CoinFactorizationDouble pivotCheck = ftranAlpha / oldPivot; //check accuracy int status = checkPivot(ftAlpha,pivotCheck); if (status==1&&!numberPivots_) { printf("check status ok\n"); status=2; } return status; } /* Replaces one Column to basis, partial update already in U */ void CoinAbcTypeFactorization::replaceColumnPart3 ( const AbcSimplex * /*model*/, CoinIndexedVector * regionSparse, CoinIndexedVector * /*tableauColumn*/, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ) { assert (numberU_<=numberRowsExtra_); #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif CoinSimplexInt * COIN_RESTRICT permuteLookup = pivotColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; #else scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; #endif CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset=startU; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow=9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1 #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; } #endif CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; numberNonZero = regionSparse->getNumElements ( ); //CoinFactorizationDouble saveFromU = 0.0; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow]=startU; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #else //CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; #endif instrument_do("CoinAbcFactorizationReplaceColumn",2*numberRows_+4*numberInColumnU2); pivotValue = 1.0 / alpha; #if ABC_SMALL<2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j=0;j(area+k+1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j=0;j=0 assert(nInRow!=9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1 // no row copy CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); for (CoinSimplexInt i = 0; i < nInRow ; i ++ ) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn]-1; numberInColumn[jColumn]=k; CoinBigIndex k2 = k+startColumnU[jColumn]; int kRow2=indexRowU[k2]; indexRowU[j]=kRow2; CoinFactorizationDouble value2=elementU[k2]; elementU[j]=value2; } #endif #if ABC_SMALL<2 } #endif #if ABC_SMALL<2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble * COIN_RESTRICT elementU = elementUColumnPlus+saveStart; saveStart=0; CoinSimplexInt * COIN_RESTRICT indexRowU = reinterpret_cast(elementU+saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd ; i ++ ) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow=indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end ; j ++ ) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn==pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j]=elementRowU[end-1]; #if CONVERTROW convertRowToColumn[j]=convertRowToColumn[end-1]; #endif indexColumnU[j]=indexColumnU[end-1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex * COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextRow=NULL; CoinSimplexInt * COIN_RESTRICT lastRow=NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow]=0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value=elementU2[i]; assert (value); if ( !TEST_LESS_THAN_TOLERANCE(value ) ) { if ( iRow != pivotRow ) { //modify by pivot CoinFactorizationDouble value2 = value*pivotValue; indexU2[n]=iRow; elementU2[n++] = value2; #if ABC_SMALL<2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if ( space <= 0 ) { getRowSpaceIterate ( iRow, iNumberInRow + 4 ); put = startRowU[iRow] + iNumberInRow; } else if (next==numberRows_) { lastEntryByRowU_=put+1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } else { // swap indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } numberInColumnU2=n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL<2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow]=numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2<9) { scatter[pivotRow].functionPointer=AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer=AbcScatterHighSubtract[numberInColumnU2&3]; } #endif assert(scatter[pivotRow].offset==lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2(area)>=0); for (int i=0;i>1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;ipivotLinkedForwardsAddress_[-1]); assert (pivotLinkedBackwardsAddress_[numberRows_]>=0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if ( numberRowsExtra_ > numberRows_ + 50 ) { CoinBigIndex extra = factorElements_ >> 1; if ( numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500 ) { if ( extra < 2 * numberRows_ ) { extra = 2 * numberRows_; } } else { if ( extra < 5 * numberRows_ ) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if ( added > extra && added > ( factorElements_ ) << 1 && !status && 3*totalElements_ > 2*(lengthAreaU_+lengthAreaL_)) { status = 3; if ( messageLevel_ & 4 ) { std::cout << "Factorization has "<< totalElements_ << ", basis had " << factorElements_ <numberInR) { // there is space CoinBigIndex put=startRR[iRow]+numberInR; numberInColumnPlus[iRow]=numberInR+1; indexRowRR[put]=pivotRow; elementRR[put]=value; //add 4 for luck if (next==maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast (put + 4) ,lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow,value,pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_=NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL<0 abort(); status=3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++ ) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow]=0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL<2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); fromLongArray(regionSparse); #if 0 static int arrayF[6]={1,1,1,1,1,1}; static int arrayB[6]={1,1,1,1,1,1}; static int arrayF1[6]={1,1,1,1,1,1}; static int arrayB1[6]={1,1,1,1,1,1}; static int itry=0; { const CoinSimplexInt * COIN_RESTRICT back = firstCountAddress_+numberRows_; const CoinSimplexInt * COIN_RESTRICT pivotColumn = pivotColumnAddress_; // no const CoinSimplexInt * COIN_RESTRICT permute = permuteAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = this->pivotLOrderAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_;//no const CoinSimplexInt * COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_;//no itry++; int testit[6]; for (int i=0;i<6;i++) testit[i]=1; for (int i=0;igetNumElements(); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow]=startU; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; numberInColumn[numberRows_]=numberInColumnU2; #else scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; #endif CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = lastEntryByColumnUPlus_; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset=startU; scatter[numberRows_].number=numberInColumnU2; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #endif // move CoinSimplexInt * COIN_RESTRICT indexU2Save = partialUpdate->getIndices(); CoinFactorizationDouble * COIN_RESTRICT elementU2Save = denseVector(partialUpdate); memcpy(indexU2,indexU2Save,numberInColumnU2*sizeof(CoinSimplexInt)); for (int i=0;isetNumElements(0); //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW>2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL<2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow=9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1 #if ABC_SMALL<2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; } #endif CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; numberNonZero = regionSparse->getNumElements ( ); //CoinFactorizationDouble saveFromU = 0.0; instrument_do("CoinAbcFactorizationReplaceColumn",2*numberRows_+4*numberInColumnU2); pivotValue = 1.0 / alpha; #if ABC_SMALL<2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j=0;j(area+k+1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j=0;j=0 assert(nInRow!=9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1 // no row copy CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); for (CoinSimplexInt i = 0; i < nInRow ; i ++ ) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn]-1; numberInColumn[jColumn]=k; CoinBigIndex k2 = k+startColumnU[jColumn]; int kRow2=indexRowU[k2]; indexRowU[j]=kRow2; CoinFactorizationDouble value2=elementU[k2]; elementU[j]=value2; } #endif #if ABC_SMALL<2 } #endif #if ABC_SMALL<2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble * COIN_RESTRICT elementU = elementUColumnPlus+saveStart; saveStart=0; CoinSimplexInt * COIN_RESTRICT indexRowU = reinterpret_cast(elementU+saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd ; i ++ ) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow=indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end ; j ++ ) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn==pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j]=elementRowU[end-1]; #if CONVERTROW convertRowToColumn[j]=convertRowToColumn[end-1]; #endif indexColumnU[j]=indexColumnU[end-1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex * COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextRow=NULL; CoinSimplexInt * COIN_RESTRICT lastRow=NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow]=0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value=elementU2[i]; assert (value); if ( !TEST_LESS_THAN_TOLERANCE(value ) ) { if ( iRow != pivotRow ) { //modify by pivot CoinFactorizationDouble value2 = value*pivotValue; indexU2[n]=iRow; elementU2[n++] = value2; #if ABC_SMALL<2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if ( space <= 0 ) { getRowSpaceIterate ( iRow, iNumberInRow + 4 ); put = startRowU[iRow] + iNumberInRow; } else if (next==numberRows_) { lastEntryByRowU_=put+1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } else { // swap indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } numberInColumnU2=n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL<2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow]=numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2<9) { scatter[pivotRow].functionPointer=AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer=AbcScatterHighSubtract[numberInColumnU2&3]; } #endif assert(scatter[pivotRow].offset==lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2(area)>=0); for (int i=0;i>1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL<2 CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;ipivotLinkedForwardsAddress_[-1]); assert (pivotLinkedBackwardsAddress_[numberRows_]>=0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if ( numberRowsExtra_ > numberRows_ + 50 ) { CoinBigIndex extra = factorElements_ >> 1; if ( numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500 ) { if ( extra < 2 * numberRows_ ) { extra = 2 * numberRows_; } } else { if ( extra < 5 * numberRows_ ) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if ( added > extra && added > ( factorElements_ ) << 1 && !status && 3*totalElements_ > 2*(lengthAreaU_+lengthAreaL_)) { status = 3; if ( messageLevel_ & 4 ) { std::cout << "Factorization has "<< totalElements_ << ", basis had " << factorElements_ <numberInR) { // there is space CoinBigIndex put=startRR[iRow]+numberInR; numberInColumnPlus[iRow]=numberInR+1; indexRowRR[put]=pivotRow; elementRR[put]=value; //add 4 for luck if (next==maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast (put + 4) ,lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow,value,pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_=NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL<0 abort(); status=3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++ ) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow]=0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL<2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); } #if ABC_SMALL>=0 /* Combines BtranU and store which elements are to be deleted */ int CoinAbcTypeFactorization::replaceColumnU ( CoinIndexedVector * regionSparse, CoinBigIndex * deletedPosition, CoinSimplexInt * deletedColumns, CoinSimplexInt pivotRow) { instrument_start("CoinAbcFactorizationReplaceColumnU",numberRows_); CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector(); int * COIN_RESTRICT regionIndex = regionSparse->getIndices(); const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_; CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_; int numberNonZero = 0; const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; int nPut=0; const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; while (jRow!=numberRows_) { assert (!region[jRow]); CoinFactorizationDouble pivotValue = 0.0; instrument_add(numberInColumn[jRow]); for (CoinBigIndex j= startColumn[jRow] ; j < startColumn[jRow]+numberInColumn[jRow]; j++ ) { int iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; if (iRow!=pivotRow) { pivotValue -= value * region[iRow]; } else { assert (!region[iRow]); pivotValue += value; deletedColumns[nPut]=jRow; deletedPosition[nPut++]=j; } } if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { regionIndex[numberNonZero++] = jRow; region[jRow] = pivotValue; } else { region[jRow] = 0; } jRow=pivotLinked[jRow]; } regionSparse->setNumElements(numberNonZero); instrument_end(); return nPut; } /* Updates part of column transpose (BTRANU) by column assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUByColumn ( CoinIndexedVector * regionSparse, CoinSimplexInt smallestIndex) const { instrument_start("CoinAbcFactorizationUpdateTransposeUByColumn",numberRows_); CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector(); const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_; const CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_; #if ABC_SMALL<3 int numberNonZero = 0; int * COIN_RESTRICT regionIndex = regionSparse->getIndices(); #endif const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; //const CoinFactorizationDouble COIN_RESTRICT *pivotRegion = pivotRegionAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=smallestIndex; while (jRow!=numberRows_) { CoinFactorizationDouble pivotValue = region[jRow]; CoinBigIndex start=startColumn[jRow]; instrument_add(numberInColumn[jRow]); #ifndef INLINE_IT2 for (CoinBigIndex j= start ; j < start+numberInColumn[jRow]; j++ ) { int iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; pivotValue -= value * region[iRow]; } #else pivotValue+=CoinAbcGatherUpdate(numberInColumn[jRow],element+start,indexRow+start,region); #endif #if ABC_SMALL<3 if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { regionIndex[numberNonZero++] = jRow; region[jRow] = pivotValue; } else { region[jRow] = 0; } #else region[jRow] = pivotValue; #endif jRow=pivotLinked[jRow]; } #if ABC_SMALL<3 regionSparse->setNumElements(numberNonZero); #endif instrument_end(); } #endif // updateColumnTranspose. Updates one column transpose (BTRAN) CoinSimplexInt CoinAbcTypeFactorization::updateColumnTranspose ( CoinIndexedVector & regionSparse) const { toLongArray(®ionSparse,0); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse.getIndices(); CoinSimplexInt numberNonZero = regionSparse.getNumElements(); const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_ORDERED_FACTORIZATION // can I move this #ifndef INLINE_IT3 for (CoinSimplexInt i = 0; i < numberNonZero; i ++ ) { CoinSimplexInt iRow = regionIndex[i]; CoinSimplexDouble value = region[iRow]; value *= pivotRegion[iRow]; region[iRow] = value; } #else multiplyIndexed(numberNonZero,pivotRegion, regionIndex,region); #endif #else // Permute in for Btran permuteInForBtranAndMultiply(regionSparse); #endif // ******* U // Apply pivot region - could be combined for speed // Can only combine/move inside vector for sparse CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; #if ABC_SMALL<2 // copy of code inside transposeU bool goSparse=false; #else #define goSparse false #endif #if ABC_SMALL<2 // Guess at number at end if (gotUCopy()) { assert (btranAverageAfterU_); CoinSimplexInt newNumber = static_cast (numberNonZero*btranAverageAfterU_*twiddleBtranFactor1()); if (newNumber< sparseThreshold_) goSparse = true; } #endif #if 0 static int xxxxxx=0; xxxxxx++; if (xxxxxx%20==0) { int smallestK=-1; int largestK=-1; //const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) { CoinSimplexInt i=pivotRowForward[k]; if (numberInColumn[i]) { if (largestK<0) largestK=k; smallestK=k; } } printf("UByCol %d slacks largestK %d smallestK %d\n",numberSlacks_,largestK,smallestK); //const CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; smallestK=-1; largestK=-1; for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) { CoinSimplexInt i=pivotRowForward[k]; if (numberInRow[i]) { if (largestK<0) largestK=k; smallestK=k; } } printf("and ByRow largestK %d smallestK %d\n",largestK,smallestK); } #endif if (numberNonZero<40&&(numberNonZero<<4)(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); //row bits here updateColumnTransposeR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ); // ******* L updateColumnTransposeL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); #if ABC_SMALL<3 #ifdef ABC_ORDERED_FACTORIZATION // Permute out for Btran permuteOutForBtran(regionSparse); #endif #if ABC_DEBUG regionSparse.checkClean(); #endif numberNonZero = regionSparse.getNumElements ( ); #else numberNonZero=0; for (CoinSimplexInt i=0;i(0)); return numberNonZero; } #if ABC_SMALL<2 /* Updates part of column transpose (BTRANU) when densish, assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUDensish ( CoinIndexedVector * regionSparse, CoinSimplexInt smallestIndex) const { CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); const CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; const CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; numberNonZero = 0; const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=smallestIndex ; //pivotLinked[-1]; instrument_start("CoinAbcFactorizationUpdateTransposeUDensish",numberRows_); while (jRow>=0) { if (TEST_DOUBLE_NONZERO(region[jRow])) { CoinFactorizationDouble pivotValue = region[jRow]; if ( !TEST_LESS_THAN_UPDATE_TOLERANCE(pivotValue ) ) { CoinSimplexInt numberIn = numberInRow[jRow]; instrument_add(numberIn); if (TEST_INT_NONZERO(numberIn)) { CoinBigIndex start = startRow[jRow]; CoinBigIndex end = start + numberIn; #ifndef INLINE_IT for (CoinBigIndex j = start ; j < end; j ++ ) { CoinSimplexInt iRow = indexColumn[j]; CoinFactorizationDouble value = elementRowU[j]; assert (value); // isetNumElements ( numberNonZero ); instrument_end(); } /* Updates part of column transpose (BTRANU) when sparse, assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUSparse ( CoinIndexedVector * regionSparse #if ABC_PARALLEL ,int whichSparse #endif ) const { CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); const CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; const CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; // use sparse_ as temporary area // mark known to be zero //printf("PP 0_ %d %s\n",__LINE__,__FILE__); CoinAbcStack * COIN_RESTRICT stackList = reinterpret_cast(sparseAddress_); CoinSimplexInt * COIN_RESTRICT list = listAddress_; CoinCheckZero * COIN_RESTRICT mark = markRowAddress_; #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { //printf("alternative sparse\n"); int addAmount=whichSparse*sizeSparseArray_; stackList=reinterpret_cast(reinterpret_cast(stackList)+addAmount); list=reinterpret_cast(reinterpret_cast(list)+addAmount); mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); } #endif CoinSimplexInt nList; #if 0 //ndef NDEBUG for (CoinSimplexInt i=0;i=startThis;j--) { CoinSimplexInt kPivot3=indexColumn[j--]; if (!mark[kPivot3]) { kPivot=kPivot3; break; } } if (j>=startThis) { /* put back on stack */ stackList[nStack++].next =j; /* and new one */ CoinBigIndex start=startRow[kPivot]; j=start+numberInRow[kPivot]-1; stackList[nStack].stack=kPivot; stackList[nStack].start=start; mark[kPivot]=2; stackList[nStack++].next=j; #else CoinBigIndex j=stackList[nStack].next; if (j>=stackList[nStack].start) { CoinSimplexInt kPivot3=indexColumn[j--]; /* put back on stack */ stackList[nStack++].next =j; if (!mark[kPivot3]) { /* and new one */ CoinBigIndex start=startRow[kPivot3]; j=start+numberInRow[kPivot3]-1; stackList[nStack].stack=kPivot3; stackList[nStack].start=start; mark[kPivot3]=2; stackList[nStack++].next=j; } #endif } else { // finished list[nList++]=kPivot; mark[kPivot]=1; } } } } instrument_start("CoinAbcFactorizationUpdateTransposeUSparse",2*(numberNonZero+nList)); numberNonZero=0; for (CoinSimplexInt i=nList-1;i>=0;i--) { CoinSimplexInt iPivot = list[i]; assert (iPivot>=0&&iPivotsetNumElements ( numberNonZero ); instrument_end_and_adjust(1.3); } #endif // updateColumnTransposeU. Updates part of column transpose (BTRANU) //assumes index is sorted i.e. region is correct //does not sort by sign void CoinAbcTypeFactorization::updateColumnTransposeU ( CoinIndexedVector * regionSparse, CoinSimplexInt smallestIndex #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichCpu #endif ) const { #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT>1 printf("file %s line %d which %d\n",__FILE__,__LINE__,whichCpu); #endif abc_assert((cilk_conflict&(1<getNumElements ( ); if (factorizationStatistics()) { statistics.numberCounts_++; statistics.countInput_ += static_cast (number); } CoinSimplexInt goSparse; // Guess at number at end if (gotUCopy()) { if (gotSparse()) { assert (statistics.averageAfterU_); CoinSimplexInt newNumber = static_cast (number*statistics.averageAfterU_*twiddleBtranFactor1()); if (newNumber< sparseThreshold_) goSparse = 2; else goSparse = 0; } else { goSparse=0; } #if ABC_SMALL>=0 } else { goSparse=-1; #endif } //CoinIndexedVector temp(*regionSparse); switch (goSparse) { #if ABC_SMALL>=0 case -1: // no row copy updateColumnTransposeUByColumn(regionSparse,smallestIndex); break; #endif case 0: // densish updateColumnTransposeUDensish(regionSparse,smallestIndex); break; case 2: // sparse { updateColumnTransposeUSparse(regionSparse #if ABC_PARALLEL ,whichCpu #endif ); } break; } if (factorizationStatistics()) statistics.countAfterU_ += static_cast (regionSparse->getNumElements()); #else updateColumnTransposeUByColumn(regionSparse,smallestIndex); #endif #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict&(1<getIndices ( ); CoinSimplexInt numberNonZero=0; #endif //scan for (first=numberRows_-1;first>=0;first--) { #ifndef ABC_ORDERED_FACTORIZATION if (region[pivotLOrder[first]]) break; #else if (region[first]) break; #endif } instrument_start("CoinAbcFactorizationUpdateTransposeLDensish",first); if ( first >= 0 ) { base = baseL_; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnLAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowLAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementLAddress_; CoinSimplexInt last = baseL_ + numberL_; if ( first >= last ) { first = last - 1; } CoinBigIndex end = startColumn[first+1]; for (CoinSimplexInt k = first ; k >= base; k-- ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif CoinFactorizationDouble pivotValue = region[i]; #ifndef INLINE_IT2 CoinBigIndex j=end-1; end=startColumn[k]; instrument_add(j-end); for ( ; j >= end; j-- ) { CoinSimplexInt iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; pivotValue -= value * region[iRow]; } #else CoinBigIndex start=startColumn[k]; instrument_add(end-start); pivotValue+=CoinAbcGatherUpdate(end-start,element+start,indexRow+start,region); end=start; #endif #if ABC_SMALL<3 if ( !TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue ) ) { region[i] = pivotValue; regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } #else region[i] = pivotValue; #endif } #if ABC_SMALL<3 //may have stopped early if ( first < base ) { base = first + 1; } for (CoinSimplexInt k = base-1 ; k >= 0; k-- ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif CoinExponent expValue=ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } } } #endif } #if ABC_SMALL<3 //set counts regionSparse->setNumElements ( numberNonZero ); #endif instrument_end(); } #if ABC_SMALL<2 /* updateColumnTransposeLByRow. Updates part of column transpose (BTRANL) densish but by row */ void CoinAbcTypeFactorization::updateColumnTransposeLByRow ( CoinIndexedVector * regionSparse ) const { CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinSimplexInt numberNonZero; // use row copy of L const CoinFactorizationDouble * COIN_RESTRICT element = elementByRowLAddress_; const CoinBigIndex * COIN_RESTRICT startRow = startRowLAddress_; const CoinSimplexInt * COIN_RESTRICT column = indexColumnLAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; numberNonZero=0; instrument_start("CoinAbcFactorizationUpdateTransposeLByRow",numberRows_+numberSlacks_); // down to slacks for (CoinSimplexInt k = numberRows_-1 ; k >= numberSlacks_; k-- ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif if (TEST_DOUBLE_NONZERO(region[i])) { CoinFactorizationDouble pivotValue = region[i]; if ( !TEST_LESS_THAN_TOLERANCE(pivotValue ) ) { regionIndex[numberNonZero++] = i; CoinBigIndex start=startRow[i]; CoinBigIndex end=startRow[i+1]; instrument_add(end-start); if (TEST_INT_NONZERO(end-start)) { #ifndef INLINE_IT for (CoinBigIndex j = end-1;j >= start; j--) { CoinSimplexInt iRow = column[j]; CoinFactorizationDouble value = element[j]; region[iRow] -= pivotValue*value; } #else CoinAbcScatterUpdate(end-start,pivotValue,element+start,column+start,region); #endif } } else { region[i] = 0.0; } } } for (CoinSimplexInt k = numberSlacks_-1 ; k >= 0; k-- ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif CoinExponent expValue=ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++]=i; } else { region[i] = 0.0; } } } //set counts regionSparse->setNumElements ( numberNonZero ); instrument_end(); } /* updateColumnTransposeLSparse. Updates part of column transpose (BTRANL) sparse */ void CoinAbcTypeFactorization::updateColumnTransposeLSparse ( CoinIndexedVector * regionSparse #if ABC_PARALLEL ,int whichSparse #endif ) const { CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); // use row copy of L const CoinFactorizationDouble * COIN_RESTRICT element = elementByRowLAddress_; const CoinBigIndex * COIN_RESTRICT startRow = startRowLAddress_; const CoinSimplexInt * COIN_RESTRICT column = indexColumnLAddress_; // use sparse_ as temporary area // mark known to be zero //printf("PP 0_ %d %s\n",__LINE__,__FILE__); CoinAbcStack * COIN_RESTRICT stackList = reinterpret_cast(sparseAddress_); CoinSimplexInt * COIN_RESTRICT list = listAddress_; CoinCheckZero * COIN_RESTRICT mark = markRowAddress_; #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { int addAmount=whichSparse*sizeSparseArray_; //printf("alternative sparse\n"); stackList=reinterpret_cast(reinterpret_cast(stackList)+addAmount); list=reinterpret_cast(reinterpret_cast(list)+addAmount); mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); } #endif #ifndef NDEBUG for (CoinSimplexInt i=0;i=0) { /* take off stack */ if (j>=stackList[nStack].start) { CoinSimplexInt jPivot=column[j--]; /* put back on stack */ stackList[nStack].next =j; if (!mark[jPivot]) { /* and new one */ kPivot=jPivot; //iPivot=pivotLBackwardOrder[kPivot]; j = startRow[kPivot+1]-1; stackList[++nStack].stack=kPivot; mark[kPivot]=1; stackList[nStack].start=startRow[kPivot]; stackList[nStack].next=j; } } else { /* finished so mark */ list[nList++]=kPivot; mark[kPivot]=1; --nStack; if (nStack>=0) { kPivot=stackList[nStack].stack; j=stackList[nStack].next; } } } } } instrument_start("CoinAbcFactorizationUpdateTransposeLSparse",2*(numberNonZero+nList)); numberNonZero=0; for (CoinSimplexInt i=nList-1;i>=0;i--) { CoinSimplexInt iPivot = list[i]; //CoinSimplexInt kPivot=pivotLOrder[iPivot]; mark[iPivot]=0; CoinFactorizationDouble pivotValue = region[iPivot]; if ( !TEST_LESS_THAN_TOLERANCE(pivotValue ) ) { regionIndex[numberNonZero++] = iPivot; CoinBigIndex start=startRow[iPivot]; CoinBigIndex end=startRow[iPivot+1]; instrument_add(end-start); #ifndef INLINE_IT CoinBigIndex j; for ( j = start; j < end; j ++ ) { CoinSimplexInt iRow = column[j]; CoinFactorizationDouble value = element[j]; region[iRow] -= value * pivotValue; } #else CoinAbcScatterUpdate(end-start,pivotValue,element+start,column+start,region); #endif } else { region[iPivot]=0.0; } } //set counts regionSparse->setNumElements ( numberNonZero ); instrument_end_and_adjust(1.3); } #endif // updateColumnTransposeL. Updates part of column transpose (BTRANL) void CoinAbcTypeFactorization::updateColumnTransposeL ( CoinIndexedVector * regionSparse #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse #endif ) const { #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT>1 printf("file %s line %d which %d\n",__FILE__,__LINE__,whichSparse); #endif abc_assert((cilk_conflict&(1<getNumElements ( ); #endif if (!numberL_ #if ABC_SMALL<4 &&!numberDense_ #endif ) { #if ABC_SMALL<3 if (number>=numberRows_) { // need scan regionSparse->setNumElements(0); scan(regionSparse); } #endif #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict&(1< (number*statistics.averageAfterL_*twiddleBtranFactor1()); if (newNumber< sparseThreshold_) goSparse = 2; else if (2*newNumber< numberRows_) goSparse = 0; else goSparse = -1; } else { goSparse=-1; } #endif #if ABC_SMALL<4 #if ABC_DENSE_CODE>0 if (numberDense_) { //take off list CoinSimplexInt lastSparse = numberRows_-numberDense_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; CoinFactorizationDouble * COIN_RESTRICT denseArea = denseAreaAddress_; CoinFactorizationDouble * COIN_RESTRICT denseRegion = denseArea+leadingDimension_*numberDense_; CoinSimplexInt * COIN_RESTRICT densePermute= reinterpret_cast(denseRegion+FACTOR_CPU*numberDense_); #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) denseRegion+=whichSparse*numberDense_; #endif CoinFactorizationDouble * COIN_RESTRICT densePut = denseRegion-lastSparse; CoinZeroN(denseRegion,numberDense_); bool doDense=false; #if ABC_SMALL<3 CoinSimplexInt number = regionSparse->getNumElements(); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; CoinSimplexInt i=0; #if ABC_SMALL<0 assert (number<=numberRows_); #else if (number<=numberRows_) { #endif while (i=lastSparse) { doDense=true; regionIndex[i] = regionIndex[--number]; densePut[jRow]=region[iRow]; region[iRow]=0.0; } else { i++; } } #endif #if ABC_SMALL>=0 #if ABC_SMALL<3 } else { #endif for (CoinSimplexInt jRow=lastSparse;jRowsetNumElements(0); scan(regionSparse); number=regionSparse->getNumElements(); } #endif #endif if (doDense) { instrument_do("CoinAbcFactorizationDenseTranspose",0.25*numberDense_*numberDense_); #if ABC_DENSE_CODE==1 #ifndef CLAPACK char trans = 'T'; CoinSimplexInt ione=1; CoinSimplexInt info; F77_FUNC(dgetrs,DGETRS)(&trans,&numberDense_,&ione,denseArea,&leadingDimension_, densePermute,denseRegion,&numberDense_,&info,1); #else clapack_dgetrs(CblasColMajor, CblasTrans,numberDense_,1, denseArea, leadingDimension_,densePermute,denseRegion,numberDense_); #endif #elif ABC_DENSE_CODE==2 CoinAbcDgetrs('T',numberDense_,denseArea,denseRegion); short * COIN_RESTRICT forBtran = reinterpret_cast(densePermute+numberDense_)+numberDense_-lastSparse; pivotLOrder += lastSparse; // adjust #endif for (CoinSimplexInt i=lastSparse;isetNumElements(number); #endif } } //printRegion(*regionSparse,"After BtranL"); #endif #endif #if ABC_SMALL<2 switch (goSparse) { case -1: // No row copy updateColumnTransposeLDensish(regionSparse); break; case 0: // densish but by row updateColumnTransposeLByRow(regionSparse); break; case 2: // sparse updateColumnTransposeLSparse(regionSparse #if ABC_PARALLEL ,whichSparse #endif ); break; } #else updateColumnTransposeLDensish(regionSparse); #endif #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict&(1<=0 // Updates part of column transpose (BTRANR) when dense void CoinAbcTypeFactorization::updateColumnTransposeRDensish( CoinIndexedVector * regionSparse ) const { const CoinBigIndex * COIN_RESTRICT startColumn = startColumnRAddress_-numberRows_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); #if ABC_SMALL<3 #ifdef ABC_DEBUG regionSparse->checkClean(); #endif #endif instrument_start("CoinAbcFactorizationUpdateTransposeRDensish",numberRows_); CoinSimplexInt last = numberRowsExtra_-1; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt * COIN_RESTRICT pivotRowBack = pivotColumnAddress_; for (CoinSimplexInt i = last ; i >= numberRows_; i-- ) { CoinSimplexInt putRow=pivotRowBack[i]; CoinFactorizationDouble pivotValue = region[putRow]; if ( pivotValue ) { CoinBigIndex start=startColumn[i]; CoinBigIndex end=startColumn[i+1]; instrument_add(end-start); #ifndef INLINE_IT for (CoinBigIndex j = start; j < end; j++ ) { CoinFactorizationDouble value = element[j]; CoinSimplexInt iRow = indexRow[j]; assert (iRowgetIndices ( ); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); instrument_start("CoinAbcFactorizationUpdateTransposeRSparse",numberRows_); #if ABC_SMALL<3 #ifdef ABC_DEBUG regionSparse->checkClean(); #endif #endif CoinSimplexInt last = numberRowsExtra_-1; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementRAddress_; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnRAddress_-numberRows_; //move using lookup const CoinSimplexInt * COIN_RESTRICT pivotRowBack = pivotColumnAddress_; // still need to do in correct order (for now) for (CoinSimplexInt i = last ; i >= numberRows_; i-- ) { CoinSimplexInt putRow = pivotRowBack[i]; CoinFactorizationDouble pivotValue = region[putRow]; if ( pivotValue ) { instrument_add(startColumn[i+1]-startColumn[i]); for (CoinBigIndex j = startColumn[i]; j < startColumn[i+1]; j++ ) { CoinFactorizationDouble value = element[j]; CoinSimplexInt iRow = indexRow[j]; assert (iRowsetNumElements(numberNonZero); } #endif // updateColumnTransposeR. Updates part of column (FTRANR) void CoinAbcTypeFactorization::updateColumnTransposeR ( CoinIndexedVector * regionSparse #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif ) const { if (numberRowsExtra_==numberRows_) return; #if ABC_SMALL<3 CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); if (numberNonZero) { #endif #if ABC_SMALL<3 const CoinBigIndex * COIN_RESTRICT startColumn = startColumnRAddress_-numberRows_; #endif // Size of R instrument_do("CoinAbcFactorizationTransposeR",startColumnRAddress_[numberR_]); #if ABC_SMALL<2 if (startColumn[numberRowsExtra_]) { #if ABC_SMALL>=0 if (numberNonZero < ((sparseThreshold_<<2)*twiddleBtranFactor2()) ||(!numberL_&&gotLCopy()&&gotRCopy())) { #endif updateColumnTransposeRSparse ( regionSparse ); if (factorizationStatistics()) statistics.countAfterR_ += regionSparse->getNumElements(); #if ABC_SMALL>=0 } else { updateColumnTransposeRDensish ( regionSparse ); // we have lost indices // make sure won't try and go sparse again if (factorizationStatistics()) statistics.countAfterR_ += CoinMin((numberNonZero<<1),numberRows_); // temp +2 (was +1) regionSparse->setNumElements (numberRows_+2); } #endif } else { if (factorizationStatistics()) statistics.countAfterR_ += numberNonZero; } #else updateColumnTransposeRDensish ( regionSparse ); #if ABC_SMALL<3 // we have lost indices // make sure won't try and go sparse again // temp +2 (was +1) regionSparse->setNumElements (numberRows_+2); #endif #endif #if ABC_SMALL<3 } #endif } // Update partial Ftran by R update void CoinAbcTypeFactorization::updatePartialUpdate(CoinIndexedVector & partialUpdate) { CoinSimplexDouble * COIN_RESTRICT region = partialUpdate.denseVector ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = partialUpdate.getIndices ( ); CoinSimplexInt numberNonZero = partialUpdate.getNumElements ( ); const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt * pivotRowBack = pivotColumnAddress_; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnRAddress_-numberRows_; CoinBigIndex start = startColumn[numberRowsExtra_-1]; CoinBigIndex end = startColumn[numberRowsExtra_]; CoinSimplexInt iRow =pivotRowBack[numberRowsExtra_-1]; CoinFactorizationDouble pivotValue = region[iRow]; for (CoinBigIndex j = start; j < end; j ++ ) { CoinFactorizationDouble value = element[j]; CoinSimplexInt jRow = indexRow[j]; value *= region[jRow]; pivotValue -= value; } if ( !TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue ) ) { if (!region[iRow]) regionIndex[numberNonZero++] = iRow; region[iRow] = pivotValue; } else { if (region[iRow]) region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } partialUpdate.setNumElements(numberNonZero); } #if FACTORIZATION_STATISTICS #ifdef ABC_JUST_ONE_FACTORIZATION #define FACTORS_HERE #endif #ifdef FACTORS_HERE double ftranTwiddleFactor1X=1.0; double ftranTwiddleFactor2X=1.0; double ftranFTTwiddleFactor1X=1.0; double ftranFTTwiddleFactor2X=1.0; double btranTwiddleFactor1X=1.0; double btranTwiddleFactor2X=1.0; double ftranFullTwiddleFactor1X=1.0; double ftranFullTwiddleFactor2X=1.0; double btranFullTwiddleFactor1X=1.0; double btranFullTwiddleFactor2X=1.0; double denseThresholdX=31; double twoThresholdX=1000; double minRowsSparse=300; double largeRowsSparse=10000; double mediumRowsDivider=6; double mediumRowsMinCount=500; double largeRowsCount=1000; #else extern double ftranTwiddleFactor1X; extern double ftranTwiddleFactor2X; extern double ftranFTTwiddleFactor1X; extern double ftranFTTwiddleFactor2X; extern double btranTwiddleFactor1X; extern double btranTwiddleFactor2X; extern double ftranFullTwiddleFactor1X; extern double ftranFullTwiddleFactor2X; extern double btranFullTwiddleFactor1X; extern double btranFullTwiddleFactor2X; extern double denseThresholdX; extern double twoThresholdX; extern double minRowsSparse; extern double largeRowsSparse; extern double mediumRowsDivider; extern double mediumRowsMinCount; extern double largeRowsCount; #endif #else #define minRowsSparse 300 #define largeRowsSparse 10000 #define mediumRowsDivider 6 #define mediumRowsMinCount 500 #define largeRowsCount 1000 #endif // makes a row copy of L void CoinAbcTypeFactorization::goSparse2 ( ) { #if ABC_SMALL<2 #if ABC_SMALL>=0 if (numberRows_>minRowsSparse) { #endif if (numberRows_>3); } #if FACTORIZATION_STATISTICS ftranTwiddleFactor1_=ftranTwiddleFactor1X; ftranTwiddleFactor2_=ftranTwiddleFactor2X; ftranFTTwiddleFactor1_=ftranFTTwiddleFactor1X; ftranFTTwiddleFactor2_=ftranFTTwiddleFactor2X; btranTwiddleFactor1_=btranTwiddleFactor1X; btranTwiddleFactor2_=btranTwiddleFactor2X; ftranFullTwiddleFactor1_=ftranFullTwiddleFactor1X; ftranFullTwiddleFactor2_=ftranFullTwiddleFactor2X; btranFullTwiddleFactor1_=btranFullTwiddleFactor1X; btranFullTwiddleFactor2_=btranFullTwiddleFactor2X; #endif setYesGotLCopy(); setYesGotUCopy(); setYesGotSparse(); // allow for stack, list, next, starts and char map of mark CoinSimplexInt nRowIndex = (numberRows_+CoinSizeofAsInt(CoinSimplexInt)-1)/ CoinSizeofAsInt(char); CoinSimplexInt nInBig = static_cast(sizeof(CoinBigIndex)/sizeof(CoinSimplexInt)); assert (nInBig>=1); sizeSparseArray_ = (2+2*nInBig)*numberRows_ + nRowIndex ; sparse_.conditionalNew(FACTOR_CPU*sizeSparseArray_); sparseAddress_ = sparse_.array(); // zero out mark CoinAbcStack * stackList = reinterpret_cast(sparseAddress_); listAddress_ = reinterpret_cast(stackList+numberRows_); markRowAddress_ = reinterpret_cast (listAddress_ + numberRows_); assert(reinterpret_cast(sparseAddress_+(2+2*nInBig)*numberRows_)==markRowAddress_); CoinAbcMemset0(markRowAddress_,nRowIndex); #if ABC_PARALLEL //printf("PP 0__ %d %s\n",__LINE__,__FILE__); // convert to bytes sizeSparseArray_*=sizeof(CoinSimplexInt); char * mark=reinterpret_cast(reinterpret_cast(markRowAddress_)+sizeSparseArray_); for (int i=1;i(reinterpret_cast(mark)+sizeSparseArray_); } #endif elementByRowL_.conditionalDelete(); indexColumnL_.conditionalDelete(); startRowL_.conditionalNew(numberRows_+1); if (lengthAreaL_) { elementByRowL_.conditionalNew(lengthAreaL_); indexColumnL_.conditionalNew(lengthAreaL_); } elementByRowLAddress_=elementByRowL_.array(); indexColumnLAddress_=indexColumnL_.array(); startRowLAddress_=startRowL_.array(); // counts CoinBigIndex * COIN_RESTRICT startRowL = startRowLAddress_; CoinZeroN(startRowL,numberRows_); const CoinBigIndex * startColumnL = startColumnLAddress_; CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; const CoinSimplexInt * indexRowL = indexRowLAddress_; for (CoinSimplexInt i=baseL_;i=baseL_;i--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt iPivot=pivotLOrder[i]; #else CoinSimplexInt iPivot=i; #endif for (CoinBigIndex j=startColumnL[i];j=0 } else { sparseThreshold_=0; setNoGotLCopy(); //setYesGotUCopy(); setNoGotUCopy(); setNoGotSparse(); } #endif #endif } // set sparse threshold void CoinAbcTypeFactorization::sparseThreshold ( CoinSimplexInt /*value*/ ) { return; #if 0 if (value>0&&sparseThreshold_) { sparseThreshold_=value; } else if (!value&&sparseThreshold_) { // delete copy sparseThreshold_=0; elementByRowL_.conditionalDelete(); startRowL_.conditionalDelete(); indexColumnL_.conditionalDelete(); sparse_.conditionalDelete(); } else if (value>0&&!sparseThreshold_) { if (value>1) sparseThreshold_=value; else sparseThreshold_=0; goSparse(); } #endif } void CoinAbcTypeFactorization::maximumPivots ( CoinSimplexInt value ) { if (value>0) { if (numberRows_) maximumMaximumPivots_=CoinMax(maximumMaximumPivots_,value); else maximumMaximumPivots_=value; maximumPivots_=value; } //printf("max %d maxmax %d\n",maximumPivots_,maximumMaximumPivots_); } void CoinAbcTypeFactorization::messageLevel ( CoinSimplexInt value ) { if (value>0&&value<16) { messageLevel_=value; } } // Reset all sparsity etc statistics void CoinAbcTypeFactorization::resetStatistics() { #if ABC_SMALL<2 setStatistics(true); /// Below are all to collect ftranCountInput_=0.0; ftranCountAfterL_=0.0; ftranCountAfterR_=0.0; ftranCountAfterU_=0.0; ftranFTCountInput_=0.0; ftranFTCountAfterL_=0.0; ftranFTCountAfterR_=0.0; ftranFTCountAfterU_=0.0; btranCountInput_=0.0; btranCountAfterU_=0.0; btranCountAfterR_=0.0; btranCountAfterL_=0.0; ftranFullCountInput_=0.0; ftranFullCountAfterL_=0.0; ftranFullCountAfterR_=0.0; ftranFullCountAfterU_=0.0; btranFullCountInput_=0.0; btranFullCountAfterL_=0.0; btranFullCountAfterR_=0.0; btranFullCountAfterU_=0.0; /// We can roll over factorizations numberFtranCounts_=0; numberFtranFTCounts_=0; numberBtranCounts_=0; numberFtranFullCounts_=0; numberFtranFullCounts_=0; /// While these are averages collected over last ftranAverageAfterL_=INITIAL_AVERAGE; ftranAverageAfterR_=INITIAL_AVERAGE; ftranAverageAfterU_=INITIAL_AVERAGE; ftranFTAverageAfterL_=INITIAL_AVERAGE; ftranFTAverageAfterR_=INITIAL_AVERAGE; ftranFTAverageAfterU_=INITIAL_AVERAGE; btranAverageAfterU_=INITIAL_AVERAGE; btranAverageAfterR_=INITIAL_AVERAGE; btranAverageAfterL_=INITIAL_AVERAGE; ftranFullAverageAfterL_=INITIAL_AVERAGE; ftranFullAverageAfterR_=INITIAL_AVERAGE; ftranFullAverageAfterU_=INITIAL_AVERAGE; btranFullAverageAfterL_=INITIAL_AVERAGE; btranFullAverageAfterR_=INITIAL_AVERAGE; btranFullAverageAfterU_=INITIAL_AVERAGE; #endif } // See if worth going sparse void CoinAbcTypeFactorization::checkSparse() { #if ABC_SMALL<2 // See if worth going sparse and when if (numberFtranCounts_>50) { ftranCountInput_= CoinMax(ftranCountInput_,1.0); ftranAverageAfterL_ = CoinMax(ftranCountAfterL_/ftranCountInput_,INITIAL_AVERAGE2); ftranAverageAfterR_ = CoinMax(ftranCountAfterR_/ftranCountAfterL_,INITIAL_AVERAGE2); ftranAverageAfterU_ = CoinMax(ftranCountAfterU_/ftranCountAfterR_,INITIAL_AVERAGE2); ftranFTCountInput_= CoinMax(ftranFTCountInput_,INITIAL_AVERAGE2); ftranFTAverageAfterL_ = CoinMax(ftranFTCountAfterL_/ftranFTCountInput_,INITIAL_AVERAGE2); ftranFTAverageAfterR_ = CoinMax(ftranFTCountAfterR_/ftranFTCountAfterL_,INITIAL_AVERAGE2); ftranFTAverageAfterU_ = CoinMax(ftranFTCountAfterU_/ftranFTCountAfterR_,INITIAL_AVERAGE2); if (btranCountInput_&&btranCountAfterU_&&btranCountAfterR_) { btranAverageAfterU_ = CoinMax(btranCountAfterU_/btranCountInput_,INITIAL_AVERAGE2); btranAverageAfterR_ = CoinMax(btranCountAfterR_/btranCountAfterU_,INITIAL_AVERAGE2); btranAverageAfterL_ = CoinMax(btranCountAfterL_/btranCountAfterR_,INITIAL_AVERAGE2); } else { // we have not done any useful btrans (values pass?) btranAverageAfterU_ = INITIAL_AVERAGE2; btranAverageAfterR_ = INITIAL_AVERAGE2; btranAverageAfterL_ = INITIAL_AVERAGE2; } ftranFullCountInput_= CoinMax(ftranFullCountInput_,1.0); ftranFullAverageAfterL_ = CoinMax(ftranFullCountAfterL_/ftranFullCountInput_,INITIAL_AVERAGE2); ftranFullAverageAfterR_ = CoinMax(ftranFullCountAfterR_/ftranFullCountAfterL_,INITIAL_AVERAGE2); ftranFullAverageAfterU_ = CoinMax(ftranFullCountAfterU_/ftranFullCountAfterR_,INITIAL_AVERAGE2); btranFullCountInput_= CoinMax(btranFullCountInput_,1.0); btranFullAverageAfterL_ = CoinMax(btranFullCountAfterL_/btranFullCountInput_,INITIAL_AVERAGE2); btranFullAverageAfterR_ = CoinMax(btranFullCountAfterR_/btranFullCountAfterL_,INITIAL_AVERAGE2); btranFullAverageAfterU_ = CoinMax(btranFullCountAfterU_/btranFullCountAfterR_,INITIAL_AVERAGE2); } // scale back ftranCountInput_ *= AVERAGE_SCALE_BACK; ftranCountAfterL_ *= AVERAGE_SCALE_BACK; ftranCountAfterR_ *= AVERAGE_SCALE_BACK; ftranCountAfterU_ *= AVERAGE_SCALE_BACK; ftranFTCountInput_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterR_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterU_ *= AVERAGE_SCALE_BACK; btranCountInput_ *= AVERAGE_SCALE_BACK; btranCountAfterU_ *= AVERAGE_SCALE_BACK; btranCountAfterR_ *= AVERAGE_SCALE_BACK; btranCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFullCountInput_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterR_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterU_ *= AVERAGE_SCALE_BACK; btranFullCountInput_ *= AVERAGE_SCALE_BACK; btranFullCountAfterL_ *= AVERAGE_SCALE_BACK; btranFullCountAfterR_ *= AVERAGE_SCALE_BACK; btranFullCountAfterU_ *= AVERAGE_SCALE_BACK; #endif } // Condition number - product of pivots after factorization CoinSimplexDouble CoinAbcTypeFactorization::conditionNumber() const { CoinSimplexDouble condition = 1.0; const CoinFactorizationDouble * pivotRegion = pivotRegionAddress_; for (CoinSimplexInt i=0;i(reinterpret_cast(mark)+sizeSparseArray_); for (CoinSimplexInt i=0;i(reinterpret_cast(mark)+sizeSparseArray_); } #endif } #endif #endif Clp-1.15.10/src/CoinAbcBaseFactorization3.cpp0000644000076600007660000023761212101105055017260 0ustar coincoin/* $Id: CoinAbcBaseFactorization3.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #if CILK_CONFLICT>0 // for conflicts extern int cilk_conflict; #endif //:class CoinAbcTypeFactorization. Deals with Factorization and Updates /* Updates one column for dual steepest edge weights (FTRAN) */ void CoinAbcTypeFactorization::updateWeights ( CoinIndexedVector & regionSparse) const { toLongArray(®ionSparse,1); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparse); #endif // ******* L updateColumnL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL // can re-use 0 which would have been used for btran ,0 #endif ); //row bits here updateColumnR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); //update counts // ******* U updateColumnU ( ®ionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); #if ABC_DEBUG regionSparse.checkClean(); #endif } CoinSimplexInt CoinAbcTypeFactorization::updateColumn ( CoinIndexedVector & regionSparse) const { toLongArray(®ionSparse,0); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparse); #endif // ******* L updateColumnL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif ); //row bits here updateColumnR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif ); //update counts // ******* U updateColumnU ( ®ionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranCountInput_) #endif ); #if ABC_DEBUG regionSparse.checkClean(); #endif return regionSparse.getNumElements(); } /* Updates one full column (FTRAN) */ void CoinAbcTypeFactorization::updateFullColumn ( CoinIndexedVector & regionSparse) const { #ifndef ABC_ORDERED_FACTORIZATION regionSparse.setNumElements(0); regionSparse.scan(0,numberRows_); #else permuteInForFtran(regionSparse,true); #endif if (regionSparse.getNumElements()) { toLongArray(®ionSparse,1); // ******* L updateColumnL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFullCountInput_) #endif #if ABC_PARALLEL ,1 #endif ); //row bits here updateColumnR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFullCountInput_) #endif #if ABC_PARALLEL ,1 #endif ); //update counts // ******* U updateColumnU ( ®ionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranFullCountInput_) #endif #if ABC_PARALLEL ,1 #endif ); fromLongArray(1); #if ABC_DEBUG regionSparse.checkClean(); #endif } } // move stuff like this into CoinAbcHelperFunctions.hpp inline void multiplyIndexed(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT multiplier, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { for (CoinSimplexInt i = 0; i < number; i ++ ) { CoinSimplexInt iRow = thisIndex[i]; CoinSimplexDouble value = region[iRow]; value *= multiplier[iRow]; region[iRow] = value; } } /* Updates one full column (BTRAN) */ void CoinAbcTypeFactorization::updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const { int numberNonZero=0; // Should pass in statistics toLongArray(®ionSparse,0); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse.getIndices(); #ifndef ABC_ORDERED_FACTORIZATION const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; for (int iRow=0;iRow (numberNonZero*btranFullAverageAfterU_*twiddleBtranFullFactor1()); if (newNumber< sparseThreshold_) goSparse = true; } #endif if (numberNonZero<40&&(numberNonZero<<4)(btranFullCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); //row bits here updateColumnTransposeR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranFullCountInput_) #endif ); // ******* L updateColumnTransposeL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranFullCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); fromLongArray(0); #if ABC_SMALL<3 #ifdef ABC_ORDERED_FACTORIZATION permuteOutForBtran(regionSparse); #endif #if ABC_DEBUG regionSparse.checkClean(); #endif #else numberNonZero=0; for (CoinSimplexInt i=0;i0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT>1 printf("file %s line %d which %d\n",__FILE__,__LINE__,whichSparse); #endif abc_assert((cilk_conflict&(1<getNumElements ( ); if (factorizationStatistics()) { statistics.numberCounts_++; statistics.countInput_ += number; } #endif if (numberL_) { #if ABC_SMALL<2 int goSparse; // Guess at number at end if (gotSparse()) { double average = statistics.averageAfterL_*twiddleFactor1S(); assert (average); CoinSimplexInt newNumber = static_cast (number*average); if (newNumber< sparseThreshold_&&(numberL_<<2)>newNumber*1.0*twiddleFactor2S()) goSparse = 1; else if (3*newNumber < numberRows_) goSparse = 0; else goSparse = -1; } else { goSparse=0; } //if(goSparse==1) goSparse=0; if (!goSparse) { // densish updateColumnLDensish(regionSparse); } else if (goSparse<0) { // densish updateColumnLDense(regionSparse); } else { // sparse updateColumnLSparse(regionSparse #if ABC_PARALLEL ,whichSparse #endif ); } #else updateColumnLDensish(regionSparse); #endif } #if ABC_SMALL<4 #if ABC_DENSE_CODE>0 if (numberDense_) { instrument_do("CoinAbcFactorizationDense",0.3*numberDense_*numberDense_); //take off list CoinSimplexInt lastSparse = numberRows_-numberDense_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector (regionSparse); CoinFactorizationDouble * COIN_RESTRICT denseArea = denseAreaAddress_; CoinFactorizationDouble * COIN_RESTRICT denseRegion = denseArea+leadingDimension_*numberDense_; CoinSimplexInt * COIN_RESTRICT densePermute= reinterpret_cast(denseRegion+FACTOR_CPU*numberDense_); //for (int i=0;i=0&&densePermute[i](densePermute+numberDense_)-lastSparse; short * COIN_RESTRICT forFtran2 = reinterpret_cast(densePermute+numberDense_)+2*numberDense_; #else const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; #endif CoinSimplexInt number = regionSparse->getNumElements(); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt i=0; while (i=lastSparse) { doDense=true; regionIndex[i] = regionIndex[--number]; densePut[jRow]=region[iRow]; #endif region[iRow]=0.0; } else { i++; } } #else CoinSimplexInt * COIN_RESTRICT forFtran = densePermute+numberDense_-lastSparse; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; for (CoinSimplexInt jRow=lastSparse;jRowsetNumElements(number); #endif } } //printRegion(*regionSparse,"After FtranL"); #endif #endif #if ABC_SMALL<2 if (factorizationStatistics()) statistics.countAfterL_ += regionSparse->getNumElements(); #endif #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict&(1<=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL==1 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL==2 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(static_cast(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { CoinFactorizationDouble pivotValue=0.0; for (CoinBigIndex j = 0; j < number; j ++ ) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; } // Updates part of column (FTRANL) when densish void CoinAbcTypeFactorization::updateColumnLDensish ( CoinIndexedVector * regionSparse) const { CoinSimplexInt * COIN_RESTRICT regionIndex=regionSparse->getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt number = regionSparse->getNumElements ( ); #if ABC_SMALL<3 CoinSimplexInt numberNonZero = 0; #endif const CoinBigIndex * COIN_RESTRICT startColumn = startColumnLAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowLAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementLAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; CoinSimplexInt last = numberRows_; assert ( last == baseL_ + numberL_); #if ABC_DENSE_CODE>0 //can take out last bit of sparse L as empty last -= numberDense_; #endif CoinSimplexInt smallestIndex = numberRowsExtra_; // do easy ones for (CoinSimplexInt k=0;k=baseL_) smallestIndex = CoinMin(jPivot,smallestIndex); else regionIndex[numberNonZero++]=iPivot; #else if (jPivot>=baseL_) smallestIndex = CoinMin(jPivot,smallestIndex); #endif } instrument_start("CoinAbcFactorizationUpdateLDensish",number+(last-smallestIndex)); // now others for (CoinSimplexInt k = smallestIndex; k < last; k++ ) { #if 0 for (int j=0;jsetNumElements ( numberNonZero ); #endif instrument_end(); } // Updates part of column (FTRANL) when dense void CoinAbcTypeFactorization::updateColumnLDense ( CoinIndexedVector * regionSparse) const { CoinSimplexInt * COIN_RESTRICT regionIndex=regionSparse->getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt number = regionSparse->getNumElements ( ); #if ABC_SMALL<3 CoinSimplexInt numberNonZero = 0; #endif const CoinBigIndex * COIN_RESTRICT startColumn = startColumnLAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowLAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementLAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; CoinSimplexInt last = numberRows_; assert ( last == baseL_ + numberL_); #if ABC_DENSE_CODE>0 //can take out last bit of sparse L as empty last -= numberDense_; #endif CoinSimplexInt smallestIndex = numberRowsExtra_; // do easy ones for (CoinSimplexInt k=0;k=baseL_) smallestIndex = CoinMin(jPivot,smallestIndex); else regionIndex[numberNonZero++]=iPivot; #else if (jPivot>=baseL_) smallestIndex = CoinMin(jPivot,smallestIndex); #endif } instrument_start("CoinAbcFactorizationUpdateLDensish",number+(last-smallestIndex)); // now others for (CoinSimplexInt k = smallestIndex; k < last; k++ ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif CoinExponent expValue=ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { CoinBigIndex start = startColumn[k]; CoinBigIndex end = startColumn[k + 1]; instrument_add(end-start); if (TEST_INT_NONZERO(end-start)) { CoinFactorizationDouble pivotValue = region[i]; #ifndef INLINE_IT for (CoinBigIndex j = start; j < end; j ++ ) { CoinSimplexInt iRow = indexRow[j]; CoinFactorizationDouble result = region[iRow]; CoinFactorizationDouble value = element[j]; region[iRow] = result - value * pivotValue; } #else CoinAbcScatterUpdate(end-start,pivotValue,element+start,indexRow+start,region); #endif } #if ABC_SMALL<3 regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; #endif } } } // and dense #if ABC_SMALL<3 for (CoinSimplexInt k = last; k < numberRows_; k++ ) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i=pivotLOrder[k]; #else CoinSimplexInt i=k; #endif CoinExponent expValue=ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } } } regionSparse->setNumElements ( numberNonZero ); #endif instrument_end(); } #if ABC_SMALL<2 // Updates part of column (FTRANL) when sparse void CoinAbcTypeFactorization::updateColumnLSparse ( CoinIndexedVector * regionSparse #if ABC_PARALLEL ,int whichSparse #endif ) const { CoinSimplexInt * COIN_RESTRICT regionIndex=regionSparse->getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt number = regionSparse->getNumElements ( ); CoinSimplexInt numberNonZero; numberNonZero = 0; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnLAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowLAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementLAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; CoinSimplexInt nList; // use sparse_ as temporary area // need to redo if this fails (just means using CoinAbcStack to compute sizes) assert (sizeof(CoinSimplexInt)==sizeof(CoinBigIndex)); CoinAbcStack * COIN_RESTRICT stackList = reinterpret_cast(sparseAddress_); CoinSimplexInt * COIN_RESTRICT list = listAddress_; #define DO_CHAR1 1 #if DO_CHAR1 // CHAR CoinCheckZero * COIN_RESTRICT mark = markRowAddress_; #else //BIT CoinSimplexUnsignedInt * COIN_RESTRICT mark = reinterpret_cast (markRowAddress_); #endif #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { //printf("alternative sparse\n"); int addAmount=whichSparse*sizeSparseArray_; stackList=reinterpret_cast(reinterpret_cast(stackList)+addAmount); list=reinterpret_cast(reinterpret_cast(list)+addAmount); #if DO_CHAR1 // CHAR mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); #else mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); #endif } #endif // mark known to be zero #ifdef COIN_DEBUG #if DO_CHAR1 // CHAR for (CoinSimplexInt i=0;i>COINFACTORIZATION_SHIFT_PER_INT;i++) { assert (!mark[i]); } #endif #endif nList=0; for (CoinSimplexInt k=0;k=baseL_) { #if DO_CHAR1 // CHAR CoinCheckZero mark_k = mark[kPivot]; #else CoinSimplexUnsignedInt wordK = kPivot >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexUnsignedInt bitK = (kPivot & COINFACTORIZATION_MASK_PER_INT); CoinSimplexUnsignedInt mark_k=(mark[wordK]>>bitK)&1; #endif if(!mark_k) { CoinBigIndex j=startColumn[iPivot+1]-1; stackList[0].stack=kPivot; CoinBigIndex start=startColumn[iPivot]; stackList[0].next=j; stackList[0].start=start; CoinSimplexInt nStack=0; while (nStack>=0) { /* take off stack */ #ifndef ABC_ORDERED_FACTORIZATION iPivot=pivotLBackwardOrder[kPivot]; // put startColumn on stackstuff #else iPivot=kPivot; #endif #if 1 //0 // what went wrong?? CoinBigIndex startThis=startColumn[iPivot]; for (;j>=startThis;j--) { CoinSimplexInt jPivot=indexRow[j]; #if DO_CHAR1 // CHAR CoinCheckZero mark_j = mark[jPivot]; #else CoinSimplexUnsignedInt word0 = jPivot >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexUnsignedInt bit0 = (jPivot & COINFACTORIZATION_MASK_PER_INT); CoinSimplexUnsignedInt mark_j=(mark[word0]>>bit0)&1; #endif if (!mark_j) { #if DO_CHAR1 // CHAR mark[jPivot]=1; #else mark[word0]|=(1<=startThis) { /* put back on stack */ stackList[nStack].next =j-1; #ifndef ABC_ORDERED_FACTORIZATION iPivot=pivotLBackwardOrder[kPivot]; #else iPivot=kPivot; #endif j = startColumn[iPivot+1]-1; nStack++; stackList[nStack].stack=kPivot; assert (kPivot=startColumn[iPivot]/*stackList[nStack].start*/) { CoinSimplexInt jPivot=indexRow[j--]; /* put back on stack */ stackList[nStack].next =j; #if DO_CHAR1 // CHAR CoinCheckZero mark_j = mark[jPivot]; #else CoinSimplexUnsignedInt word0 = jPivot >> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexUnsignedInt bit0 = (jPivot & COINFACTORIZATION_MASK_PER_INT); CoinSimplexUnsignedInt mark_j=(mark[word0]>>bit0)&1; #endif if (!mark_j) { /* and new one */ kPivot=jPivot; #ifndef ABC_ORDERED_FACTORIZATION iPivot=pivotLBackwardOrder[kPivot]; #else iPivot=kPivot; #endif j = startColumn[iPivot+1]-1; nStack++; stackList[nStack].stack=kPivot; assert (kPivot> COINFACTORIZATION_SHIFT_PER_INT; CoinSimplexUnsignedInt bitB = (kPivot & COINFACTORIZATION_MASK_PER_INT); mark[wordB]|=(1<=0) { kPivot=stackList[nStack].stack; #ifndef ABC_ORDERED_FACTORIZATION iPivot=pivotLBackwardOrder[kPivot]; #else iPivot=kPivot; #endif assert (kPivot=0;i--) { CoinSimplexInt iPivot = list[i]; test[iPivot]=1; CoinSimplexInt kPivot=pivotLBackwardOrder[iPivot]; CoinBigIndex start=startColumn[kPivot]; CoinBigIndex end=startColumn[kPivot+1]; for (CoinBigIndex j = start;j < end; j ++ ) { CoinSimplexInt iRow = indexRow[j]; assert (test[iRow]<=0); } } delete [] test; #endif for (CoinSimplexInt i=nList-1;i>=0;i--) { CoinSimplexInt iPivot = list[i]; #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt kPivot=pivotLBackwardOrder[iPivot]; #else CoinSimplexInt kPivot=iPivot; #endif #if DO_CHAR1 // CHAR mark[iPivot]=0; #else CoinSimplexUnsignedInt word0 = iPivot >> COINFACTORIZATION_SHIFT_PER_INT; //CoinSimplexUnsignedInt bit0 = (iPivot & COINFACTORIZATION_MASK_PER_INT); //mark[word0]&=(~(1<setNumElements ( numberNonZero ); instrument_end_and_adjust(1.3); } #endif #if FACTORIZATION_STATISTICS extern double twoThresholdX; #endif CoinSimplexInt CoinAbcTypeFactorization::updateTwoColumnsFT ( CoinIndexedVector & regionFTX, CoinIndexedVector & regionOtherX) { CoinIndexedVector * regionFT = ®ionFTX; CoinIndexedVector * regionOther = ®ionOtherX; #if ABC_DEBUG regionFT->checkClean(); regionOther->checkClean(); #endif toLongArray(regionFT,0); toLongArray(regionOther,1); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionFTX); permuteInForFtran(regionOtherX); #endif CoinSimplexInt numberNonZero=regionOther->getNumElements(); CoinSimplexInt numberNonZeroFT=regionFT->getNumElements(); // ******* L updateColumnL ( regionFT #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif ); updateColumnL ( regionOther #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif ); //row bits here updateColumnR ( regionFT #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif ); updateColumnR ( regionOther #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif ); bool doFT=storeFT(regionFT); //update counts // ******* U - see if densish #if ABC_SMALL<2 // Guess at number at end CoinSimplexInt goSparse=0; if (gotSparse()) { CoinSimplexInt numberNonZero = (regionOther->getNumElements ( )+ regionFT->getNumElements())>>1; double average = 0.25*(ftranAverageAfterL_*twiddleFtranFactor1() + ftranFTAverageAfterL_*twiddleFtranFTFactor1()); assert (average); CoinSimplexInt newNumber = static_cast (numberNonZero*average); if (newNumber< sparseThreshold_) goSparse = 2; } #if FACTORIZATION_STATISTICS int twoThreshold=twoThresholdX; #else #define twoThreshold 1000 #endif #else #define goSparse false #define twoThreshold 1000 #endif if (!goSparse&&numberRows_getIndices(); CoinFactorizationDouble * COIN_RESTRICT arrayUpdate = denseVector (regionOther); CoinSimplexInt * COIN_RESTRICT indexUpdate = regionOther->getIndices(); updateTwoColumnsUDensish(numberNonZeroFT,arrayFT,indexFT, numberNonZero,arrayUpdate,indexUpdate); regionFT->setNumElements ( numberNonZeroFT ); regionOther->setNumElements ( numberNonZero ); } else { // sparse updateColumnU ( regionFT #if ABC_SMALL<2 , reinterpret_cast(ftranFTCountInput_) #endif ); numberNonZeroFT=regionFT->getNumElements(); updateColumnU ( regionOther #if ABC_SMALL<2 , reinterpret_cast(ftranCountInput_) #endif ); numberNonZero=regionOther->getNumElements(); } fromLongArray(0); fromLongArray(1); #if ABC_DEBUG regionFT->checkClean(); regionOther->checkClean(); #endif if ( doFT ) return numberNonZeroFT; else return -numberNonZeroFT; } // Updates part of 2 columns (FTRANU) real work void CoinAbcTypeFactorization::updateTwoColumnsUDensish ( CoinSimplexInt & numberNonZero1, CoinFactorizationDouble * COIN_RESTRICT region1, CoinSimplexInt * COIN_RESTRICT index1, CoinSimplexInt & numberNonZero2, CoinFactorizationDouble * COIN_RESTRICT region2, CoinSimplexInt * COIN_RESTRICT index2) const { #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatterPointer = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; #else const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; #endif CoinSimplexInt numberNonZeroA = 0; CoinSimplexInt numberNonZeroB = 0; const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedBackwardsAddress_; CoinSimplexInt jRow=pivotLinked[numberRows_]; instrument_start("CoinAbcFactorizationUpdateTwoUDense",2*numberRows_); #if 1 //def DONT_USE_SLACKS while (jRow!=-1/*lastSlack_*/) { #else // would need extra code while (jRow!=lastSlack_) { #endif bool nonZero2 = (TEST_DOUBLE_NONZERO(region2[jRow])); bool nonZero1 = (TEST_DOUBLE_NONZERO(region1[jRow])); #ifndef ABC_USE_FUNCTION_POINTERS int numberIn=numberInColumn[jRow]; #else scatterStruct & COIN_RESTRICT scatter = scatterPointer[jRow]; CoinSimplexInt numberIn = scatter.number; #endif if (nonZero1||nonZero2) { #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex start = startColumn[jRow]; const CoinFactorizationDouble * COIN_RESTRICT thisElement = element+start; const CoinSimplexInt * COIN_RESTRICT thisIndex = indexRow+start; #else const CoinFactorizationDouble * COIN_RESTRICT thisElement = elementUColumnPlus+scatter.offset; const CoinSimplexInt * COIN_RESTRICT thisIndex = reinterpret_cast(thisElement+numberIn); #endif CoinFactorizationDouble pivotValue2 = region2[jRow]; CoinFactorizationDouble pivotMult = pivotRegion[jRow]; assert (pivotMult); CoinFactorizationDouble pivotValue2a = pivotValue2 * pivotMult; bool do2 = !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue2 ); region2[jRow] = 0.0; CoinFactorizationDouble pivotValue1 = region1[jRow]; region1[jRow] = 0.0; CoinFactorizationDouble pivotValue1a = pivotValue1 * pivotMult; bool do1 = !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue1 ); if (do2) { if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue2a ) ) { region2[jRow]=pivotValue2a; index2[numberNonZeroB++]=jRow; } } if (do1) { if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue1a ) ) { region1[jRow]=pivotValue1a; index1[numberNonZeroA++]=jRow; } } instrument_add(numberIn); if (numberIn) { if (do2) { if (!do1) { // just region 2 for (CoinBigIndex j=numberIn-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble value = thisElement[j]; assert (value); #ifdef NO_LOAD region2[iRow] -= value * pivotValue2; #else CoinFactorizationDouble regionValue2 = region2[iRow]; region2[iRow] = regionValue2 - value * pivotValue2; #endif } } else { // both instrument_add(numberIn); for (CoinBigIndex j=numberIn-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble value = thisElement[j]; #ifdef NO_LOAD region1[iRow] -= value * pivotValue1; region2[iRow] -= value * pivotValue2; #else CoinFactorizationDouble regionValue1 = region1[iRow]; CoinFactorizationDouble regionValue2 = region2[iRow]; region1[iRow] = regionValue1 - value * pivotValue1; region2[iRow] = regionValue2 - value * pivotValue2; #endif } } } else if (do1 ) { // just region 1 for (CoinBigIndex j=numberIn-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble value = thisElement[j]; assert (value); #ifdef NO_LOAD region1[iRow] -= value * pivotValue1; #else CoinFactorizationDouble regionValue1 = region1[iRow]; region1[iRow] = regionValue1 - value * pivotValue1; #endif } } } else { // no elements in column } } jRow=pivotLinked[jRow]; } numberNonZero1=numberNonZeroA; numberNonZero2=numberNonZeroB; #if ABC_SMALL<2 if (factorizationStatistics()) { ftranFTCountAfterU_ += numberNonZeroA; ftranCountAfterU_ += numberNonZeroB; } #endif instrument_end(); } // updateColumnU. Updates part of column (FTRANU) void CoinAbcTypeFactorization::updateColumnU ( CoinIndexedVector * regionSparse #if ABC_SMALL<2 ,CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse #endif ) const { #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT>1 printf("file %s line %d which %d\n",__FILE__,__LINE__,whichSparse); #endif abc_assert((cilk_conflict&(1<getNumElements ( ); int goSparse; // Guess at number at end if (gotSparse()) { double average = statistics.averageAfterU_*twiddleFactor1S(); assert (average); CoinSimplexInt newNumber = static_cast (numberNonZero*average); if (newNumber< sparseThreshold_) goSparse = 1; else if (numberNonZero*3getNumElements ( ); } #endif #if CILK_CONFLICT>0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict&(1<getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = 0; const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatterPointer = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; #else const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; const CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; #endif const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedBackwardsAddress_; CoinSimplexInt jRow=pivotLinked[numberRows_]; #define ETAS_1 2 #define TEST_BEFORE #ifdef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif #ifdef DONT_USE_SLACKS while (jRow!=-1/*lastSlack_*/) { #else while (jRow!=lastSlack_) { #endif #ifndef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_UPDATE_TOLERANCE(expValue)) { CoinFactorizationDouble pivotValue = region[jRow]; #if ETAS_1>1 CoinFactorizationDouble pivotValue2 = pivotValue*pivotRegion[jRow]; #endif #ifndef ABC_USE_FUNCTION_POINTERS int number=numberInColumn[jRow]; #else scatterStruct & COIN_RESTRICT scatter = scatterPointer[jRow]; CoinSimplexInt number = scatter.number; #endif instrument_add(number); if (TEST_INT_NONZERO(number)) { #ifdef COUNT_U { int k=numberInColumn[jRow]; if (k>10) k=11; nUDense[k]++; int kk=0; for (int k=0;k<12;k++) kk+=nUDense[k]; if (kk%1000000==0) { printf("ZZ"); for (int k=0;k<12;k++) printf(" %d",nUDense[k]); printf("\n"); } } #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex start = startColumn[jRow]; #ifndef INLINE_IT const CoinFactorizationDouble * COIN_RESTRICT thisElement = element+start; const CoinSimplexInt * COIN_RESTRICT thisIndex = indexRow+start; for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #else CoinAbcScatterUpdate(number,pivotValue,element+start,indexRow+start,region); #endif #else CoinBigIndex start = scatter.offset; #if ABC_USE_FUNCTION_POINTERS (*(scatter.functionPointer))(number,pivotValue,elementUColumnPlus+start,region); #else CoinAbcScatterUpdate(number,pivotValue,elementUColumnPlus+start,region); #endif #endif } CoinSimplexInt kRow=jRow; jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif #if ETAS_1<2 pivotValue *= pivotRegion[kRow]; if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { region[kRow]=pivotValue; regionIndex[numberNonZero++]=kRow; } else { region[kRow]=0.0; } #else if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue2 ) ) { region[kRow]=pivotValue2; regionIndex[numberNonZero++]=kRow; } else { region[kRow]=0.0; } #endif } else { CoinSimplexInt kRow=jRow; jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif region[kRow]=0.0; } } else { jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif } } #ifndef DONT_USE_SLACKS while (jRow!=-1) { #ifndef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { #if SLACK_VALUE==-1 CoinFactorizationDouble pivotValue = region[jRow]; assert (pivotRegion[jRow]==SLACK_VALUE); region[jRow]=-pivotValue; #endif regionIndex[numberNonZero++]=jRow; } else { region[jRow] = 0.0; } } jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif } #endif regionSparse->setNumElements ( numberNonZero ); instrument_end(); } // updateColumnU. Updates part of column (FTRANU) // Updates part of column (FTRANU) real work void CoinAbcTypeFactorization::updateColumnUDense ( CoinIndexedVector * regionSparse ) const { instrument_start("CoinAbcFactorizationUpdateUDensish",2*numberRows_); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinSimplexInt numberNonZero = 0; const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatterPointer = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; #else const CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; const CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; #endif const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedBackwardsAddress_; CoinSimplexInt jRow=pivotLinked[numberRows_]; #define ETAS_1 2 #define TEST_BEFORE #ifdef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif //int ixxxxxx=0; #ifdef DONT_USE_SLACKS while (jRow!=-1/*lastSlack_*/) { #else while (jRow!=lastSlack_) { #endif #if 0 double largest=1.0; int iLargest=-1; ixxxxxx++; for (int i=0;ilargest) { largest=fabs(region[i]); iLargest=i; } } if (iLargest>=0) printf("largest %g on row %d after %d\n",largest,iLargest,ixxxxxx); #endif #ifndef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_UPDATE_TOLERANCE(expValue)) { CoinFactorizationDouble pivotValue = region[jRow]; #if ETAS_1>1 CoinFactorizationDouble pivotValue2 = pivotValue*pivotRegion[jRow]; #endif #ifndef ABC_USE_FUNCTION_POINTERS int number=numberInColumn[jRow]; #else scatterStruct & COIN_RESTRICT scatter = scatterPointer[jRow]; CoinSimplexInt number = scatter.number; #endif instrument_add(number); if (TEST_INT_NONZERO(number)) { #ifdef COUNT_U { int k=numberInColumn[jRow]; if (k>10) k=11; nUDense[k]++; int kk=0; for (int k=0;k<12;k++) kk+=nUDense[k]; if (kk%1000000==0) { printf("ZZ"); for (int k=0;k<12;k++) printf(" %d",nUDense[k]); printf("\n"); } } #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex start = startColumn[jRow]; #ifndef INLINE_IT const CoinFactorizationDouble * COIN_RESTRICT thisElement = element+start; const CoinSimplexInt * COIN_RESTRICT thisIndex = indexRow+start; for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #else CoinAbcScatterUpdate(number,pivotValue,element+start,indexRow+start,region); #endif #else CoinBigIndex start = scatter.offset; #if ABC_USE_FUNCTION_POINTERS (*(scatter.functionPointer))(number,pivotValue,elementUColumnPlus+start,region); #else CoinAbcScatterUpdate(number,pivotValue,elementUColumnPlus+start,region); #endif #endif } CoinSimplexInt kRow=jRow; jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif #if ETAS_1<2 pivotValue *= pivotRegion[kRow]; if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { region[kRow]=pivotValue; regionIndex[numberNonZero++]=kRow; } else { region[kRow]=0.0; } #else if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue2 ) ) { region[kRow]=pivotValue2; regionIndex[numberNonZero++]=kRow; } else { region[kRow]=0.0; } #endif } else { CoinSimplexInt kRow=jRow; jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif region[kRow]=0.0; } } else { jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif } } #ifndef DONT_USE_SLACKS while (jRow!=-1) { #ifndef TEST_BEFORE CoinExponent expValue=ABC_EXPONENT(region[jRow]); #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { #if SLACK_VALUE==-1 CoinFactorizationDouble pivotValue = region[jRow]; assert (pivotRegion[jRow]==SLACK_VALUE); region[jRow]=-pivotValue; #endif regionIndex[numberNonZero++]=jRow; } else { region[jRow] = 0.0; } } jRow=pivotLinked[jRow]; #ifdef TEST_BEFORE expValue=ABC_EXPONENT(region[jRow]); #endif } #endif regionSparse->setNumElements ( numberNonZero ); instrument_end(); } #if ABC_SMALL<2 // updateColumnU. Updates part of column (FTRANU) /* Since everything is in order I should be able to do a better job of marking stuff - think. Also as L is static maybe I can do something better there (I know I could if I marked the depth of every element but that would lead to other inefficiencies. */ void CoinAbcTypeFactorization::updateColumnUSparse ( CoinIndexedVector * regionSparse #if ABC_PARALLEL ,int whichSparse #endif ) const { CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); //const CoinBigIndex * COIN_RESTRICT startColumn = startColumnUAddress_; //const CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; //const CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; // use sparse_ as temporary area // mark known to be zero #define COINFACTORIZATION_SHIFT_PER_INT2 (COINFACTORIZATION_SHIFT_PER_INT-1) #define COINFACTORIZATION_MASK_PER_INT2 (COINFACTORIZATION_MASK_PER_INT>>1) // need to redo if this fails (just means using CoinAbcStack to compute sizes) assert (sizeof(CoinSimplexInt)==sizeof(CoinBigIndex)); CoinAbcStack * COIN_RESTRICT stackList = reinterpret_cast(sparseAddress_); CoinSimplexInt * COIN_RESTRICT list = listAddress_; #ifndef ABC_USE_FUNCTION_POINTERS const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; #else scatterStruct * COIN_RESTRICT scatterPointer = scatterUColumn(); const CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; const CoinSimplexInt * COIN_RESTRICT indexRow = reinterpret_cast(elementUColumnPlusAddress_); #endif //#define DO_CHAR2 1 #if DO_CHAR2 // CHAR CoinCheckZero * COIN_RESTRICT mark = markRowAddress_; #else //BIT CoinSimplexUnsignedInt * COIN_RESTRICT mark = reinterpret_cast (markRowAddress_); #endif #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { int addAmount=whichSparse*sizeSparseArray_; stackList=reinterpret_cast(reinterpret_cast(stackList)+addAmount); list=reinterpret_cast(reinterpret_cast(list)+addAmount); #if DO_CHAR2 // CHAR mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); #else mark=reinterpret_cast(reinterpret_cast(mark)+addAmount); #endif } #endif #ifdef COIN_DEBUG #if DO_CHAR2 // CHAR for (CoinSimplexInt i=0;i>COINFACTORIZATION_SHIFT_PER_INT;i++) { assert (!mark[i]); } #endif #endif CoinSimplexInt nList = 0; // move slacks to end of stack list int * COIN_RESTRICT putLast = list+numberRows_; int * COIN_RESTRICT put = putLast; for (CoinSimplexInt i=0;i> COINFACTORIZATION_SHIFT_PER_INT2; CoinSimplexUnsignedInt bitB = (kPivot & COINFACTORIZATION_MASK_PER_INT2)<<1; CoinSimplexUnsignedInt mark_B=(mark[wordB]>>bitB)&3; #endif if (!mark_B) { #if DO_CHAR2 // CHAR mark[kPivot]=1; #else mark[wordB]|=(1<=0) { /* take off stack */ CoinBigIndex j=stackList[nStack].next-1; CoinBigIndex start=stackList[nStack].start; #if DO_CHAR2==0 // CHAR CoinSimplexUnsignedInt word0; CoinSimplexUnsignedInt bit0; #endif CoinSimplexInt jPivot; for (;j>=start;j--) { jPivot=indexRow[j]; #if DO_CHAR2 // CHAR CoinCheckZero mark_j = mark[jPivot]; #else word0 = jPivot >> COINFACTORIZATION_SHIFT_PER_INT2; bit0 = (jPivot & COINFACTORIZATION_MASK_PER_INT2)<<1; CoinSimplexUnsignedInt mark_j=(mark[word0]>>bit0)&3; #endif if (!mark_j) break; } if (j>=start) { /* put back on stack */ stackList[nStack].next =j; /* and new one */ #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex start=startColumn[jPivot]; CoinSimplexInt number=numberInColumn[jPivot]; #else scatterStruct & COIN_RESTRICT scatter = scatterPointer[jPivot]; CoinSimplexInt number = scatter.number; CoinBigIndex start = (scatter.offset+number)<<1; #endif if (number) { nStack++; stackList[nStack].stack=jPivot; stackList[nStack].next=start+number; stackList[nStack].start=start; #if DO_CHAR2 // CHAR mark[jPivot]=1; #else mark[word0]|=(1<>bit0)&3; #endif assert (mark_j!=3); #endif #if ABC_SMALL<2 if (!start) { // slack - put at end --put; *put=jPivot; assert(pivotRegion[jPivot]==1.0); } else { list[nList++]=jPivot; } #else list[nList++]=jPivot; #endif #if DO_CHAR2 // CHAR mark[jPivot]=3; #else mark[word0]|=(3<> COINFACTORIZATION_SHIFT_PER_INT2; CoinSimplexUnsignedInt bitB = (kPivot & COINFACTORIZATION_MASK_PER_INT2)<<1; CoinSimplexUnsignedInt mark_B=(mark[wordB]>>bitB)&3; #endif assert (mark_B!=3); //if (mark_B!=3) { list[nList++]=kPivot; #if DO_CHAR2 // CHAR mark[kPivot]=3; #else mark[wordB]|=(3<=0;i--) { CoinSimplexInt iPivot = list[i]; CoinExponent expValue=ABC_EXPONENT(region[iPivot]); #if DO_CHAR2 // CHAR mark[iPivot]=0; #else CoinSimplexInt word0 = iPivot >> COINFACTORIZATION_SHIFT_PER_INT2; mark[word0]=0; #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_UPDATE_TOLERANCE(expValue)) { CoinFactorizationDouble pivotValue = region[iPivot]; #if ETAS_1>1 CoinFactorizationDouble pivotValue2 = pivotValue*pivotRegion[iPivot]; #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt number = numberInColumn[iPivot]; #else scatterStruct & COIN_RESTRICT scatter = scatterPointer[iPivot]; CoinSimplexInt number = scatter.number; #endif if (TEST_INT_NONZERO(number)) { #ifdef COUNT_U { int k=numberInColumn[iPivot]; if (k>10) k=11; nUSparse[k]++; int kk=0; for (int k=0;k<12;k++) kk+=nUSparse[k]; if (kk%1000000==0) { printf("ZZsparse"); for (int k=0;k<12;k++) printf(" %d",nUSparse[k]); printf("\n"); } } #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex start = startColumn[iPivot]; #else //CoinBigIndex start = startColumn[iPivot]; CoinBigIndex start = scatter.offset; #endif instrument_add(number); #ifndef INLINE_IT CoinBigIndex j; for ( j = start; j < start+number; j++ ) { CoinFactorizationDouble value = element[j]; assert (value); CoinSimplexInt iRow = indexRow[j]; region[iRow] -= value * pivotValue; } #else #ifdef ABC_USE_FUNCTION_POINTERS #if ABC_USE_FUNCTION_POINTERS (*(scatter.functionPointer))(number,pivotValue,elementUColumnPlus+start,region); #else CoinAbcScatterUpdate(number,pivotValue,elementUColumnPlus+start,region); #endif #else CoinAbcScatterUpdate(number,pivotValue,element+start,indexRow+start,region); #endif #endif } #if ETAS_1<2 pivotValue *= pivotRegion[iPivot]; if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { region[iPivot]=pivotValue; regionIndex[numberNonZero++]=iPivot; } #else if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue2 ) ) { region[iPivot]=pivotValue2; regionIndex[numberNonZero++]=iPivot; } else { region[iPivot]=0.0; } #endif } else { region[iPivot]=0.0; } } } #if ABC_SMALL<2 // slacks for (;put> COINFACTORIZATION_SHIFT_PER_INT2; mark[word0]=0; #endif if (expValue) { if (!TEST_EXPONENT_LESS_THAN_UPDATE_TOLERANCE(expValue)) { CoinFactorizationDouble pivotValue = region[iPivot]; if ( !TEST_LESS_THAN_TOLERANCE_REGISTER( pivotValue ) ) { region[iPivot]=pivotValue; regionIndex[numberNonZero++]=iPivot; } } else { region[iPivot]=0.0; } } } #endif #ifdef COIN_DEBUG for (CoinSimplexInt i=0;i>COINFACTORIZATION_SHIFT_PER_INT2;i++) { assert (!mark[i]); } #endif regionSparse->setNumElements ( numberNonZero ); instrument_end_and_adjust(1.3); } #endif // Store update after doing L and R - retuns false if no room bool CoinAbcTypeFactorization::storeFT( #if ABC_SMALL<3 const #endif CoinIndexedVector * updateFT) { #if ABC_SMALL<3 CoinSimplexInt numberNonZero = updateFT->getNumElements ( ); #else CoinSimplexInt numberNonZero = numberRows_; #endif #ifndef ABC_USE_FUNCTION_POINTERS if (lengthAreaU_>=lastEntryByColumnU_+numberNonZero) { #else if (lengthAreaUPlus_>=lastEntryByColumnUPlus_+(3*numberNonZero+1)/2) { scatterStruct & scatter = scatterUColumn()[numberRows_]; CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; #endif #if ABC_SMALL<3 const CoinFactorizationDouble * COIN_RESTRICT region = denseVector(updateFT); const CoinSimplexInt * COIN_RESTRICT regionIndex = updateFT->getIndices(); #else CoinSimplexDouble * COIN_RESTRICT region = updateFT->denseVector ( ); #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; //we are going to save at end of U startColumnU[numberRows_] = lastEntryByColumnU_; CoinSimplexInt * COIN_RESTRICT putIndex = indexRowUAddress_ + lastEntryByColumnU_; CoinFactorizationDouble * COIN_RESTRICT putElement = elementUAddress_ + lastEntryByColumnU_; #else scatter.offset=lastEntryByColumnUPlus_; CoinFactorizationDouble * COIN_RESTRICT putElement = elementUColumnPlus + lastEntryByColumnUPlus_; CoinSimplexInt * COIN_RESTRICT putIndex = reinterpret_cast(putElement+numberNonZero); #endif #if ABC_SMALL<3 for (CoinSimplexInt i=0;igetNumElements(); toLongArray(regionSparse,0); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparseX); #endif // ******* L //printf("a\n"); //regionSparse->checkClean(); updateColumnL ( regionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif ); //printf("b\n"); //regionSparse->checkClean(); //row bits here updateColumnR ( regionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif ); //printf("c\n"); //regionSparse->checkClean(); bool doFT=storeFT(regionSparse); //printf("d\n"); //regionSparse->checkClean(); //update counts // ******* U updateColumnU ( regionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranFTCountInput_) #endif ); //printf("e\n"); #if ABC_DEBUG regionSparse->checkClean(); #endif numberNonZero=regionSparse->getNumElements(); // will be negative if no room if ( doFT ) return numberNonZero; else return -numberNonZero; } void CoinAbcTypeFactorization::updateColumnFT ( CoinIndexedVector & regionSparseX, CoinIndexedVector & partialUpdate, int whichSparse) { CoinIndexedVector * regionSparse = ®ionSparseX; CoinSimplexInt numberNonZero=regionSparse->getNumElements(); toLongArray(regionSparse,whichSparse); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparseX); #endif // ******* L //printf("a\n"); //regionSparse->checkClean(); updateColumnL ( regionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif #if ABC_PARALLEL ,whichSparse #endif ); //printf("b\n"); //regionSparse->checkClean(); //row bits here updateColumnR ( regionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif #if ABC_PARALLEL ,whichSparse #endif ); numberNonZero = regionSparse->getNumElements ( ); CoinSimplexInt * COIN_RESTRICT indexSave=partialUpdate.getIndices(); CoinSimplexDouble * COIN_RESTRICT regionSave=partialUpdate.denseVector(); partialUpdate.setNumElements(numberNonZero); memcpy(indexSave,regionSparse->getIndices(),numberNonZero*sizeof(CoinSimplexInt)); partialUpdate.setPackedMode(false); CoinFactorizationDouble * COIN_RESTRICT region=denseVector(regionSparse); for (int i=0;i(ftranFTCountInput_) #endif #if ABC_PARALLEL ,whichSparse #endif ); //printf("e\n"); #if ABC_DEBUG regionSparse->checkClean(); #endif } int CoinAbcTypeFactorization::updateColumnFTPart1 ( CoinIndexedVector & regionSparse) { toLongArray(®ionSparse,0); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparse); #endif //CoinSimplexInt numberNonZero=regionSparse.getNumElements(); // ******* L //regionSparse.checkClean(); updateColumnL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif #if ABC_PARALLEL ,2 #endif ); //regionSparse.checkClean(); //row bits here updateColumnR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranFTCountInput_) #endif #if ABC_PARALLEL ,2 #endif ); //regionSparse.checkClean(); bool doFT=storeFT(®ionSparse); // will be negative if no room if ( doFT ) return 1; else return -1; } void CoinAbcTypeFactorization::updateColumnFTPart2 ( CoinIndexedVector & regionSparse) { toLongArray(®ionSparse,0); //CoinSimplexInt numberNonZero=regionSparse.getNumElements(); // ******* U updateColumnU ( ®ionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranFTCountInput_) #endif #if ABC_PARALLEL ,2 #endif ); #if ABC_DEBUG regionSparse.checkClean(); #endif } /* Updates one column (FTRAN) */ void CoinAbcTypeFactorization::updateColumnCpu ( CoinIndexedVector & regionSparse,int whichCpu) const { toLongArray(®ionSparse,whichCpu); #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran permuteInForFtran(regionSparse); #endif // ******* L updateColumnL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL ,whichCpu #endif ); //row bits here updateColumnR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL ,whichCpu #endif ); //update counts // ******* U updateColumnU ( ®ionSparse #if ABC_SMALL<2 , reinterpret_cast(ftranCountInput_) #endif #if ABC_PARALLEL ,whichCpu #endif ); fromLongArray(whichCpu); #if ABC_DEBUG regionSparse.checkClean(); #endif } /* Updates one column (BTRAN) */ void CoinAbcTypeFactorization::updateColumnTransposeCpu ( CoinIndexedVector & regionSparse,int whichCpu) const { toLongArray(®ionSparse,whichCpu); CoinSimplexDouble * COIN_RESTRICT region = regionSparse.denseVector(); CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse.getIndices(); CoinSimplexInt numberNonZero = regionSparse.getNumElements(); //#if COIN_BIG_DOUBLE==1 //const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegion_.array()+1; //#else const CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; //#endif #ifndef ABC_ORDERED_FACTORIZATION // can I move this #ifndef INLINE_IT3 for (CoinSimplexInt i = 0; i < numberNonZero; i ++ ) { CoinSimplexInt iRow = regionIndex[i]; CoinSimplexDouble value = region[iRow]; value *= pivotRegion[iRow]; region[iRow] = value; } #else multiplyIndexed(numberNonZero,pivotRegion, regionIndex,region); #endif #else // Permute in for Btran permuteInForBtranAndMultiply(regionSparse); #endif // ******* U // Apply pivot region - could be combined for speed // Can only combine/move inside vector for sparse CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; #if ABC_SMALL<2 // copy of code inside transposeU bool goSparse=false; #else #define goSparse false #endif #if ABC_SMALL<2 // Guess at number at end if (gotUCopy()) { assert (btranAverageAfterU_); CoinSimplexInt newNumber = static_cast (numberNonZero*btranAverageAfterU_*twiddleBtranFactor1()); if (newNumber< sparseThreshold_) goSparse = true; } #endif if (numberNonZero<40&&(numberNonZero<<4)(btranCountInput_) #endif #if ABC_PARALLEL ,whichCpu #endif ); //row bits here updateColumnTransposeR ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif ); // ******* L updateColumnTransposeL ( ®ionSparse #if ABC_SMALL<2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL , whichCpu #endif ); #if ABC_SMALL<3 #ifdef ABC_ORDERED_FACTORIZATION // Permute out for Btran permuteOutForBtran(regionSparse); #endif #if ABC_DEBUG regionSparse.checkClean(); #endif numberNonZero = regionSparse.getNumElements ( ); #else numberNonZero=0; for (CoinSimplexInt i=0;i2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex space = lengthAreaU_ - lastEntryByRowU_; CoinSimplexInt * COIN_RESTRICT nextRow = nextRowAddress_; CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; if ( space < extraNeeded + number + 2 ) { //compression CoinSimplexInt iRow = nextRow[numberRows_]; CoinBigIndex put = 0; while ( iRow != numberRows_ ) { //move CoinBigIndex get = startRow[iRow]; CoinBigIndex getEnd = startRow[iRow] + numberInRow[iRow]; startRow[iRow] = put; CoinBigIndex i; for ( i = get; i < getEnd; i++ ) { indexColumnU[put] = indexColumnU[i]; #if CONVERTROW convertRowToColumn[put] = convertRowToColumn[i]; #if CONVERTROW>2 convertColumnToRow[i] = convertColumnToRow[put]; #endif #endif elementRowU[put] = elementRowU[i]; put++; } iRow = nextRow[iRow]; } /* endwhile */ numberCompressions_++; lastEntryByRowU_ = put; space = lengthAreaU_ - put; if ( space < extraNeeded + number + 2 ) { //need more space //if we can allocate bigger then do so and copy //if not then return so code can start again status_ = -99; return false; } } CoinBigIndex put = lastEntryByRowU_; CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt last = lastRow[iRow]; //out nextRow[last] = next; lastRow[next] = last; //in at end last = lastRow[numberRows_]; nextRow[last] = iRow; lastRow[numberRows_] = iRow; lastRow[iRow] = last; nextRow[iRow] = numberRows_; //move CoinBigIndex get = startRow[iRow]; startRow[iRow] = put; while ( number ) { number--; indexColumnU[put] = indexColumnU[get]; #if CONVERTROW convertRowToColumn[put] = convertRowToColumn[get]; #if CONVERTROW>2 convertColumnToRow[get] = convertColumnToRow[put]; #endif #endif elementRowU[put] = elementRowU[get]; put++; get++; } /* endwhile */ //add four for luck lastEntryByRowU_ = put + extraNeeded + 4; return true; } #endif void CoinAbcTypeFactorization::printRegion(const CoinIndexedVector & vector,const char * where) const { //return; CoinSimplexInt numberNonZero = vector.getNumElements ( ); //CoinSimplexInt * COIN_RESTRICT regionIndex = vector.getIndices ( ); const CoinSimplexDouble * COIN_RESTRICT region = vector.denseVector ( ); int n=0; for (int i=0;igetIndices ( ); CoinSimplexInt numberNonZero = regionFrom->getNumElements(); CoinSimplexInt * COIN_RESTRICT index = regionFrom->getIndices(); CoinSimplexDouble * COIN_RESTRICT region = regionTo->denseVector(); CoinSimplexDouble * COIN_RESTRICT array = regionFrom->denseVector(); for (CoinSimplexInt j = 0; j < numberNonZero; j ++ ) { CoinSimplexInt iRow = index[j]; CoinSimplexDouble value = array[j]; array[j]=0.0; region[iRow] = value; regionIndex[j] = iRow; } regionTo->setNumElements(numberNonZero); } void CoinAbcTypeFactorization::pack ( CoinIndexedVector * regionFrom, CoinIndexedVector * regionTo) const { // move CoinSimplexInt * COIN_RESTRICT regionIndex = regionFrom->getIndices ( ); CoinSimplexInt numberNonZero = regionFrom->getNumElements(); CoinSimplexInt * COIN_RESTRICT index = regionTo->getIndices(); CoinSimplexDouble * COIN_RESTRICT region = regionFrom->denseVector(); CoinSimplexDouble * COIN_RESTRICT array = regionTo->denseVector(); for (CoinSimplexInt j = 0; j < numberNonZero; j ++ ) { CoinSimplexInt iRow = regionIndex[j]; CoinSimplexDouble value = region[iRow]; region[iRow]=0.0; array[j] = value; index[j] = iRow; } regionTo->setNumElements(numberNonZero); } // Set up addresses from arrays void CoinAbcTypeFactorization::doAddresses() { pivotColumnAddress_ = pivotColumn_.array(); permuteAddress_ = permute_.array(); pivotRegionAddress_ = pivotRegion_.array()+1; elementUAddress_ = elementU_.array(); indexRowUAddress_ = indexRowU_.array(); numberInColumnAddress_ = numberInColumn_.array(); numberInColumnPlusAddress_ = numberInColumnPlus_.array(); #ifdef ABC_USE_FUNCTION_POINTERS scatterPointersUColumnAddress_ = reinterpret_cast(scatterUColumn_.array()); #endif startColumnUAddress_ = startColumnU_.array(); #if CONVERTROW convertRowToColumnUAddress_ = convertRowToColumnU_.array(); #if CONVERTROW>1 convertColumnToRowUAddress_ = convertColumnToRowU_.array(); #endif #endif #if ABC_SMALL<2 elementRowUAddress_ = elementRowU_.array(); #endif startRowUAddress_ = startRowU_.array(); numberInRowAddress_ = numberInRow_.array(); indexColumnUAddress_ = indexColumnU_.array(); firstCountAddress_ = firstCount_.array(); nextCountAddress_ = nextCount(); lastCountAddress_ = lastCount(); nextColumnAddress_ = nextColumn_.array(); lastColumnAddress_ = lastColumn_.array(); nextRowAddress_ = nextRow_.array(); lastRowAddress_ = lastRow_.array(); saveColumnAddress_ = saveColumn_.array(); //saveColumnAddress2_ = saveColumn_.array()+numberRows_; elementLAddress_ = elementL_.array(); indexRowLAddress_ = indexRowL_.array(); startColumnLAddress_ = startColumnL_.array(); #if ABC_SMALL<2 startRowLAddress_ = startRowL_.array(); #endif pivotLinkedBackwardsAddress_ = pivotLinkedBackwards(); pivotLinkedForwardsAddress_ = pivotLinkedForwards(); pivotLOrderAddress_ = pivotLOrder(); startColumnRAddress_ = startColumnR(); // next two are recomputed cleanup elementRAddress_ = elementL_.array() + lengthL_; indexRowRAddress_ = indexRowL_.array() + lengthL_; #if ABC_SMALL<2 indexColumnLAddress_ = indexColumnL_.array(); elementByRowLAddress_ = elementByRowL_.array(); #endif #if ABC_DENSE_CODE denseAreaAddress_ = denseArea_.array(); #endif workAreaAddress_ = workArea_.array(); workArea2Address_ = workArea2_.array(); #if ABC_SMALL<2 sparseAddress_ = sparse_.array(); CoinAbcStack * stackList = reinterpret_cast(sparseAddress_); listAddress_ = reinterpret_cast(stackList+numberRows_); markRowAddress_ = reinterpret_cast (listAddress_ + numberRows_); #endif } #endif Clp-1.15.10/src/CoinAbcSmallFactorization2.cpp0000644000076600007660000000103012101105055017434 0ustar coincoin/* $Id: CoinAbcSmallFactorization2.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization2.cpp" #endif Clp-1.15.10/src/AbcMatrix.cpp0000644000076600007660000035425112101105055014220 0ustar coincoin/* $Id: AbcMatrix.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcPrimalColumnDantzig.hpp" #include "AbcPrimalColumnSteepest.hpp" #include "CoinTime.hpp" #include "AbcSimplex.hpp" #include "AbcSimplexDual.hpp" // at end to get min/max! #include "AbcMatrix.hpp" #include "ClpMessage.hpp" #ifdef INTEL_MKL #include "mkl_spblas.h" #endif #if ABC_INSTRUMENT>1 extern int abcPricing[20]; extern int abcPricingDense[20]; #endif //============================================================================= //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcMatrix::AbcMatrix () : matrix_(NULL), model_(NULL), rowStart_(NULL), element_(NULL), column_(NULL), numberColumnBlocks_(0), numberRowBlocks_(0), #ifdef COUNT_COPY countRealColumn_(NULL), countStartLarge_(NULL), countRow_(NULL), countElement_(NULL), smallestCount_(0), largestCount_(0), #endif startFraction_(0.0), endFraction_(1.0), savedBestDj_(0.0), originalWanted_(0), currentWanted_(0), savedBestSequence_(-1), minimumObjectsScan_(-1), minimumGoodReducedCosts_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcMatrix::AbcMatrix (const AbcMatrix & rhs) { #ifndef COIN_SPARSE_MATRIX matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -1, -1); #else matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -0, -0); #endif model_=rhs.model_; rowStart_ = NULL; element_ = NULL; column_ = NULL; #ifdef COUNT_COPY countRealColumn_ = NULL; countStartLarge_ = NULL; countRow_ = NULL; countElement_ = NULL; #endif numberColumnBlocks_ = rhs.numberColumnBlocks_; CoinAbcMemcpy(startColumnBlock_,rhs.startColumnBlock_,numberColumnBlocks_+1); numberRowBlocks_ = rhs.numberRowBlocks_; if (numberRowBlocks_) { assert (model_); int numberRows=model_->numberRows(); int numberElements = matrix_->getNumElements(); memcpy(blockStart_,rhs.blockStart_,sizeof(blockStart_)); rowStart_=CoinCopyOfArray(rhs.rowStart_,numberRows*(numberRowBlocks_+2)); element_=CoinCopyOfArray(rhs.element_,numberElements); column_=CoinCopyOfArray(rhs.column_,numberElements); #ifdef COUNT_COPY smallestCount_ = rhs.smallestCount_; largestCount_ = rhs.largestCount_; int numberColumns=model_->numberColumns(); countRealColumn_=CoinCopyOfArray(rhs.countRealColumn_,numberColumns); memcpy(countStart_,rhs.countStart_,reinterpret_cast(&countRealColumn_)- reinterpret_cast(countStart_)); int numberLarge = numberColumns-countStart_[MAX_COUNT]; countStartLarge_=CoinCopyOfArray(rhs.countStartLarge_,numberLarge+1); numberElements=countStartLarge_[numberLarge]; countElement_=CoinCopyOfArray(rhs.countElement_,numberElements); countRow_=CoinCopyOfArray(rhs.countRow_,numberElements); #endif } } AbcMatrix::AbcMatrix (const CoinPackedMatrix & rhs) { #ifndef COIN_SPARSE_MATRIX matrix_ = new CoinPackedMatrix(rhs, -1, -1); #else matrix_ = new CoinPackedMatrix(rhs, -0, -0); #endif matrix_->cleanMatrix(); model_=NULL; rowStart_ = NULL; element_ = NULL; column_ = NULL; #ifdef COUNT_COPY countRealColumn_ = NULL; countStartLarge_ = NULL; countRow_ = NULL; countElement_ = NULL; smallestCount_ = 0; largestCount_ = 0; #endif numberColumnBlocks_=1; startColumnBlock_[0]=0; startColumnBlock_[1]=0; numberRowBlocks_ = 0; startFraction_ = 0; endFraction_ = 1.0; savedBestDj_ = 0; originalWanted_ = 0; currentWanted_ = 0; savedBestSequence_ = -1; minimumObjectsScan_ = -1; minimumGoodReducedCosts_ = -1; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcMatrix::~AbcMatrix () { delete matrix_; delete [] rowStart_; delete [] element_; delete [] column_; #ifdef COUNT_COPY delete [] countRealColumn_; delete [] countStartLarge_; delete [] countRow_; delete [] countElement_; #endif } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcMatrix & AbcMatrix::operator=(const AbcMatrix& rhs) { if (this != &rhs) { delete matrix_; #ifndef COIN_SPARSE_MATRIX matrix_ = new CoinPackedMatrix(*(rhs.matrix_)); #else matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -0, -0); #endif model_=rhs.model_; delete [] rowStart_; delete [] element_; delete [] column_; #ifdef COUNT_COPY delete [] countRealColumn_; delete [] countStartLarge_; delete [] countRow_; delete [] countElement_; #endif rowStart_ = NULL; element_ = NULL; column_ = NULL; #ifdef COUNT_COPY countRealColumn_ = NULL; countStartLarge_ = NULL; countRow_ = NULL; countElement_ = NULL; #endif numberColumnBlocks_ = rhs.numberColumnBlocks_; CoinAbcMemcpy(startColumnBlock_,rhs.startColumnBlock_,numberColumnBlocks_+1); numberRowBlocks_ = rhs.numberRowBlocks_; if (numberRowBlocks_) { assert (model_); int numberRows=model_->numberRows(); int numberElements = matrix_->getNumElements(); memcpy(blockStart_,rhs.blockStart_,sizeof(blockStart_)); rowStart_=CoinCopyOfArray(rhs.rowStart_,numberRows*(numberRowBlocks_+2)); element_=CoinCopyOfArray(rhs.element_,numberElements); column_=CoinCopyOfArray(rhs.column_,numberElements); #ifdef COUNT_COPY smallestCount_ = rhs.smallestCount_; largestCount_ = rhs.largestCount_; int numberColumns=model_->numberColumns(); countRealColumn_=CoinCopyOfArray(rhs.countRealColumn_,numberColumns); memcpy(countStart_,rhs.countStart_,reinterpret_cast(&countRealColumn_)- reinterpret_cast(countStart_)); int numberLarge = numberColumns-countStart_[MAX_COUNT]; countStartLarge_=CoinCopyOfArray(rhs.countStartLarge_,numberLarge+1); numberElements=countStartLarge_[numberLarge]; countElement_=CoinCopyOfArray(rhs.countElement_,numberElements); countRow_=CoinCopyOfArray(rhs.countRow_,numberElements); #endif } startFraction_ = rhs.startFraction_; endFraction_ = rhs.endFraction_; savedBestDj_ = rhs.savedBestDj_; originalWanted_ = rhs.originalWanted_; currentWanted_ = rhs.currentWanted_; savedBestSequence_ = rhs.savedBestSequence_; minimumObjectsScan_ = rhs.minimumObjectsScan_; minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_; } return *this; } // Sets model void AbcMatrix::setModel(AbcSimplex * model) { model_=model; int numberColumns=model_->numberColumns(); bool needExtension=numberColumns>matrix_->getNumCols(); if (needExtension) { CoinBigIndex lastElement = matrix_->getNumElements(); matrix_->reserve(numberColumns,lastElement,true); CoinBigIndex * columnStart = matrix_->getMutableVectorStarts(); for (int i=numberColumns;i>=0;i--) { if (columnStart[i]==0) columnStart[i]=lastElement; else break; } assert (lastElement==columnStart[numberColumns]); } } /* Returns a new matrix in reverse order without gaps */ CoinPackedMatrix * AbcMatrix::reverseOrderedCopy() const { CoinPackedMatrix * matrix = new CoinPackedMatrix(); matrix->setExtraGap(0.0); matrix->setExtraMajor(0.0); matrix->reverseOrderedCopyOf(*matrix_); return matrix; } /// returns number of elements in column part of basis, CoinBigIndex AbcMatrix::countBasis( const int * whichColumn, int & numberColumnBasic) { const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); CoinBigIndex numberElements = 0; int numberRows=model_->numberRows(); // just count - can be over so ignore zero problem for (int i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]-numberRows; numberElements += columnLength[iColumn]; } return numberElements; } void AbcMatrix::fillBasis(const int * COIN_RESTRICT whichColumn, int & numberColumnBasic, int * COIN_RESTRICT indexRowU, int * COIN_RESTRICT start, int * COIN_RESTRICT rowCount, int * COIN_RESTRICT columnCount, CoinFactorizationDouble * COIN_RESTRICT elementU) { const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); CoinBigIndex numberElements = start[0]; // fill const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const int * COIN_RESTRICT row = matrix_->getIndices(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); int numberRows=model_->numberRows(); for (int i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]-numberRows; int length = columnLength[iColumn]; CoinBigIndex startThis = columnStart[iColumn]; columnCount[i] = length; CoinBigIndex endThis = startThis + length; for (CoinBigIndex j = startThis; j < endThis; j++) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; assert (elementByColumn[j]); elementU[numberElements++] = elementByColumn[j]; } start[i+1] = numberElements; } } #ifdef ABC_LONG_FACTORIZATION void AbcMatrix::fillBasis(const int * COIN_RESTRICT whichColumn, int & numberColumnBasic, int * COIN_RESTRICT indexRowU, int * COIN_RESTRICT start, int * COIN_RESTRICT rowCount, int * COIN_RESTRICT columnCount, long double * COIN_RESTRICT elementU) { const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); CoinBigIndex numberElements = start[0]; // fill const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const int * COIN_RESTRICT row = matrix_->getIndices(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); int numberRows=model_->numberRows(); for (int i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]-numberRows; int length = columnLength[iColumn]; CoinBigIndex startThis = columnStart[iColumn]; columnCount[i] = length; CoinBigIndex endThis = startThis + length; for (CoinBigIndex j = startThis; j < endThis; j++) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; assert (elementByColumn[j]); elementU[numberElements++] = elementByColumn[j]; } start[i+1] = numberElements; } } #endif #if 0 /// Move largest in column to beginning void AbcMatrix::moveLargestToStart() { // get matrix data pointers int * COIN_RESTRICT row = matrix_->getMutableIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); double * COIN_RESTRICT elementByColumn = matrix_->getMutableElements(); int numberColumns=model_->numberColumns(); CoinBigIndex start = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex end = columnStart[iColumn+1]; double largest=0.0; int position=-1; for (CoinBigIndex j = start; j < end; j++) { double value = fabs(elementByColumn[j]); if (value>largest) { largest=value; position=j; } } assert (position>=0); // ? empty column if (position>start) { double value=elementByColumn[start]; elementByColumn[start]=elementByColumn[position]; elementByColumn[position]=value; int iRow=row[start]; row[start]=row[position]; row[position]=iRow; } start=end; } } #endif // Creates row copy void AbcMatrix::createRowCopy() { #if ABC_PARALLEL if (model_->parallelMode()==0) #endif numberRowBlocks_=1; #if ABC_PARALLEL else numberRowBlocks_=CoinMin(NUMBER_ROW_BLOCKS,model_->numberCpus()); #endif int maximumRows=model_->maximumAbcNumberRows(); int numberRows=model_->numberRows(); int numberColumns=model_->numberColumns(); int numberElements = matrix_->getNumElements(); assert (!rowStart_); char * whichBlock_=new char [numberColumns]; rowStart_=new CoinBigIndex[numberRows*(numberRowBlocks_+2)]; element_ = new double [numberElements]; column_ = new int [numberElements]; const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); memset(blockStart_,0,sizeof(blockStart_)); int ecount[10]; assert (numberRowBlocks_<16); CoinAbcMemset0(ecount,10); // allocate to blocks (put a bit less in first as will be dealing with slacks) LATER CoinBigIndex start=0; int block=0; CoinBigIndex work=(2*numberColumns+matrix_->getNumElements()+numberRowBlocks_-1)/numberRowBlocks_; CoinBigIndex thisWork=work; for (int iColumn=0;iColumn=0&&block(block); thisWork -= 2+end-start; ecount[block]+=end-start; start=end; blockStart_[block]++; if (thisWork<=0) { block++; thisWork=work; } } #if 0 printf("Blocks "); for (int i=0;igetIndices(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); // counts CoinAbcMemset0(rowStart_,numberRows*(numberRowBlocks_+2)); int * COIN_RESTRICT last = rowStart_+numberRows*(numberRowBlocks_+1); for (int iColumn=0;iColumn=0;iBlock--) blockStart_[iBlock+1]=blockStart_[iBlock]; blockStart_[0]=0; CoinBigIndex put=0; for (int iRow=1;iRow=0;iBlock--) { blockStart_[iBlock+1]=blockStart_[iBlock]+maximumRows; CoinAbcMemcpy(rowStart_+base,rowStart_+base-numberRows,numberRows); base -= numberRows; } blockStart_[0]=0;//maximumRows; delete [] whichBlock_; // and move CoinAbcMemcpy(rowStart_,last,numberRows); // All in useful CoinAbcMemcpy(rowStart_+(numberRowBlocks_+1)*numberRows, rowStart_+(numberRowBlocks_)*numberRows,numberRows); #ifdef COUNT_COPY // now blocked by element count countRealColumn_=new int [numberColumns]; int counts [2*MAX_COUNT]; memset(counts,0,sizeof(counts)); //memset(countFirst_,0,sizeof(countFirst_)); int numberLarge=0; for (int iColumn=0;iColumn=SMALL_COUNT) { n &= 3; int extra=(4-n)&3; numberExtra+= i*extra; } else { // treat as large numberLarge+=n; } } countElement_= new double [numberElements+numberExtra]; countRow_=new int [numberElements+numberExtra]; countStartLarge_ = new CoinBigIndex [numberLarge+1]; countStartLarge_[numberLarge]=numberElements+numberExtra; //return; CoinInt64 xx = reinterpret_cast(countElement_); int iBottom = static_cast(xx & 31); int offset = iBottom>>3; CoinBigIndex firstElementLarge=0; if (offset) firstElementLarge=4-offset; //countStart_[0]=firstElementLarge; int positionLarge=0; smallestCount_=0; largestCount_=0; for (int i=0;i=SMALL_COUNT) { counts[i+MAX_COUNT]=1; if (smallestCount_==0) smallestCount_=i; largestCount_=i; positionLarge+=n; firstElementLarge+=n*i; n &= 3; int extra=(4-n)&3; firstElementLarge+= i*extra; } counts[i]=0; } largestCount_++; countFirst_[MAX_COUNT]=positionLarge; countStart_[MAX_COUNT]=firstElementLarge; numberLarge=0; for (int iColumn=0;iColumnnumberRows(); CoinBigIndex * COIN_RESTRICT rowEnd = rowStart_+numberRows; const CoinBigIndex * COIN_RESTRICT rowReallyEnd = rowStart_+2*numberRows; for (int iRow=0;iRownumberRows(); bool inBranchAndBound=(model_->specialOptions(),0x1000000)!=0; bool doScaling=numberAlreadyScaled>=0; if (!doScaling) numberAlreadyScaled=0; if (numberAlreadyScaled==numberRows) return; // no need to do anything int numberColumns=model_->numberColumns(); double * COIN_RESTRICT rowScale=model_->rowScale2(); double * COIN_RESTRICT inverseRowScale=model_->inverseRowScale2(); double * COIN_RESTRICT columnScale=model_->columnScale2(); double * COIN_RESTRICT inverseColumnScale=model_->inverseColumnScale2(); // we are going to mark bits we are interested in int whichArray=model_->getAvailableArrayPublic(); char * COIN_RESTRICT usefulColumn = reinterpret_cast(model_->usefulArray(whichArray)->getIndices()); memset(usefulColumn,1,numberColumns); const double * COIN_RESTRICT rowLower = model_->rowLower(); const double * COIN_RESTRICT rowUpper = model_->rowUpper(); const double * COIN_RESTRICT columnLower = model_->columnLower(); const double * COIN_RESTRICT columnUpper = model_->columnUpper(); //#define LEAVE_FIXED // mark empty and fixed columns // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); double * COIN_RESTRICT elementByColumn = matrix_->getMutableElements(); CoinPackedMatrix * COIN_RESTRICT rowCopy = reverseOrderedCopy(); const int * column = rowCopy->getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = rowCopy->getVectorStarts(); const double * COIN_RESTRICT element = rowCopy->getElements(); assert (numberAlreadyScaled>=0&&numberAlreadyScaledstart) { for (CoinBigIndex j = start; j < end; j++) { double value = fabs(elementByColumn[j]); overallLargest = CoinMax(overallLargest, value); overallSmallest = CoinMin(overallSmallest, value); } } else { usefulColumn[iColumn]=0; } } start=end; } } else { CoinBigIndex start = rowStart[numberAlreadyScaled]; for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { rowScale[iRow]=1.0; CoinBigIndex end = rowStart[iRow+1]; for (CoinBigIndex j = start; j < end; j++) { int iColumn=column[j]; if (usefulColumn[iColumn]) { double value = fabs(elementByColumn[j])*columnScale[iColumn]; overallLargest = CoinMax(overallLargest, value); overallSmallest = CoinMin(overallSmallest, value); } } } } if ((overallSmallest >= 0.5 && overallLargest <= 2.0)||!doScaling) { //printf("no scaling\n"); delete rowCopy; model_->clearArraysPublic(whichArray); CoinFillN(inverseRowScale+numberAlreadyScaled,numberRows-numberAlreadyScaled,1.0); if (!numberAlreadyScaled) CoinFillN(inverseColumnScale,numberColumns,1.0); //moveLargestToStart(); return ; } // need to scale double largest; double smallest; int scalingMethod=model_->scalingFlag(); if (scalingMethod == 4) { // As auto scalingMethod = 3; } else if (scalingMethod == 5) { // As geometric scalingMethod = 2; } double savedOverallRatio = 0.0; double tolerance = 5.0 * model_->primalTolerance(); bool finished = false; // if scalingMethod 3 then may change bool extraDetails = (model_->logLevel() > 2); bool secondTime=false; while (!finished) { int numberPass = !numberAlreadyScaled ? 3 : 1; overallLargest = -1.0e-20; overallSmallest = 1.0e20; if (!secondTime) { secondTime=true; } else { CoinFillN ( rowScale, numberRows, 1.0); CoinFillN ( columnScale, numberColumns, 1.0); } if (scalingMethod == 1 || scalingMethod == 3) { // Maximum in each row for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { largest = 1.0e-10; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); largest = CoinMax(largest, value); assert (largest < 1.0e40); } } rowScale[iRow] = 1.0 / largest; #ifdef COIN_DEVELOP if (extraDetails) { overallLargest = CoinMax(overallLargest, largest); overallSmallest = CoinMin(overallSmallest, largest); } #endif } } else { while (numberPass) { overallLargest = 0.0; overallSmallest = 1.0e50; numberPass--; // Geometric mean on row scales for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { largest = 1.0e-50; smallest = 1.0e50; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } #ifdef SQRT_ARRAY rowScale[iRow] = smallest * largest; #else rowScale[iRow] = 1.0 / sqrt(smallest * largest); #endif if (extraDetails) { overallLargest = CoinMax(largest * rowScale[iRow], overallLargest); overallSmallest = CoinMin(smallest * rowScale[iRow], overallSmallest); } } if (model_->scalingFlag() == 5) break; // just scale rows #ifdef SQRT_ARRAY CoinAbcInverseSqrts(rowScale, numberRows); #endif if (!inBranchAndBound) model_->messageHandler()->message(CLP_PACKEDSCALE_WHILE, *model_->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; // skip last column round if (numberPass == 1) break; // Geometric mean on column scales for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { largest = 1.0e-50; smallest = 1.0e50; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; double value = fabs(elementByColumn[j]); value *= rowScale[iRow]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } #ifdef SQRT_ARRAY columnScale[iColumn] = smallest * largest; #else columnScale[iColumn] = 1.0 / sqrt(smallest * largest); #endif } } #ifdef SQRT_ARRAY CoinAbcInverseSqrts(columnScale, numberColumns); #endif } } // If ranges will make horrid then scale for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { double difference = rowUpper[iRow] - rowLower[iRow]; double scaledDifference = difference * rowScale[iRow]; if (scaledDifference > tolerance && scaledDifference < 1.0e-4) { // make gap larger rowScale[iRow] *= 1.0e-4 / scaledDifference; rowScale[iRow] = CoinMax(1.0e-10, CoinMin(1.0e10, rowScale[iRow])); //printf("Row %d difference %g scaled diff %g => %g\n",iRow,difference, // scaledDifference,difference*rowScale[iRow]); } } // final pass to scale columns so largest is reasonable // See what smallest will be if largest is 1.0 if (model_->scalingFlag() != 5) { overallSmallest = 1.0e50; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { largest = 1.0e-20; smallest = 1.0e50; for (CoinBigIndex j = columnStart[iColumn];j < columnStart[iColumn+1]; j++) { int iRow = row[j]; double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } if (overallSmallest * largest > smallest) overallSmallest = smallest / largest; } } } if (scalingMethod == 1 || scalingMethod == 2) { finished = true; } else if (savedOverallRatio == 0.0 && scalingMethod != 4) { savedOverallRatio = overallSmallest; scalingMethod = 4; } else { assert (scalingMethod == 4); if (overallSmallest > 2.0 * savedOverallRatio) { finished = true; // geometric was better if (model_->scalingFlag() == 4) { // If in Branch and bound change if ((model_->specialOptions() & 1024) != 0) { model_->scaling(2); } } } else { scalingMethod = 1; // redo equilibrium if (model_->scalingFlag() == 4) { // If in Branch and bound change if ((model_->specialOptions() & 1024) != 0) { model_->scaling(1); } } } #if 0 if (extraDetails) { if (finished) printf("equilibrium ratio %g, geometric ratio %g , geo chosen\n", savedOverallRatio, overallSmallest); else printf("equilibrium ratio %g, geometric ratio %g , equi chosen\n", savedOverallRatio, overallSmallest); } #endif } } //#define RANDOMIZE #ifdef RANDOMIZE // randomize by up to 10% for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 rowScale[iRow] *= (1.0 + 0.1 * value); } #endif overallLargest = 1.0; if (overallSmallest < 1.0e-1) overallLargest = 1.0 / sqrt(overallSmallest); overallLargest = CoinMin(100.0, overallLargest); overallSmallest = 1.0e50; char * COIN_RESTRICT usedRow = reinterpret_cast(inverseRowScale); memset(usedRow, 0, numberRows); //printf("scaling %d\n",model_->scalingFlag()); if (model_->scalingFlag() != 5) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { largest = 1.0e-20; smallest = 1.0e50; for (CoinBigIndex j = columnStart[iColumn];j < columnStart[iColumn+1]; j++) { int iRow = row[j]; usedRow[iRow] = 1; double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } columnScale[iColumn] = overallLargest / largest; //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn])); #ifdef RANDOMIZE if (!numberAlreadyScaled) { double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 columnScale[iColumn] *= (1.0 + 0.1 * value); } #endif double difference = columnUpper[iColumn] - columnLower[iColumn]; if (difference < 1.0e-5 * columnScale[iColumn]) { // make gap larger columnScale[iColumn] = difference / 1.0e-5; //printf("Column %d difference %g scaled diff %g => %g\n",iColumn,difference, // scaledDifference,difference*columnScale[iColumn]); } double value = smallest * columnScale[iColumn]; if (overallSmallest > value) overallSmallest = value; //overallSmallest = CoinMin(overallSmallest,smallest*columnScale[iColumn]); } else { assert(columnScale[iColumn] == 1.0); //columnScale[iColumn]=1.0; } } for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) { if (!usedRow[iRow]) { rowScale[iRow] = 1.0; } } } if (!inBranchAndBound) model_->messageHandler()->message(CLP_PACKEDSCALE_FINAL, *model_->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; if (overallSmallest < 1.0e-13) { // Change factorization zero tolerance double newTolerance = CoinMax(1.0e-15 * (overallSmallest / 1.0e-13), 1.0e-18); if (model_->factorization()->zeroTolerance() > newTolerance) model_->factorization()->zeroTolerance(newTolerance); newTolerance = CoinMax(overallSmallest * 0.5, 1.0e-18); model_->setZeroTolerance(newTolerance); #ifndef NDEBUG assert (newTolerance<0.0); // just so we can fix #endif } // make copy (could do faster by using previous values) // could just do partial CoinAbcReciprocal(inverseRowScale+numberAlreadyScaled,numberRows-numberAlreadyScaled, rowScale+numberAlreadyScaled); if (!numberAlreadyScaled) CoinAbcReciprocal(inverseColumnScale,numberColumns,columnScale); // Do scaled copy //NO and move largest to start CoinBigIndex start = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double scale=columnScale[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; for (CoinBigIndex j = start; j < end; j++) { double value=elementByColumn[j]; int iRow = row[j]; if (iRow>=numberAlreadyScaled) { value*= scale*rowScale[iRow]; elementByColumn[j]= value; } } start=end; } delete rowCopy; #if 0 if (model_->rowCopy()) { // need to replace row by row CoinPackedMatrix * rowCopy = NULL; //static_cast< AbcMatrix*>(model_->rowCopy()); double * element = rowCopy->getMutableElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); // scale row copy for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; double scale = rowScale[iRow]; double * elementsInThisRow = element + rowStart[iRow]; const int * columnsInThisRow = column + rowStart[iRow]; int number = rowStart[iRow+1] - rowStart[iRow]; assert (number <= numberColumns); for (j = 0; j < number; j++) { int iColumn = columnsInThisRow[j]; elementsInThisRow[j] *= scale * columnScale[iColumn]; } } } #endif model_->clearArraysPublic(whichArray); } /* Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ //scaled versions void AbcMatrix::timesModifyExcludingSlacks(double scalar, const double * x, double * y) const { int numberTotal = model_->numberTotal(); int maximumRows = model_->maximumAbcNumberRows(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) { double value = x[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; value *= scalar; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; y[iRow] += value * elementByColumn[j]; } } } } /* Return y + A * scalar(+-1) *x in y. @pre x must be of size numColumns()+numRows() @pre y must be of size numRows() */ void AbcMatrix::timesModifyIncludingSlacks(double scalar, const double * x, double * y) const { int numberRows=model_->numberRows(); int numberTotal = model_->numberTotal(); int maximumRows = model_->maximumAbcNumberRows(); // makes no sense for x==y?? assert (x!=y); // For now just by column and assumes already scaled (use reallyScale) // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); if (scalar==1.0) { // add if (x!=y) { for (int i=0;i in y. @pre x must be of size numColumns()+numRows() @pre y must be of size numRows() */ void AbcMatrix::timesIncludingSlacks(double scalar, const double * x, double * y) const { int numberRows=model_->numberRows(); int numberTotal = model_->numberTotal(); int maximumRows = model_->maximumAbcNumberRows(); // For now just by column and assumes already scaled (use reallyScale) // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); if (scalar==1.0) { // add if (x!=y) { for (int i=0;idjRegion(); const unsigned char * COIN_RESTRICT internalStatus = model->internalStatus(); // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = model->currentAcceptablePivot(); double dualT=-model->currentDualTolerance(); // fixed will have been taken out by now const double multiplier[] = { 1.0, -1.0}; freeSequence=-1; int firstIn=model->abcMatrix()->blockStart(iBlock); int numberNonZero=tableauRow.getNumElements(iBlock)+firstIn; int numberRemaining=firstIn; //first=tableauRow.getNumElements(); // could pass in last and if numberNonZero==last-firstIn scan as well if (model->ordinaryVariables()) { for (int i = firstIn; i < numberNonZero; i++) { int iSequence = index[i]; double tableauValue=array[i]; unsigned char iStatus=internalStatus[iSequence]&7; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } else { double badFree = 0.0; double freeAlpha = model->currentAcceptablePivot(); int freeSequenceIn=model->freeSequenceIn(); double currentDualTolerance = model->currentDualTolerance(); for (int i = firstIn; i < numberNonZero; i++) { int iSequence = index[i]; double tableauValue=array[i]; unsigned char iStatus=internalStatus[iSequence]&7; if ((iStatus&4)==0) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } if (keep) { #ifdef PAN if (model->fakeSuperBasic(iSequence)>=0) { #endif if (iSequence==freeSequenceIn) tableauValue=COIN_DBL_MAX; // free - choose largest if (fabs(tableauValue) > fabs(freeAlpha)) { freeAlpha = tableauValue; freeSequence = iSequence; } #ifdef PAN } #endif } } } } //firstInX=numberNonZero-firstIn; //lastInX=-1;//numberRemaining-lastInX; tableauRow.setNumElementsPartition(iBlock,numberNonZero-firstIn); candidateList.setNumElementsPartition(iBlock,numberRemaining-firstIn); return upperTheta; } // gets sorted tableau row and a possible value of theta double AbcMatrix::dualColumn1Row(int iBlock, double upperTheta, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const { int maximumRows = model_->maximumAbcNumberRows(); int number=update.getNumElements(); const double * COIN_RESTRICT pi=update.denseVector(); const int * COIN_RESTRICT piIndex = update.getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_; int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows*numberRowBlocks_; // count down int nColumns; int firstIn=blockStart_[iBlock]; int first=firstIn; if (!first) first=maximumRows; int last=blockStart_[iBlock+1]; nColumns=last-first; int target=nColumns; rowStart += iBlock*numberRows; rowEnd = rowStart+numberRows; for (int i=0;i0) { //printf("going to few %d ops %d\n",number,nColumns-target); return dualColumn1RowFew(iBlock, upperTheta, freeSequence, update, tableauRow, candidateList); } const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; for (int i=0;i=first&&iColumn(model_)->dualColumn1A(); numberNonZero=tableauRow.getNumElements(0); numberRemaining=candidateList.getNumElements(0); #else numberNonZero=0; for (int i=0;idjRegion(); // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = model_->currentAcceptablePivot(); double dualT=-model_->currentDualTolerance(); const double multiplier[] = { 1.0, -1.0}; double zeroTolerance = model_->zeroTolerance(); freeSequence=-1; if (model_->ordinaryVariables()) { for (int iSequence = first; iSequence < last; iSequence++) { double tableauValue=array[iSequence]; if (tableauValue) { array[iSequence]=0.0; if (fabs(tableauValue)>zeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } } } } else { double badFree = 0.0; double freeAlpha = model_->currentAcceptablePivot(); int freeSequenceIn=model_->freeSequenceIn(); //printf("block %d freeSequence %d acceptable %g\n",iBlock,freeSequenceIn,freeAlpha); double currentDualTolerance = model_->currentDualTolerance(); for (int iSequence = first; iSequence < last; iSequence++) { double tableauValue=array[iSequence]; if (tableauValue) { array[iSequence]=0.0; if (fabs(tableauValue)>zeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { if ((iStatus&4)==0) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; // may be fake super basic if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } #if 0 if (iSequence==freeSequenceIn) assert (keep); #endif if (keep) { #ifdef PAN if (model_->fakeSuperBasic(iSequence)>=0) { #endif if (iSequence==freeSequenceIn) tableauValue=COIN_DBL_MAX; // free - choose largest if (fabs(tableauValue) > fabs(freeAlpha)) { freeAlpha = tableauValue; freeSequence = iSequence; } #ifdef PAN } #endif } } } } } } } #if 0 if (model_->freeSequenceIn()>=first&&model_->freeSequenceIn()freeSequenceIn()); extern int xxInfo[6][8]; xxInfo[0][iBlock]=first; xxInfo[1][iBlock]=last; xxInfo[2][iBlock]=firstIn; xxInfo[3][iBlock]=numberNonZero-firstIn; xxInfo[4][iBlock]=numberRemaining-firstIn; #endif tableauRow.setNumElementsPartition(iBlock,numberNonZero-firstIn); candidateList.setNumElementsPartition(iBlock,numberRemaining-firstIn); return upperTheta; } // gets sorted tableau row and a possible value of theta double AbcMatrix::dualColumn1Row2(double upperTheta, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const { //int first=model_->maximumAbcNumberRows(); assert(update.getNumElements()==2); const double * COIN_RESTRICT pi=update.denseVector(); const int * COIN_RESTRICT piIndex = update.getIndices(); int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_; int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows*numberRowBlocks_; const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; int iRow0 = piIndex[0]; int iRow1 = piIndex[1]; CoinBigIndex end0 = rowEnd[iRow0]; CoinBigIndex end1 = rowEnd[iRow1]; if (end0-rowStart[iRow0]>end1-rowStart[iRow1]) { int temp=iRow0; iRow0=iRow1; iRow1=temp; } CoinBigIndex start = rowStart[iRow0]; CoinBigIndex end = rowEnd[iRow0]; double piValue = pi[iRow0]; double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); int numberNonZero; numberNonZero=tableauRow.getNumElements(0); int n=numberNonZero; for (CoinBigIndex j=start;jinternalStatus(); double zeroTolerance = model_->zeroTolerance(); while (numberNonZerozeroTolerance&&iStatus<6) { index[numberNonZero]=iSequence; array[numberNonZero++]=value; } else { // kill n--; index[numberNonZero]=index[n]; } } tableauRow.setNumElementsPartition(0,numberNonZero); return firstPass(model_,0, upperTheta, freeSequence, tableauRow, candidateList) ; } //static int ixxxxxx=1; // gets sorted tableau row and a possible value of theta double AbcMatrix::dualColumn1RowFew(int iBlock, double upperTheta, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const { //int first=model_->maximumAbcNumberRows(); int number = update.getNumElements(); const double * COIN_RESTRICT pi=update.denseVector(); const int * COIN_RESTRICT piIndex = update.getIndices(); int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_; int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows*numberRowBlocks_; const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); int numberNonZero; assert (iBlock>=0); const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); int firstIn=blockStart_[iBlock]; if (iBlock==0) { numberNonZero=0; for (int i=0;izeroTolerance(); while (numberNonZerozeroTolerance&&iStatus<6) { index[numberNonZero]=iSequence; array[numberNonZero++]=value; } else { // kill n--; index[numberNonZero]=index[n]; } } tableauRow.setNumElementsPartition(iBlock,numberNonZero-firstIn); upperTheta = firstPass(model_,iBlock, upperTheta, freeSequence, tableauRow, candidateList) ; return upperTheta; } // gets sorted tableau row and a possible value of theta double AbcMatrix::dualColumn1Row1(double upperTheta, int & freeSequence, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow, CoinPartitionedVector & candidateList) const { assert(update.getNumElements()==1); int iRow = update.getIndices()[0]; double piValue = update.denseVector()[iRow]; int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_; int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows*numberRowBlocks_; CoinBigIndex start = rowStart[iRow]; CoinBigIndex end = rowEnd[iRow]; const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; int numberNonZero; int numberRemaining; numberNonZero=tableauRow.getNumElements(0); numberRemaining = candidateList.getNumElements(0); double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); int * COIN_RESTRICT indexCandidate = candidateList.getIndices(); const double * COIN_RESTRICT abcDj = model_->djRegion(); const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = model_->currentAcceptablePivot(); double dualT=-model_->currentDualTolerance(); const double multiplier[] = { 1.0, -1.0}; double zeroTolerance = model_->zeroTolerance(); freeSequence=-1; if (model_->ordinaryVariables()) { for (CoinBigIndex j=start;jzeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } } } else { double badFree = 0.0; double freeAlpha = model_->currentAcceptablePivot(); int freeSequenceIn=model_->freeSequenceIn(); double currentDualTolerance = model_->currentDualTolerance(); for (CoinBigIndex j=start;jzeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { if ((iStatus&4)==0) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } if (keep) { #ifdef PAN if (model_->fakeSuperBasic(iSequence)>=0) { #endif if (iSequence==freeSequenceIn) tableauValue=COIN_DBL_MAX; // free - choose largest if (fabs(tableauValue) > fabs(freeAlpha)) { freeAlpha = tableauValue; freeSequence = iSequence; } #ifdef PAN } #endif } } } } } } tableauRow.setNumElementsPartition(0,numberNonZero); candidateList.setNumElementsPartition(0,numberRemaining); return upperTheta; } //#define PARALLEL2 #ifdef PARALLEL2 #undef cilk_for #undef cilk_spawn #undef cilk_sync #include #include #endif #if 0 static void compact(int numberBlocks,CoinIndexedVector * vector,const int * starts,const int * lengths) { int numberNonZeroIn=vector->getNumElements(); int * index = vector->getIndices(); double * array = vector->denseVector(); CoinAbcCompact(numberBlocks,numberNonZeroIn, array,starts,lengths); int numberNonZero = CoinAbcCompact(numberBlocks,numberNonZeroIn, index,starts,lengths); vector->setNumElements(numberNonZero); } static void compactBoth(int numberBlocks,CoinIndexedVector * vector1,CoinIndexedVector * vector2, const int * starts,const int * lengths1, const int * lengths2) { cilk_spawn compact(numberBlocks,vector1,starts,lengths1); compact(numberBlocks,vector2,starts,lengths2); cilk_sync; } #endif void AbcMatrix::rebalance() const { int maximumRows = model_->maximumAbcNumberRows(); int numberTotal = model_->numberTotal(); /* rebalance For non-vector version each basic etc column is 1 each real column is 5+2*nel each basic slack is 0 each real slack is 3 */ #if ABC_PARALLEL int howOften=CoinMax(model_->factorization()->maximumPivots(),200); if ((model_->numberIterations()%howOften)==0||!startColumnBlock_[1]) { int numberCpus=model_->numberCpus(); if (numberCpus>1) { const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); int numberRows=model_->numberRows(); int total=0; for (int iSequence=0;iSequencechunk) { iCpu++; total=0; startColumnBlock_[iCpu]=iSequence; } } assert(iCpunumberTotal(); // rebalance rebalance(); tableauRow.setPackedMode(true); candidateList.setPackedMode(true); int number=update.getNumElements(); double upperTheta; if (rowStart_&&number<3) { #if ABC_INSTRUMENT>1 { int n=update.getNumElements(); abcPricing[n<19 ? n : 19]++; } #endif // always do serially // do slacks first int starts[2]; starts[0]=0; starts[1]=numberTotal; tableauRow.setPartitions(1,starts); candidateList.setPartitions(1,starts); upperTheta = static_cast(model_)->dualColumn1A(); //assert (upperTheta>-100*model_->dualTolerance()||model_->sequenceIn()>=0||model_->lastFirstFree()>=0); int freeSequence=-1; // worth using row copy assert (number); if (number==2) { upperTheta=dualColumn1Row2(upperTheta,freeSequence,update,tableauRow,candidateList); } else { upperTheta=dualColumn1Row1(upperTheta,freeSequence,update,tableauRow,candidateList); } if (freeSequence>=0) { int numberNonZero=tableauRow.getNumElements(0); const int * COIN_RESTRICT index = tableauRow.getIndices(); const double * COIN_RESTRICT array = tableauRow.denseVector(); // search for free coming in double freeAlpha=0.0; int bestSequence=model_->sequenceIn(); if (bestSequence>=0) freeAlpha=model_->alpha(); index = tableauRow.getIndices(); array = tableauRow.denseVector(); // free variable - search for (int k=0;ksequenceIn()<0||fabs(freeAlpha)>fabs(model_->alpha())) { double oldValue = model_->djRegion()[freeSequence]; model_->setSequenceIn(freeSequence); model_->setAlpha(freeAlpha); model_->setTheta(oldValue / freeAlpha); } } } else { // three or more // need to do better job on dividing up (but wait until vector or by row) upperTheta = parallelDual4(static_cast(model_)); } //tableauRow.compact(); //candidateList.compact(); #if 0 //ndef NDEBUG model_->checkArrays(); #endif candidateList.computeNumberElements(); int numberRemaining=candidateList.getNumElements(); if (!numberRemaining&&model_->sequenceIn()<0) { return COIN_DBL_MAX; // Looks infeasible } else { return upperTheta; } } #define _mm256_broadcast_sd(x) static_cast<__m256d> (__builtin_ia32_vbroadcastsd256 (x)) #define _mm256_load_pd(x) *(__m256d *)(x) #define _mm256_store_pd (s, x) *((__m256d *)s)=x void AbcMatrix::dualColumn1Part(int iBlock, int & sequenceIn, double & upperThetaResult, const CoinIndexedVector & update, CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const { double upperTheta=upperThetaResult; #if 0 double time0=CoinCpuTime(); #endif int maximumRows = model_->maximumAbcNumberRows(); int firstIn=startColumnBlock_[iBlock]; int last = startColumnBlock_[iBlock+1]; int numberNonZero; int numberRemaining; int first; if (firstIn==0) { upperTheta=static_cast(model_)->dualColumn1A(); numberNonZero=tableauRow.getNumElements(0); numberRemaining = candidateList.getNumElements(0); first=maximumRows; } else { first=firstIn; numberNonZero=first; numberRemaining=first; } sequenceIn=-1; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT pi=update.denseVector(); //const int * COIN_RESTRICT piIndex = update.getIndices(); int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); // pivot elements double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); // indices int * COIN_RESTRICT indexCandidate = candidateList.getIndices(); const double * COIN_RESTRICT abcDj = model_->djRegion(); const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = model_->currentAcceptablePivot(); double dualT=-model_->currentDualTolerance(); const double multiplier[] = { 1.0, -1.0}; double zeroTolerance = model_->zeroTolerance(); if (model_->ordinaryVariables()) { #ifdef COUNT_COPY if (first>maximumRows||lastnumberTotal()||false) { #endif #if 1 for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += pi[jRow] * elementByColumn[j]; } if (fabs(tableauValue)>zeroTolerance) { #else cilk_for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += pi[jRow] * elementByColumn[j]; } array[iSequence]=tableauValue; } } //printf("time %.6g\n",CoinCpuTime()-time0); for (int iSequence = first; iSequence < last; iSequence++) { double tableauValue=array[iSequence]; if (tableauValue) { array[iSequence]=0.0; if (fabs(tableauValue)>zeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; #endif index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } } #ifdef COUNT_COPY } else { const double * COIN_RESTRICT element = countElement_; const int * COIN_RESTRICT row = countRow_; double temp[4] __attribute__ ((aligned (32))); memset(temp,0,sizeof(temp)); for (int iCount=smallestCount_;iCount>2; number &= 3; for (int iBlock=0;iBlockzeroTolerance) { int iSequence=sequence[0]; unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue0; double mult = multiplier[iStatus]; double alpha = tableauValue0 * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } if (fabs(tableauValue1)>zeroTolerance) { int iSequence=sequence[1]; unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue1; double mult = multiplier[iStatus]; double alpha = tableauValue1 * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } if (fabs(tableauValue2)>zeroTolerance) { int iSequence=sequence[2]; unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue2; double mult = multiplier[iStatus]; double alpha = tableauValue2 * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } if (fabs(tableauValue3)>zeroTolerance) { int iSequence=sequence[3]; unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<4) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue3; double mult = multiplier[iStatus]; double alpha = tableauValue3 * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } sequence+=4; } for (int i=0;izeroTolerance) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } blockRow++; blockElement++; } } int numberColumns=model_->numberColumns(); // large ones const CoinBigIndex * COIN_RESTRICT largeStart = countStartLarge_-countFirst_[MAX_COUNT]; for (int i=countFirst_[MAX_COUNT];izeroTolerance) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } } } #endif } else { double badFree = 0.0; double freePivot = model_->currentAcceptablePivot(); int freeSequenceIn=model_->freeSequenceIn(); double currentDualTolerance = model_->currentDualTolerance(); for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += pi[jRow] * elementByColumn[j]; } if (fabs(tableauValue)>zeroTolerance) { if ((iStatus&4)==0) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } if (keep) { #ifdef PAN if (model_->fakeSuperBasic(iSequence)>=0) { #endif if (iSequence==freeSequenceIn) tableauValue=COIN_DBL_MAX; // free - choose largest if (fabs(tableauValue) > fabs(freePivot)) { freePivot = tableauValue; sequenceIn = iSequence; } #ifdef PAN } #endif } } } } } } // adjust numberNonZero -= firstIn; numberRemaining -= firstIn; tableauRow.setNumElementsPartition(iBlock,numberNonZero); candidateList.setNumElementsPartition(iBlock,numberRemaining); if (!numberRemaining&&model_->sequenceIn()<0) { upperThetaResult=COIN_DBL_MAX; // Looks infeasible } else { upperThetaResult=upperTheta; } } // gets tableau row - returns number of slacks in block int AbcMatrix::primalColumnRow(int iBlock,bool doByRow,const CoinIndexedVector & updates, CoinPartitionedVector & tableauRow) const { int maximumRows = model_->maximumAbcNumberRows(); int first=tableauRow.startPartition(iBlock); int last=tableauRow.startPartition(iBlock+1); if (doByRow) { assert(first==blockStart_[iBlock]); assert(last==blockStart_[iBlock+1]); } else { assert(first==startColumnBlock_[iBlock]); assert(last==startColumnBlock_[iBlock+1]); } int numberSlacks=updates.getNumElements(); int numberNonZero=0; const double * COIN_RESTRICT pi=updates.denseVector(); const int * COIN_RESTRICT piIndex = updates.getIndices(); int * COIN_RESTRICT index = tableauRow.getIndices()+first; double * COIN_RESTRICT array = tableauRow.denseVector()+first; const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); if (!iBlock) { numberNonZero=numberSlacks; for (int i=0;izeroTolerance(); if (doByRow) { int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_+iBlock*numberRows; const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows; const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; if (numberSlacks>1) { double * COIN_RESTRICT arrayTemp = tableauRow.denseVector(); for (int i=0;izeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; } } } } } else { int iRow=piIndex[0]; double piValue = pi[iRow]; CoinBigIndex end = rowEnd[iRow]; for (CoinBigIndex j=rowStart[iRow];jzeroTolerance) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; } } } } } else { // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT pi=updates.denseVector(); for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += pi[jRow] * elementByColumn[j]; } if (fabs(tableauValue)>zeroTolerance) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; } } } } tableauRow.setNumElementsPartition(iBlock,numberNonZero); return numberSlacks; } // Get sequenceIn when Dantzig int AbcMatrix::pivotColumnDantzig(const CoinIndexedVector & updates, CoinPartitionedVector & spare) const { int maximumRows = model_->maximumAbcNumberRows(); // rebalance rebalance(); spare.setPackedMode(true); bool useRowCopy=false; if (rowStart_) { // see if worth using row copy int number=updates.getNumElements(); assert (number); useRowCopy = (number<<2)numberCpus()); #else #define NUMBER_BLOCKS 1 int numberBlocks=NUMBER_BLOCKS; #endif #if ABC_PARALLEL if (model_->parallelMode()==0) numberBlocks=1; #endif spare.setPartitions(numberBlocks,starts); int which[NUMBER_BLOCKS]; double best[NUMBER_BLOCKS]; for (int i=0;idualTolerance(); for (int i=0;ibestValue) { bestValue=best[i]; bestSequence=which[i]; } } return bestSequence; } // Get sequenceIn when Dantzig (One block) int AbcMatrix::pivotColumnDantzig(int iBlock, bool doByRow,const CoinIndexedVector & updates, CoinPartitionedVector & spare, double & bestValue) const { // could rewrite to do more directly int numberSlacks=primalColumnRow(iBlock,doByRow,updates,spare); double * COIN_RESTRICT reducedCost = model_->djRegion(); int first=spare.startPartition(iBlock); int last=spare.startPartition(iBlock+1); int * COIN_RESTRICT index = spare.getIndices()+first; double * COIN_RESTRICT array = spare.denseVector()+first; int numberNonZero=spare.getNumElements(iBlock); int bestSequence=-1; double bestDj=model_->dualTolerance(); double bestFreeDj = model_->dualTolerance(); int bestFreeSequence = -1; // redo LOTS so signs for slacks and columns same if (!first) { first = model_->maximumAbcNumberRows(); for (int i=0;inumberRows(); for (int iSequence=0 ; iSequence < numberRows; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence] * CLP_PRIMAL_SLACK_MULTIPLIER; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case AbcSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case AbcSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } } for (int i=numberSlacks;iflagged(iSequence)) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case AbcSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case AbcSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } spare.setNumElementsPartition(iBlock,0); // bias towards free if (bestFreeSequence >= 0 && bestFreeDj > 0.1 * bestDj) { bestSequence = bestFreeSequence; bestDj=10.0*bestFreeDj; } bestValue=bestDj; return bestSequence; } // gets tableau row and dj row - returns number of slacks in block int AbcMatrix::primalColumnRowAndDjs(int iBlock,const CoinIndexedVector & updateTableau, const CoinIndexedVector & updateDjs, CoinPartitionedVector & tableauRow) const { int maximumRows = model_->maximumAbcNumberRows(); int first=tableauRow.startPartition(iBlock); int last=tableauRow.startPartition(iBlock+1); assert(first==startColumnBlock_[iBlock]); assert(last==startColumnBlock_[iBlock+1]); int numberSlacks=updateTableau.getNumElements(); int numberNonZero=0; const double * COIN_RESTRICT piTableau=updateTableau.denseVector(); const double * COIN_RESTRICT pi=updateDjs.denseVector(); int * COIN_RESTRICT index = tableauRow.getIndices()+first; double * COIN_RESTRICT array = tableauRow.denseVector()+first; const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); double * COIN_RESTRICT reducedCost = model_->djRegion(); if (!iBlock) { const int * COIN_RESTRICT piIndexTableau = updateTableau.getIndices(); numberNonZero=numberSlacks; for (int i=0;izeroTolerance(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; double djValue=reducedCost[iSequence]; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += piTableau[jRow] * elementByColumn[j]; djValue -= pi[jRow] * elementByColumn[j]; // sign? } reducedCost[iSequence]=djValue; if (fabs(tableauValue)>zeroTolerance) { index[numberNonZero]=iSequence; array[numberNonZero++]=tableauValue; } } } tableauRow.setNumElementsPartition(iBlock,numberNonZero); return numberSlacks; } /* does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs */ int AbcMatrix::primalColumnDouble(int iBlock,CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, double * infeasibilities, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const { int maximumRows = model_->maximumAbcNumberRows(); int first=startColumnBlock_[iBlock]; int last=startColumnBlock_[iBlock+1]; const double * COIN_RESTRICT piTableau=updateForTableauRow.denseVector(); const double * COIN_RESTRICT pi=updateForDjs.denseVector(); const double * COIN_RESTRICT piWeights=updateForWeights.denseVector(); const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); double * COIN_RESTRICT reducedCost = model_->djRegion(); double tolerance = model_->currentDualTolerance(); // use spareColumn to track new infeasibilities int * COIN_RESTRICT newInfeas = spareColumn1.getIndices()+first; int numberNewInfeas=0; // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; double mult[2]={1.0,-1.0}; bool updateWeights=devex!=0.0; #define isReference(i) (((reference[i>>5] >> (i & 31)) & 1) != 0) // Scale factor is other way round so tableau row is 1.0* while dj update is scaleFactor* if (!iBlock) { int numberSlacks=updateForTableauRow.getNumElements(); const int * COIN_RESTRICT piIndexTableau = updateForTableauRow.getIndices(); if (!scaleFactor) { const int * COIN_RESTRICT piIndex = updateForDjs.getIndices(); int number=updateForDjs.getNumElements(); for (int i=0;izeroTolerance(); double freeTolerance = FREE_ACCEPT * tolerance;; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); bool updateDjs=scaleFactor!=COIN_DBL_MAX; for (int iSequence = first; iSequence < last; iSequence++) { unsigned char iStatus=internalStatus[iSequence]&7; if (iStatus<6) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double tableauValue = 0.0; double djValue=reducedCost[iSequence]; if (!scaleFactor) { for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += piTableau[jRow] * elementByColumn[j]; djValue += pi[jRow] * elementByColumn[j]; } } else { for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; tableauValue += piTableau[jRow] * elementByColumn[j]; } djValue += tableauValue*scaleFactor; // sign? } if (updateDjs) { reducedCost[iSequence]=djValue; if (iStatus<4) { djValue *= mult[iStatus]; if (djValue<0.0) { if (!infeasibilities[iSequence]) newInfeas[numberNewInfeas++]=iSequence; infeasibilities[iSequence]=djValue*djValue; } else { if (infeasibilities[iSequence]) infeasibilities[iSequence]=COIN_INDEXED_REALLY_TINY_ELEMENT; } } else { if (fabs(djValue) > freeTolerance) { // we are going to bias towards free (but only if reasonable) djValue *= FREE_BIAS; if (!infeasibilities[iSequence]) newInfeas[numberNewInfeas++]=iSequence; // store square in list infeasibilities[iSequence] = djValue * djValue; } else { if (infeasibilities[iSequence]) infeasibilities[iSequence]=COIN_INDEXED_REALLY_TINY_ELEMENT; } } } if (fabs(tableauValue)>zeroTolerance&&updateWeights) { double modification=0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; modification += piWeights[jRow] * elementByColumn[j]; } double thisWeight = weights[iSequence]; double pivot = tableauValue; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex - pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (isReference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iSequence] = thisWeight; } } } spareColumn1.setTempNumElementsPartition(iBlock,numberNewInfeas); int bestSequence=-1; #if 0 if (!iBlock) first=0; // not at present - maybe later double bestDj=tolerance*tolerance; for (int iSequence=first;iSequencebestDj*weights[iSequence]) { int iStatus=internalStatus[iSequence]&7; assert (iStatus<6); bestSequence=iSequence; bestDj=infeasibilities[iSequence]/weights[iSequence]; } } #endif return bestSequence; } /* does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs */ int AbcMatrix::primalColumnSparseDouble(int iBlock,CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, double * infeasibilities, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const { int maximumRows = model_->maximumAbcNumberRows(); int first=blockStart_[iBlock]; //int last=blockStart_[iBlock+1]; const double * COIN_RESTRICT piTableau=updateForTableauRow.denseVector(); //const double * COIN_RESTRICT pi=updateForDjs.denseVector(); const double * COIN_RESTRICT piWeights=updateForWeights.denseVector(); const unsigned char * COIN_RESTRICT internalStatus = model_->internalStatus(); double * COIN_RESTRICT reducedCost = model_->djRegion(); double tolerance = model_->currentDualTolerance(); // use spareColumn to track new infeasibilities int * COIN_RESTRICT newInfeas = spareColumn1.getIndices()+first; int numberNewInfeas=0; // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; double mult[2]={1.0,-1.0}; bool updateWeights=devex!=0.0; int numberSlacks=updateForTableauRow.getNumElements(); const int * COIN_RESTRICT piIndexTableau = updateForTableauRow.getIndices(); #define isReference(i) (((reference[i>>5] >> (i & 31)) & 1) != 0) // Scale factor is other way round so tableau row is 1.0* while dj update is scaleFactor* assert (scaleFactor); if (!iBlock) { if (scaleFactor!=COIN_DBL_MAX) { for (int i=0;izeroTolerance(); double freeTolerance = FREE_ACCEPT * tolerance;; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); // get tableau row int * COIN_RESTRICT index = updateForTableauRow.getIndices()+first; double * COIN_RESTRICT array = updateForTableauRow.denseVector(); int numberRows=model_->numberRows(); const CoinBigIndex * COIN_RESTRICT rowStart = rowStart_+iBlock*numberRows; const CoinBigIndex * COIN_RESTRICT rowEnd = rowStart+numberRows; const double * COIN_RESTRICT element = element_; const int * COIN_RESTRICT column = column_; int numberInRow=0; if (numberSlacks>2) { for (int i=0;iend1-rowStart[iRow1]) { int temp=iRow0; iRow0=iRow1; iRow1=temp; } CoinBigIndex start = rowStart[iRow0]; CoinBigIndex end = rowEnd[iRow0]; double piValue = piTableau[iRow0]; for (CoinBigIndex j=start;j freeTolerance) { // we are going to bias towards free (but only if reasonable) djValue *= FREE_BIAS; if (!infeasibilities[iSequence]) newInfeas[numberNewInfeas++]=iSequence; // store square in list infeasibilities[iSequence] = djValue * djValue; } else { if (infeasibilities[iSequence]) infeasibilities[iSequence]=COIN_INDEXED_REALLY_TINY_ELEMENT; } } } if (fabs(tableauValue)>zeroTolerance&&updateWeights) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double modification=0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; modification += piWeights[jRow] * elementByColumn[j]; } double thisWeight = weights[iSequence]; double pivot = tableauValue; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex - pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (isReference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iSequence] = thisWeight; } } else { array[iSequence]=0.0; } } spareColumn1.setTempNumElementsPartition(iBlock,numberNewInfeas); int bestSequence=-1; #if 0 if (!iBlock) first=0; // not at present - maybe later double bestDj=tolerance*tolerance; for (int iSequence=first;iSequencebestDj*weights[iSequence]) { int iStatus=internalStatus[iSequence]&7; assert (iStatus<6); bestSequence=iSequence; bestDj=infeasibilities[iSequence]/weights[iSequence]; } } #endif return bestSequence; } #if 0 /* Chooses best weighted dj */ int AbcMatrix::chooseBestDj(int iBlock,const CoinIndexedVector & infeasibilities, const double * weights) const { return 0; } #endif /* does steepest edge double or triple update If scaleFactor!=0 then use with tableau row to update djs otherwise use updateForDjs Returns best */ int AbcMatrix::primalColumnDouble(CoinPartitionedVector & updateForTableauRow, CoinPartitionedVector & updateForDjs, const CoinIndexedVector & updateForWeights, CoinPartitionedVector & spareColumn1, CoinIndexedVector & infeasible, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) const { //int maximumRows = model_->maximumAbcNumberRows(); // rebalance rebalance(); #ifdef PRICE_IN_ABC_MATRIX int which[NUMBER_BLOCKS]; #endif double * infeasibilities=infeasible.denseVector(); int bestSequence=-1; // see if worth using row copy int maximumRows=model_->maximumAbcNumberRows(); int number=updateForTableauRow.getNumElements(); assert (number); bool useRowCopy = (gotRowCopy()&&(number<<2)dualTolerance(); int sequenceIn[8]={-1,-1,-1,-1,-1,-1,-1,-1}; #endif assert (numberColumnBlocks_<=8); #ifdef PRICE_IN_ABC_MATRIX double weightedDj[8]; int nPossible=0; #endif //const double * reducedCost = model_->djRegion(); // use spareColumn to track new infeasibilities int numberInfeas=infeasible.getNumElements(); int * COIN_RESTRICT infeas = infeasible.getIndices(); const int * COIN_RESTRICT newInfeasAll = spareColumn1.getIndices(); for (int i=0;i=0) { int iSequence=which[i]; double value=fabs(infeasibilities[iSequence]/weights[iSequence]); if (value>bestValue) { bestValue=value; bestSequence=which[i]; } weightedDj[nPossible]=-value; sequenceIn[nPossible++]=iSequence; } #endif } infeasible.setNumElements(numberInfeas); #ifdef PRICE_IN_ABC_MATRIX CoinSort_2(weightedDj,weightedDj+nPossible,sequenceIn); //model_->setMultipleSequenceIn(sequenceIn); #endif return bestSequence; } // Partial pricing void AbcMatrix::partialPricing(double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; int maximumRows = model_->maximumAbcNumberRows(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); int numberColumns=model_->numberColumns(); int start = static_cast (startFraction * numberColumns); int end = CoinMin(static_cast (endFraction * numberColumns + 1), numberColumns); // adjust start += maximumRows; end += maximumRows; double tolerance = model_->currentDualTolerance(); double * reducedCost = model_->djRegion(); const double * duals = model_->dualRowSolution(); const double * cost = model_->costRegion(); double bestDj; if (bestSequence >= 0) bestDj = fabs(reducedCost[bestSequence]); else bestDj = tolerance; int sequenceOut = model_->sequenceOut(); int saveSequence = bestSequence; int lastScan = minimumObjectsScan_ < 0 ? end : start + minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ == -1 ? numberWanted : minimumGoodReducedCosts_; for (int iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: value = cost[iSequence]; for (CoinBigIndex j = columnStart[iSequence]; j < columnStart[iSequence+1]; j++) { int jRow = row[j]; value -= duals[jRow] * elementByColumn[j]; } value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case AbcSimplex::atUpperBound: value = cost[iSequence]; // scaled for (CoinBigIndex j = columnStart[iSequence]; j < columnStart[iSequence+1]; j++) { int jRow = row[j]; value -= duals[jRow] * elementByColumn[j]; } if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case AbcSimplex::atLowerBound: value = cost[iSequence]; for (CoinBigIndex j = columnStart[iSequence]; j < columnStart[iSequence+1]; j++) { int jRow = row[j]; value -= duals[jRow] * elementByColumn[j]; } value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (numberWanted + minNeg < originalWanted_ && iSequence > lastScan) { // give up break; } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = cost[bestSequence]; for (CoinBigIndex j = columnStart[bestSequence]; j < columnStart[bestSequence+1]; j++) { int jRow = row[j]; value -= duals[jRow] * elementByColumn[j]; } reducedCost[bestSequence] = value; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } currentWanted_ = numberWanted; } /* Return x *A in z but just for indices Already in z. Note - z always packed mode */ void AbcMatrix::subsetTransposeTimes(const CoinIndexedVector & x, CoinIndexedVector & z) const { int maximumRows = model_->maximumAbcNumberRows(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT other=x.denseVector(); int numberNonZero = z.getNumElements(); int * COIN_RESTRICT index = z.getIndices(); double * COIN_RESTRICT array = z.denseVector(); int numberRows=model_->numberRows(); for (int i=0;i=numberRows) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; double value = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; value -= other[jRow] * elementByColumn[j]; } array[i]=value; } else { array[i]=-other[iSequence]; } } } // Return -x *A in z void AbcMatrix::transposeTimes(const CoinIndexedVector & x, CoinIndexedVector & z) const { int maximumRows = model_->maximumAbcNumberRows(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT other=x.denseVector(); int numberNonZero = 0; int * COIN_RESTRICT index = z.getIndices(); double * COIN_RESTRICT array = z.denseVector(); int numberColumns=model_->numberColumns(); double zeroTolerance=model_->zeroTolerance(); for (int iSequence=maximumRows;iSequencezeroTolerance) { // TEMP array[iSequence-maximumRows]=value; index[numberNonZero++]=iSequence-maximumRows; } } z.setNumElements(numberNonZero); } /* Return A * scalar(+-1) *x + y in y. @pre x must be of size numRows() @pre y must be of size numRows()+numColumns() */ void AbcMatrix::transposeTimesNonBasic(double scalar, const double * pi, double * y) const { int numberTotal = model_->numberTotal(); int maximumRows = model_->maximumAbcNumberRows(); assert (scalar==-1.0); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); int numberRows=model_->numberRows(); const unsigned char * COIN_RESTRICT status=model_->internalStatus(); for (int i=0;i in y. @pre x must be of size numRows() @pre y must be of size numRows()+numColumns() */ void AbcMatrix::transposeTimesAll(const double * pi, double * y) const { int numberTotal = model_->numberTotal(); int maximumRows = model_->maximumAbcNumberRows(); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-maximumRows; const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); int numberRows=model_->numberRows(); for (int i=0;i in y. @pre x must be of size numRows() @pre y must be of size numRows() */ void AbcMatrix::transposeTimesBasic(double scalar, const double * pi, double * y) const { assert (scalar==-1.0); int numberRows=model_->numberRows(); //AbcMemset0(y,numberRows); // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts()-model_->maximumAbcNumberRows(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const int * COIN_RESTRICT pivotVariable = model_->pivotVariable(); for (int i=0;i=numberRows) { CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; value = 0.0; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; value += pi[jRow] * elementByColumn[j]; } } else { value=pi[iSequence]; } y[i]+=scalar*value; } } // Adds multiple of a column (or slack) into an CoinIndexedvector void AbcMatrix::add(CoinIndexedVector & rowArray, int iSequence, double multiplier) const { int maximumRows=model_->maximumAbcNumberRows(); if (iSequence>=maximumRows) { const int * COIN_RESTRICT row = matrix_->getIndices(); iSequence -= maximumRows; const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); CoinBigIndex start = columnStart[iSequence]; CoinBigIndex next = columnStart[iSequence+1]; for (CoinBigIndex j = start; j < next; j++) { int jRow = row[j]; rowArray.quickAdd(jRow,elementByColumn[j]*multiplier); } } else { rowArray.quickAdd(iSequence,multiplier); } } /* Unpacks a column into an CoinIndexedVector */ void AbcMatrix::unpack(CoinIndexedVector & usefulArray, int sequence) const { usefulArray.clear(); int maximumRows=model_->maximumAbcNumberRows(); if (sequence < maximumRows) { //slack usefulArray.insert(sequence , 1.0); } else { // column const CoinBigIndex * COIN_RESTRICT columnStart = matrix()->getVectorStarts()-maximumRows; CoinBigIndex start=columnStart[sequence]; CoinBigIndex end=columnStart[sequence+1]; const int * COIN_RESTRICT row = matrix()->getIndices()+start; const double * COIN_RESTRICT elementByColumn = matrix()->getElements()+start; int * COIN_RESTRICT index = usefulArray.getIndices(); double * COIN_RESTRICT array = usefulArray.denseVector(); int numberNonZero=end-start; for (int j=0; jnumberRows()*(numberRowBlocks_+1); //} } // Row elements double * AbcMatrix::rowElements() const { return element_; } // Row columnss CoinSimplexInt * AbcMatrix::rowColumns() const { return column_; } Clp-1.15.10/src/ClpConfig.h0000644000076600007660000000242411573730475013675 0ustar coincoin/* Copyright (C) 2011 * All Rights Reserved. * This code is published under the Eclipse Public License. * * $Id: ClpConfig.h 1734 2011-06-08 17:28:29Z stefan $ * * Include file for the configuration of Clp. * * 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. * * 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 __CLPCONFIG_H__ #define __CLPCONFIG_H__ #ifdef HAVE_CONFIG_H #ifdef CLP_BUILD #include "config.h" #else #include "config_clp.h" #endif #else /* HAVE_CONFIG_H */ #ifdef CLP_BUILD #include "config_default.h" #else #include "config_clp_default.h" #endif #endif /* HAVE_CONFIG_H */ #endif /*__CLPCONFIG_H__*/ Clp-1.15.10/src/CoinAbcSmallFactorization5.cpp0000644000076600007660000000103012101105055017437 0ustar coincoin/* $Id: CoinAbcSmallFactorization5.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization5.cpp" #endif Clp-1.15.10/src/AbcSimplexParallel.cpp0000644000076600007660000030070212101105055016042 0ustar coincoin/* $Id: AbcSimplexParallel.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "AbcSimplexDual.hpp" #include "ClpEventHandler.hpp" #include "AbcSimplexFactorization.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "CoinFloatEqual.hpp" #include "AbcDualRowDantzig.hpp" #include "ClpMessage.hpp" #include "ClpLinearObjective.hpp" #include #include #include #include #include //#undef AVX2 #define _mm256_broadcast_sd(x) static_cast<__m256d> (__builtin_ia32_vbroadcastsd256 (x)) #define _mm256_load_pd(x) *(__m256d *)(x) #define _mm256_store_pd (s, x) *((__m256d *)s)=x //#define ABC_DEBUG 2 /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int AbcSimplexDual::whileIteratingSerial() { /* arrays 0 - to get tableau row and then for weights update 1 - tableau column 2 - for flip 3 - actual tableau row */ #ifdef CLP_DEBUG int debugIteration = -1; #endif // if can't trust much and long way from optimal then relax //if (largestPrimalError_ > 10.0) //abcFactorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0)); //else //abcFactorization_->relaxAccuracyCheck(1.0); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int returnCode = -1; #define DELAYED_UPDATE arrayForBtran_=0; setUsedArray(arrayForBtran_); arrayForFtran_=1; setUsedArray(arrayForFtran_); arrayForFlipBounds_=2; setUsedArray(arrayForFlipBounds_); arrayForTableauRow_=3; setUsedArray(arrayForTableauRow_); arrayForDualColumn_=4; setUsedArray(arrayForDualColumn_); arrayForReplaceColumn_=4; //4; arrayForFlipRhs_=5; setUsedArray(arrayForFlipRhs_); dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row createDualPricingVectorSerial(); do { #if ABC_DEBUG checkArrays(); #endif /* -1 - just move dual in values pass 0 - take iteration 1 - don't take but continue 2 - don't take and break */ stateOfIteration_=0; returnCode=-1; // put row of tableau in usefulArray[arrayForTableauRow_] /* Could a) copy [arrayForBtran_] and start off updateWeights earlier b) break transposeTimes into two and do after slack part c) also think if cleaner to go all way with update but just don't do final part */ //upperTheta=COIN_DBL_MAX; double saveAcceptable=acceptablePivot_; if (largestPrimalError_>1.0e-5||largestDualError_>1.0e-5) { if (!abcFactorization_->pivots()) acceptablePivot_*=1.0e2; else if (abcFactorization_->pivots()<5) acceptablePivot_*=1.0e1; } dualColumn1(); acceptablePivot_=saveAcceptable; if ((stateOfProblem_&VALUES_PASS)!=0) { // see if can just move dual if (fabs(upperTheta_-fabs(abcDj_[sequenceOut_]))= 0) { // normal iteration // update the incoming column (and do weights) getTableauColumnFlipAndStartReplaceSerial(); } else if (stateOfIteration_!=-1) { stateOfIteration_=2; } } if (!stateOfIteration_) { // assert (stateOfIteration_!=1); int whatNext=0; whatNext = housekeeping(); if (whatNext == 1) { problemStatus_ = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; stateOfIteration_=2; } if (problemStatus_==-1) { replaceColumnPart3(); //clearArrays(arrayForReplaceColumn_); #if ABC_DEBUG checkArrays(); #endif updateDualsInDual(); abcDualRowPivot_->updatePrimalSolutionAndWeights(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_], movement_); #if ABC_DEBUG checkArrays(); #endif } else { abcDualRowPivot_->updateWeights2(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_]); //clearArrays(arrayForBtran_); //clearArrays(arrayForFtran_); } } else { if (stateOfIteration_<0) { // move dual in dual values pass theta_=abcDj_[sequenceOut_]; updateDualsInDual(); abcDj_[sequenceOut_]=0.0; sequenceOut_=-1; } // clear all arrays clearArrays(-1); //sequenceIn_=-1; //sequenceOut_=-1; } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 4; stateOfIteration_=2; } } // at this stage sequenceIn_ may be <0 if (sequenceIn_<0&&sequenceOut_>=0) { // no incoming column is valid returnCode=noPivotColumn(); } if (stateOfIteration_==2) { sequenceIn_=-1; break; } swapPrimalStuff(); if (problemStatus_!=-1) { break; } // dualRow will go to virtual row pivot choice algorithm // make sure values pass off if it should be // use Btran array and clear inside dualPivotRow (if used) int lastSequenceOut=sequenceOut_; int lastDirectionOut=directionOut_; dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row // create as packed createDualPricingVectorSerial(); swapDualStuff(lastSequenceOut,lastDirectionOut); // next pivot } else { // no pivot row clearArrays(-1); returnCode=noPivotRow(); break; } } while (problemStatus_ == -1); usefulArray_[arrayForTableauRow_].compact(); #if ABC_DEBUG checkArrays(); #endif } else { // no pivot row on first try clearArrays(-1); returnCode=noPivotRow(); } //printStuff(); clearArrays(-1); //if (pivotRow_==-100) //returnCode=-100; // end of values pass return returnCode; } // Create dual pricing vector void AbcSimplexDual::createDualPricingVectorSerial() { #ifndef NDEBUG #if ABC_NORMAL_DEBUG>3 checkArrays(); #endif #endif // we found a pivot row if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) { handler_->message(CLP_SIMPLEX_PIVOTROW, messages_) << pivotRow_ << CoinMessageEol; } // check accuracy of weights abcDualRowPivot_->checkAccuracy(); // get sign for finding row of tableau // create as packed usefulArray_[arrayForBtran_].createOneUnpackedElement(pivotRow_, -directionOut_); abcFactorization_->updateColumnTranspose(usefulArray_[arrayForBtran_]); sequenceIn_ = -1; } void AbcSimplexDual::getTableauColumnPart1Serial() { #if ABC_DEBUG { const double * work=usefulArray_[arrayForTableauRow_].denseVector(); int number=usefulArray_[arrayForTableauRow_].getNumElements(); const int * which=usefulArray_[arrayForTableauRow_].getIndices(); for (int i=0;iupdateWeights1(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_]); } int AbcSimplexDual::getTableauColumnFlipAndStartReplaceSerial() { // move checking stuff down into called functions int numberFlipped; numberFlipped=flipBounds(); // update the incoming column getTableauColumnPart1Serial(); checkReplacePart1(); //checkReplacePart1a(); //checkReplacePart1b(); getTableauColumnPart2(); //usefulArray_[arrayForTableauRow_].compact(); // returns 3 if skip this iteration and re-factorize /* return code 0 - OK 2 - flag something and skip 3 - break and re-factorize 4 - break and say infeasible */ int returnCode=0; // amount primal will move movement_ = -dualOut_ * directionOut_ / alpha_; // see if update stable #if ABC_NORMAL_DEBUG>3 if ((handler_->logLevel() & 32)) { double ft=ftAlpha_*abcFactorization_->pivotRegion()[pivotRow_]; double diff1=fabs(alpha_-btranAlpha_); double diff2=fabs(fabs(alpha_)-fabs(ft)); double diff3=fabs(fabs(ft)-fabs(btranAlpha_)); double largest=CoinMax(CoinMax(diff1,diff2),diff3); printf("btran alpha %g, ftran alpha %g ftAlpha %g largest diff %g\n", btranAlpha_, alpha_,ft,largest); if (largest>0.001*fabs(alpha_)) { printf("bad\n"); } } #endif int numberPivots=abcFactorization_->pivots(); //double checkValue = 1.0e-7; // numberPivots<5 ? 1.0e-7 : 1.0e-6; double checkValue = numberPivots ? 1.0e-7 : 1.0e-5; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha_ << alpha_ << CoinMessageEol; // see with more relaxed criterion double test; if (fabs(btranAlpha_) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 10.0*checkValue;//1.0e-4 * (1.0 + fabs(alpha_)); bool needFlag = (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > test); double derror = CoinMin(fabs(btranAlpha_ - alpha_)/(1.0 + fabs(alpha_)),1.0)*0.9999e7; int error=0; while (derror>1.0) { error++; derror *= 0.1; } int frequency[8]={99999999,100,10,2,1,1,1,1}; int newFactorFrequency=CoinMin(forceFactorization_,frequency[error]); #if ABC_NORMAL_DEBUG>0 if (newFactorFrequency0.5e-6 &&abcFactorization_->pivotTolerance()<0.5) abcFactorization_->saferTolerances (1.0, -1.03); forceFactorization_=newFactorFrequency; #if ABC_NORMAL_DEBUG>0 if (fabs(btranAlpha_ + alpha_) < 1.0e-5*(1.0 + fabs(alpha_))) { printf("diff (%g,%g) %g check %g\n",btranAlpha_,alpha_,fabs(btranAlpha_-alpha_),checkValue*(1.0+fabs(alpha_))); } #endif if (numberPivots) { if (needFlag&&numberPivots<10) { // need to reject something assert (sequenceOut_>=0); char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("flag %d as alpha %g %g - after %d pivots\n", sequenceOut_, btranAlpha_, alpha_,numberPivots); #endif // Make safer? abcFactorization_->saferTolerances (1.0, -1.03); setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; lastBadIteration_ = numberIterations_; // say be more cautious } // Make safer? //if (numberPivots<5) //abcFactorization_->saferTolerances (-0.99, -1.01); problemStatus_ = -2; // factorize now returnCode = -2; stateOfIteration_=2; } else { if (needFlag) { assert (sequenceOut_>=0); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag a %g %g\n", btranAlpha_, alpha_); #endif setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha_) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; stateOfIteration_=2; } else { stateOfIteration_=1; } // Make safer? if (abcFactorization_->pivotTolerance()<0.999&&stateOfIteration_==1) { // change tolerance and re-invert abcFactorization_->saferTolerances (1.0, -1.03); problemStatus_ = -6; // factorize now returnCode = -2; stateOfIteration_=2; } } } } if (!stateOfIteration_) { // check update //int updateStatus = /* returns 0 - OK 1 - take iteration then re-factorize 2 - flag something and skip 3 - break and re-factorize 5 - take iteration then re-factorize because of memory */ int status=checkReplace(); if (status&&!returnCode) returnCode=status; } //clearArrays(arrayForFlipRhs_); if (stateOfIteration_&&numberFlipped) { //usefulArray_[arrayForTableauRow_].compact(); // move variables back flipBack(numberFlipped); } // could choose average of all three return returnCode; } #if ABC_PARALLEL==1 /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int AbcSimplexDual::whileIteratingThread() { /* arrays 0 - to get tableau row and then for weights update 1 - tableau column 2 - for flip 3 - actual tableau row */ #ifdef CLP_DEBUG int debugIteration = -1; #endif // if can't trust much and long way from optimal then relax //if (largestPrimalError_ > 10.0) //abcFactorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0)); //else //abcFactorization_->relaxAccuracyCheck(1.0); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int returnCode = -1; #define DELAYED_UPDATE arrayForBtran_=0; setUsedArray(arrayForBtran_); arrayForFtran_=1; setUsedArray(arrayForFtran_); arrayForFlipBounds_=2; setUsedArray(arrayForFlipBounds_); arrayForTableauRow_=3; setUsedArray(arrayForTableauRow_); arrayForDualColumn_=4; setUsedArray(arrayForDualColumn_); arrayForReplaceColumn_=4; //4; arrayForFlipRhs_=5; setUsedArray(arrayForFlipRhs_); dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row createDualPricingVectorThread(); do { #if ABC_DEBUG checkArrays(); #endif /* -1 - just move dual in values pass 0 - take iteration 1 - don't take but continue 2 - don't take and break */ stateOfIteration_=0; returnCode=-1; // put row of tableau in usefulArray[arrayForTableauRow_] /* Could a) copy [arrayForBtran_] and start off updateWeights earlier b) break transposeTimes into two and do after slack part c) also think if cleaner to go all way with update but just don't do final part */ //upperTheta=COIN_DBL_MAX; double saveAcceptable=acceptablePivot_; if (largestPrimalError_>1.0e-5||largestDualError_>1.0e-5) { if (!abcFactorization_->pivots()) acceptablePivot_*=1.0e2; else if (abcFactorization_->pivots()<5) acceptablePivot_*=1.0e1; } dualColumn1(); acceptablePivot_=saveAcceptable; if ((stateOfProblem_&VALUES_PASS)!=0) { // see if can just move dual if (fabs(upperTheta_-fabs(abcDj_[sequenceOut_]))= 0) { // normal iteration // update the incoming column (and do weights if serial) getTableauColumnFlipAndStartReplaceThread(); //usleep(1000); } else if (stateOfIteration_!=-1) { stateOfIteration_=2; } } if (parallelMode_!=0) { // do sync here stopParallelStuff(2); } if (!stateOfIteration_) { // assert (stateOfIteration_!=1); int whatNext=0; whatNext = housekeeping(); if (whatNext == 1) { problemStatus_ = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; stateOfIteration_=2; } } else { if (stateOfIteration_<0) { // move dual in dual values pass theta_=abcDj_[sequenceOut_]; updateDualsInDual(); abcDj_[sequenceOut_]=0.0; sequenceOut_=-1; } // clear all arrays clearArrays(-1); } // at this stage sequenceIn_ may be <0 if (sequenceIn_<0&&sequenceOut_>=0) { // no incoming column is valid returnCode=noPivotColumn(); } if (stateOfIteration_==2) { sequenceIn_=-1; break; } if (problemStatus_!=-1) { abcDualRowPivot_->updateWeights2(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_]); swapPrimalStuff(); break; } #if ABC_DEBUG checkArrays(); #endif if (stateOfIteration_!=-1) { assert (stateOfIteration_==0); // if 1 why are we here // can do these in parallel if (parallelMode_==0) { replaceColumnPart3(); updateDualsInDual(); abcDualRowPivot_->updatePrimalSolutionAndWeights(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_], movement_); } else { stopStart_=1+32*1; startParallelStuff(3); if (parallelMode_>1) { stopStart_=2+32*2; startParallelStuff(9); } else { replaceColumnPart3(); } abcDualRowPivot_->updatePrimalSolutionAndWeights(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_], movement_); } } #if ABC_DEBUG checkArrays(); #endif swapPrimalStuff(); // dualRow will go to virtual row pivot choice algorithm // make sure values pass off if it should be // use Btran array and clear inside dualPivotRow (if used) int lastSequenceOut=sequenceOut_; int lastDirectionOut=directionOut_; // redo to test on parallelMode_ if (parallelMode_>1) { stopStart_=2+32*2; // stop factorization update //stopStart_=3+32*3; // stop all stopParallelStuff(9); } dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row // create as packed createDualPricingVectorThread(); swapDualStuff(lastSequenceOut,lastDirectionOut); // next pivot // redo to test on parallelMode_ if (parallelMode_!=0) { stopStart_=1+32*1; // stop dual update stopParallelStuff(3); } } else { // no pivot row // redo to test on parallelMode_ if (parallelMode_!=0) { stopStart_=1+32*1; // stop dual update stopParallelStuff(3); } clearArrays(-1); returnCode=noPivotRow(); break; } } while (problemStatus_ == -1); usefulArray_[arrayForTableauRow_].compact(); #if ABC_DEBUG checkArrays(); #endif } else { // no pivot row on first try clearArrays(-1); returnCode=noPivotRow(); } //printStuff(); clearArrays(-1); //if (pivotRow_==-100) //returnCode=-100; // end of values pass return returnCode; } // Create dual pricing vector void AbcSimplexDual::createDualPricingVectorThread() { #ifndef NDEBUG #if ABC_NORMAL_DEBUG>3 checkArrays(); #endif #endif // we found a pivot row if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) { handler_->message(CLP_SIMPLEX_PIVOTROW, messages_) << pivotRow_ << CoinMessageEol; } // check accuracy of weights abcDualRowPivot_->checkAccuracy(); // get sign for finding row of tableau // create as packed usefulArray_[arrayForBtran_].createOneUnpackedElement(pivotRow_, -directionOut_); abcFactorization_->updateColumnTranspose(usefulArray_[arrayForBtran_]); sequenceIn_ = -1; } void AbcSimplexDual::getTableauColumnPart1Thread() { #if ABC_DEBUG { const double * work=usefulArray_[arrayForTableauRow_].denseVector(); int number=usefulArray_[arrayForTableauRow_].getNumElements(); const int * which=usefulArray_[arrayForTableauRow_].getIndices(); for (int i=0;iupdateColumnFTPart1(usefulArray_[arrayForFtran_]); // pivot element //alpha_ = usefulArray_[arrayForFtran_].denseVector()[pivotRow_]; } else { alpha_ = abcDualRowPivot_->updateWeights1(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_]); } } int AbcSimplexDual::getTableauColumnFlipAndStartReplaceThread() { // move checking stuff down into called functions // threads 2 and 3 are available int numberFlipped; if (parallelMode_==0) { numberFlipped=flipBounds(); // update the incoming column getTableauColumnPart1Thread(); checkReplacePart1(); //checkReplacePart1a(); //checkReplacePart1b(); getTableauColumnPart2(); } else { // save stopStart int saveStopStart=stopStart_; if (parallelMode_>1) { // we can flip immediately stopStart_=2+32*2; // just thread 1 startParallelStuff(8); // update the incoming column getTableauColumnPart1Thread(); stopStart_=4+32*4; // just thread 2 startParallelStuff(7); getTableauColumnPart2(); stopStart_=6+32*6; // just threads 1 and 2 stopParallelStuff(8); //ftAlpha_=threadInfo_[2].result; } else { // just one extra thread - do replace // update the incoming column getTableauColumnPart1Thread(); stopStart_=2+32*2; // just thread 1 startParallelStuff(7); getTableauColumnPart2(); numberFlipped=flipBounds(); stopParallelStuff(8); //ftAlpha_=threadInfo_[1].result; } stopStart_=saveStopStart; } //usefulArray_[arrayForTableauRow_].compact(); // returns 3 if skip this iteration and re-factorize /* return code 0 - OK 2 - flag something and skip 3 - break and re-factorize 4 - break and say infeasible */ int returnCode=0; // amount primal will move movement_ = -dualOut_ * directionOut_ / alpha_; // see if update stable #if ABC_NORMAL_DEBUG>3 if ((handler_->logLevel() & 32)) { double ft=ftAlpha_*abcFactorization_->pivotRegion()[pivotRow_]; double diff1=fabs(alpha_-btranAlpha_); double diff2=fabs(fabs(alpha_)-fabs(ft)); double diff3=fabs(fabs(ft)-fabs(btranAlpha_)); double largest=CoinMax(CoinMax(diff1,diff2),diff3); printf("btran alpha %g, ftran alpha %g ftAlpha %g largest diff %g\n", btranAlpha_, alpha_,ft,largest); if (largest>0.001*fabs(alpha_)) { printf("bad\n"); } } #endif int numberPivots=abcFactorization_->pivots(); //double checkValue = 1.0e-7; // numberPivots<5 ? 1.0e-7 : 1.0e-6; double checkValue = numberPivots ? 1.0e-7 : 1.0e-5; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha_ << alpha_ << CoinMessageEol; // see with more relaxed criterion double test; if (fabs(btranAlpha_) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 10.0*checkValue;//1.0e-4 * (1.0 + fabs(alpha_)); bool needFlag = (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > test); double derror = CoinMin(fabs(btranAlpha_ - alpha_)/(1.0 + fabs(alpha_)),1.0)*0.9999e7; int error=0; while (derror>1.0) { error++; derror *= 0.1; } int frequency[8]={99999999,100,10,2,1,1,1,1}; int newFactorFrequency=CoinMin(forceFactorization_,frequency[error]); #if ABC_NORMAL_DEBUG>0 if (newFactorFrequency0.5e-6 &&abcFactorization_->pivotTolerance()<0.5) abcFactorization_->saferTolerances (1.0, -1.03); forceFactorization_=newFactorFrequency; #if ABC_NORMAL_DEBUG>0 if (fabs(btranAlpha_ + alpha_) < 1.0e-5*(1.0 + fabs(alpha_))) { printf("diff (%g,%g) %g check %g\n",btranAlpha_,alpha_,fabs(btranAlpha_-alpha_),checkValue*(1.0+fabs(alpha_))); } #endif if (numberPivots) { if (needFlag&&numberPivots<10) { // need to reject something assert (sequenceOut_>=0); char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("flag %d as alpha %g %g - after %d pivots\n", sequenceOut_, btranAlpha_, alpha_,numberPivots); #endif // Make safer? abcFactorization_->saferTolerances (1.0, -1.03); setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; lastBadIteration_ = numberIterations_; // say be more cautious } // Make safer? //if (numberPivots<5) //abcFactorization_->saferTolerances (-0.99, -1.01); problemStatus_ = -2; // factorize now returnCode = -2; stateOfIteration_=2; } else { if (needFlag) { assert (sequenceOut_>=0); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag a %g %g\n", btranAlpha_, alpha_); #endif setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha_) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; stateOfIteration_=2; } else { stateOfIteration_=1; } // Make safer? if (abcFactorization_->pivotTolerance()<0.999&&stateOfIteration_==1) { // change tolerance and re-invert abcFactorization_->saferTolerances (1.0, -1.03); problemStatus_ = -6; // factorize now returnCode = -2; stateOfIteration_=2; } } } } if (!stateOfIteration_) { // check update //int updateStatus = /* returns 0 - OK 1 - take iteration then re-factorize 2 - flag something and skip 3 - break and re-factorize 5 - take iteration then re-factorize because of memory */ int status=checkReplace(); if (status&&!returnCode) returnCode=status; } //clearArrays(arrayForFlipRhs_); if (stateOfIteration_&&numberFlipped) { //usefulArray_[arrayForTableauRow_].compact(); // move variables back flipBack(numberFlipped); } // could choose average of all three return returnCode; } #endif #if ABC_PARALLEL==2 #if ABC_NORMAL_DEBUG>0 // for conflicts int cilk_conflict=0; #endif #ifdef EARLY_FACTORIZE static int doEarlyFactorization(AbcSimplexDual * dual) { int returnCode=cilk_spawn dual->whileIteratingParallel(123456789); CoinIndexedVector & vector = *dual->usefulArray(ABC_NUMBER_USEFUL-1); int status=dual->earlyFactorization()->factorize(dual,vector); #if 0 // Is this safe if (!status&&true) { // do pivots if there are any int capacity = vector.capacity(); capacity--; int numberPivotsStored = vector.getIndices()[capacity]; status = dual->earlyFactorization()->replaceColumns(dual,vector, 0,numberPivotsStored,false); } #endif if (status) { printf("bad early factorization in doEarly - switch off\n"); vector.setNumElements(-1); } cilk_sync; return returnCode; } #endif #define MOVE_UPDATE_WEIGHTS /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int AbcSimplexDual::whileIteratingCilk() { /* arrays 0 - to get tableau row and then for weights update 1 - tableau column 2 - for flip 3 - actual tableau row */ #ifdef CLP_DEBUG int debugIteration = -1; #endif // if can't trust much and long way from optimal then relax //if (largestPrimalError_ > 10.0) //abcFactorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0)); //else //abcFactorization_->relaxAccuracyCheck(1.0); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int returnCode = -1; #define DELAYED_UPDATE arrayForBtran_=0; setUsedArray(arrayForBtran_); arrayForFtran_=1; setUsedArray(arrayForFtran_); arrayForFlipBounds_=2; setUsedArray(arrayForFlipBounds_); arrayForTableauRow_=3; setUsedArray(arrayForTableauRow_); arrayForDualColumn_=4; setUsedArray(arrayForDualColumn_); arrayForReplaceColumn_=6; //4; setUsedArray(arrayForReplaceColumn_); #ifndef MOVE_UPDATE_WEIGHTS arrayForFlipRhs_=5; setUsedArray(arrayForFlipRhs_); #else arrayForFlipRhs_=0; // use for weights setUsedArray(5); #endif dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row createDualPricingVectorCilk(); // ABC_PARALLEL 2 #if 0 { for (int i=0;i=0) printf("%d status %d l %g,%g u %g,%g\n",iSequence,internalStatus_[iSequence], abcLower_[iSequence],lowerSaved_[iSequence], abcUpper_[iSequence],upperSaved_[iSequence]); } #endif int numberPivots = abcFactorization_->maximumPivots(); #ifdef EARLY_FACTORIZE int numberEarly=0; if (numberPivots>20&&(numberEarly_&0xffff)>5) { numberEarly=numberEarly_&0xffff; numberPivots=CoinMax(numberPivots-numberEarly-abcFactorization_->pivots(),numberPivots/2); } returnCode=whileIteratingParallel(numberPivots); if (returnCode==-99) { if (numberEarly) { if (!abcEarlyFactorization_) abcEarlyFactorization_ = new AbcSimplexFactorization(*abcFactorization_); // create pivot list CoinIndexedVector & vector = usefulArray_[ABC_NUMBER_USEFUL-1]; vector.checkClear(); int * indices = vector.getIndices(); int capacity = vector.capacity(); int numberNeeded=numberRows_+2*numberEarly+1; if (capacity=numberRows_) indices[numberBasic++]=iSequence; } assert (numberBasic==numberRows_); indices[capacity-1]=0; // could set iterations to -1 for safety #if 0 cilk_spawn doEarlyFactorization(this); returnCode=whileIteratingParallel(123456789); cilk_sync; #else returnCode=doEarlyFactorization(this); #endif } else { returnCode=whileIteratingParallel(123456789); } } #else returnCode=whileIteratingParallel(numberPivots); #endif usefulArray_[arrayForTableauRow_].compact(); #if ABC_DEBUG checkArrays(); #endif } else { // no pivot row on first try clearArrays(-1); returnCode=noPivotRow(); } //printStuff(); clearArrays(-1); //if (pivotRow_==-100) //returnCode=-100; // end of values pass return returnCode; } // Create dual pricing vector void AbcSimplexDual::createDualPricingVectorCilk() { #if CILK_CONFLICT>0 if(cilk_conflict&15!=0) { printf("cilk_conflict %d!\n",cilk_conflict); cilk_conflict=0; } #endif #ifndef NDEBUG #if ABC_NORMAL_DEBUG>3 checkArrays(); #endif #endif // we found a pivot row if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) { handler_->message(CLP_SIMPLEX_PIVOTROW, messages_) << pivotRow_ << CoinMessageEol; } // check accuracy of weights abcDualRowPivot_->checkAccuracy(); // get sign for finding row of tableau // create as packed #if MOVE_REPLACE_PART1A > 0 if (!abcFactorization_->usingFT()) { #endif usefulArray_[arrayForBtran_].createOneUnpackedElement(pivotRow_, -directionOut_); abcFactorization_->updateColumnTranspose(usefulArray_[arrayForBtran_]); #if MOVE_REPLACE_PART1A > 0 } else { cilk_spawn abcFactorization_->checkReplacePart1a(&usefulArray_[arrayForReplaceColumn_],pivotRow_); usefulArray_[arrayForBtran_].createOneUnpackedElement(pivotRow_, -directionOut_); abcFactorization_->updateColumnTransposeCpu(usefulArray_[arrayForBtran_],1); cilk_sync; } #endif sequenceIn_ = -1; } void AbcSimplexDual::getTableauColumnPart1Cilk() { #if ABC_DEBUG { const double * work=usefulArray_[arrayForTableauRow_].denseVector(); int number=usefulArray_[arrayForTableauRow_].getNumElements(); const int * which=usefulArray_[arrayForTableauRow_].getIndices(); for (int i=0;iupdateColumnFTPart1(usefulArray_[arrayForFtran_]); } int AbcSimplexDual::getTableauColumnFlipAndStartReplaceCilk() { // move checking stuff down into called functions // threads 2 and 3 are available int numberFlipped; //cilk getTableauColumnPart1Cilk(); #if MOVE_REPLACE_PART1A <= 0 cilk_spawn getTableauColumnPart2(); #if MOVE_REPLACE_PART1A == 0 cilk_spawn checkReplacePart1(); #endif numberFlipped=flipBounds(); cilk_sync; #else if (abcFactorization_->usingFT()) { cilk_spawn getTableauColumnPart2(); ftAlpha_ = cilk_spawn abcFactorization_->checkReplacePart1b(&usefulArray_[arrayForReplaceColumn_],pivotRow_); numberFlipped=flipBounds(); cilk_sync; } else { cilk_spawn getTableauColumnPart2(); numberFlipped=flipBounds(); cilk_sync; } #endif //usefulArray_[arrayForTableauRow_].compact(); // returns 3 if skip this iteration and re-factorize /* return code 0 - OK 2 - flag something and skip 3 - break and re-factorize 4 - break and say infeasible */ int returnCode=0; // amount primal will move movement_ = -dualOut_ * directionOut_ / alpha_; // see if update stable #if ABC_NORMAL_DEBUG>3 if ((handler_->logLevel() & 32)) { double ft=ftAlpha_*abcFactorization_->pivotRegion()[pivotRow_]; double diff1=fabs(alpha_-btranAlpha_); double diff2=fabs(fabs(alpha_)-fabs(ft)); double diff3=fabs(fabs(ft)-fabs(btranAlpha_)); double largest=CoinMax(CoinMax(diff1,diff2),diff3); printf("btran alpha %g, ftran alpha %g ftAlpha %g largest diff %g\n", btranAlpha_, alpha_,ft,largest); if (largest>0.001*fabs(alpha_)) { printf("bad\n"); } } #endif int numberPivots=abcFactorization_->pivots(); //double checkValue = 1.0e-7; // numberPivots<5 ? 1.0e-7 : 1.0e-6; double checkValue = numberPivots ? 1.0e-7 : 1.0e-5; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha_ << alpha_ << CoinMessageEol; // see with more relaxed criterion double test; if (fabs(btranAlpha_) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = CoinMin(10.0*checkValue,1.0e-4 * (1.0 + fabs(alpha_))); bool needFlag = (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > test); double derror = CoinMin(fabs(btranAlpha_ - alpha_)/(1.0 + fabs(alpha_)),1.0)*0.9999e7; int error=0; while (derror>1.0) { error++; derror *= 0.1; } int frequency[8]={99999999,100,10,2,1,1,1,1}; int newFactorFrequency=CoinMin(forceFactorization_,frequency[error]); #if ABC_NORMAL_DEBUG>0 if (newFactorFrequency0.5e-6 &&abcFactorization_->pivotTolerance()<0.5) abcFactorization_->saferTolerances (1.0, -1.03); forceFactorization_=newFactorFrequency; #if ABC_NORMAL_DEBUG>0 if (fabs(btranAlpha_ + alpha_) < 1.0e-5*(1.0 + fabs(alpha_))) { printf("diff (%g,%g) %g check %g\n",btranAlpha_,alpha_,fabs(btranAlpha_-alpha_),checkValue*(1.0+fabs(alpha_))); } #endif if (numberPivots) { if (needFlag&&numberPivots<10) { // need to reject something assert (sequenceOut_>=0); char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("flag %d as alpha %g %g - after %d pivots\n", sequenceOut_, btranAlpha_, alpha_,numberPivots); #endif // Make safer? abcFactorization_->saferTolerances (1.0, -1.03); setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; lastBadIteration_ = numberIterations_; // say be more cautious } // Make safer? //if (numberPivots<5) //abcFactorization_->saferTolerances (-0.99, -1.01); problemStatus_ = -2; // factorize now returnCode = -2; stateOfIteration_=2; } else { if (needFlag) { assert (sequenceOut_>=0); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag a %g %g\n", btranAlpha_, alpha_); #endif setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha_) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; stateOfIteration_=2; } else { stateOfIteration_=1; } // Make safer? if (abcFactorization_->pivotTolerance()<0.999&&stateOfIteration_==1) { // change tolerance and re-invert abcFactorization_->saferTolerances (1.0, -1.03); problemStatus_ = -6; // factorize now returnCode = -2; stateOfIteration_=2; } } } } if (!stateOfIteration_) { // check update //int updateStatus = /* returns 0 - OK 1 - take iteration then re-factorize 2 - flag something and skip 3 - break and re-factorize 5 - take iteration then re-factorize because of memory */ int status=checkReplace(); if (status&&!returnCode) returnCode=status; } //clearArrays(arrayForFlipRhs_); if (stateOfIteration_&&numberFlipped) { //usefulArray_[arrayForTableauRow_].compact(); // move variables back flipBack(numberFlipped); } // could choose average of all three return returnCode; } int AbcSimplexDual::whileIteratingParallel(int numberIterations) { int returnCode=-1; #ifdef EARLY_FACTORIZE int savePivot=-1; CoinIndexedVector & early = usefulArray_[ABC_NUMBER_USEFUL-1]; int * pivotIndices = early.getIndices(); double * pivotValues = early.denseVector(); int pivotCountPosition=early.capacity()-1; int numberSaved=0; if (numberIterations==123456789) savePivot=pivotCountPosition;; #endif numberIterations += numberIterations_; do { #if ABC_DEBUG checkArrays(); #endif /* -1 - just move dual in values pass 0 - take iteration 1 - don't take but continue 2 - don't take and break */ stateOfIteration_=0; returnCode=-1; // put row of tableau in usefulArray[arrayForTableauRow_] /* Could a) copy [arrayForBtran_] and start off updateWeights earlier b) break transposeTimes into two and do after slack part c) also think if cleaner to go all way with update but just don't do final part */ //upperTheta=COIN_DBL_MAX; double saveAcceptable=acceptablePivot_; if (largestPrimalError_>1.0e-5||largestDualError_>1.0e-5) { //if ((largestPrimalError_>1.0e-5||largestDualError_>1.0e-5)&&false) { if (!abcFactorization_->pivots()) acceptablePivot_*=1.0e2; else if (abcFactorization_->pivots()<5) acceptablePivot_*=1.0e1; } #ifdef MOVE_UPDATE_WEIGHTS // copy btran across usefulArray_[5].copy(usefulArray_[arrayForBtran_]); cilk_spawn abcDualRowPivot_->updateWeightsOnly(usefulArray_[5]);; #endif dualColumn1(); acceptablePivot_=saveAcceptable; if ((stateOfProblem_&VALUES_PASS)!=0) { // see if can just move dual if (fabs(upperTheta_-fabs(abcDj_[sequenceOut_]))updateWeightsOnly(usefulArray_[arrayForBtran_]);; #endif // get sequenceIn_ dualPivotColumn(); //stateOfIteration_=0; if (sequenceIn_ >= 0) { // normal iteration // update the incoming column //arrayForReplaceColumn_=getAvailableArray(); getTableauColumnFlipAndStartReplaceCilk(); //usleep(1000); } else if (stateOfIteration_!=-1) { stateOfIteration_=2; } } cilk_sync; // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 4; stateOfIteration_=2; } } if (!stateOfIteration_) { // assert (stateOfIteration_!=1); int whatNext=0; whatNext = housekeeping(); #ifdef EARLY_FACTORIZE if (savePivot>=0) { // save pivot pivotIndices[--savePivot]=sequenceOut_; pivotValues[savePivot]=alpha_; pivotIndices[--savePivot]=sequenceIn_; pivotValues[savePivot]=btranAlpha_; numberSaved++; } #endif if (whatNext == 1) { problemStatus_ = -2; // refactorize usefulArray_[arrayForTableauRow_].compact(); } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; stateOfIteration_=2; } #ifdef EARLY_FACTORIZE if (savePivot>=0) { // tell worker can update this pivotIndices[pivotCountPosition]=numberSaved; } #endif } else { usefulArray_[arrayForTableauRow_].compact(); if (stateOfIteration_<0) { // move dual in dual values pass theta_=abcDj_[sequenceOut_]; updateDualsInDual(); abcDj_[sequenceOut_]=0.0; sequenceOut_=-1; } // clear all arrays clearArrays(-1); } // at this stage sequenceIn_ may be <0 if (sequenceIn_<0&&sequenceOut_>=0) { usefulArray_[arrayForTableauRow_].compact(); // no incoming column is valid returnCode=noPivotColumn(); } if (stateOfIteration_==2) { usefulArray_[arrayForTableauRow_].compact(); sequenceIn_=-1; #ifdef ABC_LONG_FACTORIZATION abcFactorization_->clearHiddenArrays(); #endif break; } if (problemStatus_!=-1) { #ifndef MOVE_UPDATE_WEIGHTS abcDualRowPivot_->updateWeights2(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_]); #else abcDualRowPivot_->updateWeights2(usefulArray_[5],usefulArray_[arrayForFtran_]); #endif #ifdef ABC_LONG_FACTORIZATION abcFactorization_->clearHiddenArrays(); #endif swapPrimalStuff(); break; } if (stateOfIteration_==1) { // clear all arrays clearArrays(-2); #ifdef ABC_LONG_FACTORIZATION abcFactorization_->clearHiddenArrays(); #endif } if (stateOfIteration_==0) { // can do these in parallel // No idea why I need this - but otherwise runs not repeatable (try again??) //usefulArray_[3].compact(); cilk_spawn updateDualsInDual(); int lastSequenceOut; int lastDirectionOut; if (firstFree_<0) { // can do in parallel cilk_spawn replaceColumnPart3(); updatePrimalSolution(); swapPrimalStuff(); // dualRow will go to virtual row pivot choice algorithm // make sure values pass off if it should be // use Btran array and clear inside dualPivotRow (if used) lastSequenceOut=sequenceOut_; lastDirectionOut=directionOut_; dualPivotRow(); cilk_sync; } else { // be more careful as dualPivotRow may do update cilk_spawn replaceColumnPart3(); updatePrimalSolution(); swapPrimalStuff(); // dualRow will go to virtual row pivot choice algorithm // make sure values pass off if it should be // use Btran array and clear inside dualPivotRow (if used) lastSequenceOut=sequenceOut_; lastDirectionOut=directionOut_; cilk_sync; dualPivotRow(); } lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row // create as packed // dual->checkReplacePart1a(); createDualPricingVectorCilk(); swapDualStuff(lastSequenceOut,lastDirectionOut); } cilk_sync; } else { // after moving dual in values pass dualPivotRow(); lastPivotRow_=pivotRow_; if (pivotRow_ >= 0) { // we found a pivot row // create as packed createDualPricingVectorCilk(); } } if (pivotRow_<0) { // no pivot row clearArrays(-1); returnCode=noPivotRow(); break; } if (numberIterations == numberIterations_&&problemStatus_==-1) { returnCode=-99; break; } } while (problemStatus_ == -1); return returnCode; } #if 0 void AbcSimplexDual::whileIterating2() { // get sequenceIn_ dualPivotColumn(); //stateOfIteration_=0; if (sequenceIn_ >= 0) { // normal iteration // update the incoming column //arrayForReplaceColumn_=getAvailableArray(); getTableauColumnFlipAndStartReplaceCilk(); //usleep(1000); } else if (stateOfIteration_!=-1) { stateOfIteration_=2; } } #endif #endif void AbcSimplexDual::updatePrimalSolution() { // finish doing weights #ifndef MOVE_UPDATE_WEIGHTS abcDualRowPivot_->updatePrimalSolutionAndWeights(usefulArray_[arrayForBtran_],usefulArray_[arrayForFtran_], movement_); #else abcDualRowPivot_->updatePrimalSolutionAndWeights(usefulArray_[5],usefulArray_[arrayForFtran_], movement_); #endif } int xxInfo[6][8]; double parallelDual4(AbcSimplexDual * dual) { int maximumRows=dual->maximumAbcNumberRows(); //int numberTotal=dual->numberTotal(); CoinIndexedVector & update = *dual->usefulArray(dual->arrayForBtran()); CoinPartitionedVector & tableauRow= *dual->usefulArray(dual->arrayForTableauRow()); CoinPartitionedVector & candidateList= *dual->usefulArray(dual->arrayForDualColumn()); AbcMatrix * matrix = dual->abcMatrix(); // do slacks first (move before sync) double upperTheta=dual->upperTheta(); //assert (upperTheta>-100*dual->dualTolerance()||dual->sequenceIn()>=0||dual->lastFirstFree()>=0); #if ABC_PARALLEL #define NUMBER_BLOCKS NUMBER_ROW_BLOCKS int numberBlocks=CoinMin(NUMBER_BLOCKS,dual->numberCpus()); #else #define NUMBER_BLOCKS 1 int numberBlocks=NUMBER_BLOCKS; #endif #if ABC_PARALLEL if (dual->parallelMode()==0) numberBlocks=1; #endif // see if worth using row copy bool gotRowCopy = matrix->gotRowCopy(); int number=update.getNumElements(); assert (number); bool useRowCopy = (gotRowCopy&&(number<<2)numberRowBlocks()); #if ABC_PARALLEL==1 // redo so can pass info in with void * CoinAbcThreadInfo * infoP = dual->threadInfoPointer(); int cpuMask=((1<parallelMode())-1); cpuMask += cpuMask<<5; dual->setStopStart(cpuMask); #endif CoinAbcThreadInfo info[NUMBER_BLOCKS]; const int * starts; if (useRowCopy) starts=matrix->blockStart(); else starts=matrix->startColumnBlock(); tableauRow.setPartitions(numberBlocks,starts); candidateList.setPartitions(numberBlocks,starts); //printf("free sequence in %d\n",dual->freeSequenceIn()); if (useRowCopy) { // using row copy #if ABC_PARALLEL if (numberBlocks>1) { #if ABC_PARALLEL==2 for (int i=0;idualColumn1Row(info[i].stuff[1],COIN_DBL_MAX,info[i].stuff[2], update,tableauRow,candidateList); } cilk_sync; #else // parallel 1 for (int i=0;istartParallelStuff(5); } } info[numberBlocks-1].stuff[1]=numberBlocks-1; info[numberBlocks-1].stuff[2]=-1; //double freeAlpha; info[numberBlocks-1].result = matrix->dualColumn1Row(info[numberBlocks-1].stuff[1], upperTheta,info[numberBlocks-1].stuff[2], update,tableauRow,candidateList); dual->stopParallelStuff(5); for (int i=0;i2); info[0].result = matrix->dualColumn1Row(info[0].stuff[1], upperTheta,info[0].stuff[2], update,tableauRow,candidateList); #if ABC_PARALLEL } #endif } else { // end of useRowCopy #if ABC_PARALLEL if (numberBlocks>1) { #if ABC_PARALLEL==2 // do by column for (int i=0;idualColumn1Part(info[i].stuff[1],info[i].stuff[2], info[i].result, update,tableauRow,candidateList); } cilk_sync; #else // parallel 1 // do by column for (int i=0;istartParallelStuff(4); } } matrix->dualColumn1Part(info[numberBlocks-1].stuff[1],info[numberBlocks-1].stuff[2], info[numberBlocks-1].result, update,tableauRow,candidateList); dual->stopParallelStuff(4); for (int i=0;idualColumn1Part(info[0].stuff[1],info[0].stuff[2], info[0].result, update,tableauRow,candidateList); #if ABC_PARALLEL } #endif } int sequenceIn[NUMBER_BLOCKS]; bool anyFree=false; #if 0 if (useRowCopy) { printf("Result at iteration %d slack seqIn %d upperTheta %g\n", dual->numberIterations(),dual->freeSequenceIn(),upperTheta); double * arrayT = tableauRow.denseVector(); int * indexT = tableauRow.getIndices(); double * arrayC = candidateList.denseVector(); int * indexC = candidateList.getIndices(); for (int i=0;i=0) anyFree=true; upperTheta=CoinMin(info[i].result,upperTheta); //assert (info[i].result>-100*dual->dualTolerance()||sequenceIn[i]>=0||dual->lastFirstFree()>=0); } if (anyFree) { int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); // search for free coming in double bestFree=0.0; int bestSequence=dual->sequenceIn(); if (bestSequence>=0) bestFree=dual->alpha(); for (int i=0;i=0) { // free variable - search int start=starts[i]; int end=start+tableauRow.getNumElements(i); for (int k=start;k=0) { double oldValue = dual->djRegion()[bestSequence]; dual->setSequenceIn(bestSequence); dual->setAlpha(bestFree); dual->setTheta(oldValue / bestFree); } } //tableauRow.compact(); //candidateList.compact(); #if 0//ndef NDEBUG tableauRow.setPackedMode(true); tableauRow.sortPacked(); candidateList.setPackedMode(true); candidateList.sortPacked(); #endif return upperTheta; } #if ABC_PARALLEL==2 static void parallelDual5a(AbcSimplexFactorization * factorization, CoinIndexedVector * whichVector, int numberCpu, int whichCpu, double * weights) { double * COIN_RESTRICT array = whichVector->denseVector(); int * COIN_RESTRICT which = whichVector->getIndices(); int numberRows=factorization->numberRows(); for (int i = whichCpu; i < numberRows; i+=numberCpu) { double value = 0.0; array[i] = 1.0; which[0] = i; whichVector->setNumElements(1); factorization->updateColumnTransposeCpu(*whichVector,whichCpu); int number = whichVector->getNumElements(); for (int j = 0; j < number; j++) { int k= which[j]; value += array[k] * array[k]; array[k] = 0.0; } weights[i] = value; } whichVector->setNumElements(0); } #endif #if ABC_PARALLEL==2 void parallelDual5(AbcSimplexFactorization * factorization, CoinIndexedVector ** whichVector, int numberCpu, int whichCpu, double * weights) { if (whichCpu) { cilk_spawn parallelDual5(factorization,whichVector,numberCpu,whichCpu-1,weights); parallelDual5a(factorization,whichVector[whichCpu],numberCpu,whichCpu,weights); cilk_sync; } else { parallelDual5a(factorization,whichVector[whichCpu],numberCpu,whichCpu,weights); } } #endif // cilk seems a bit fragile #define CILK_FRAGILE 1 #if CILK_FRAGILE>1 #undef cilk_spawn #undef cilk_sync #define cilk_spawn #define cilk_sync #define ONWARD 0 #elif CILK_FRAGILE==1 #define ONWARD 0 #else #define ONWARD 1 #endif // Code below is just a translation of LAPACK #define BLOCKING1 8 // factorization strip #define BLOCKING2 8 // dgemm recursive #define BLOCKING3 16 // dgemm parallel /* type 0 Left Lower NoTranspose Unit 1 Left Upper NoTranspose NonUnit 2 Left Lower Transpose Unit 3 Left Upper Transpose NonUnit */ static void CoinAbcDtrsmFactor(int m, int n, double * COIN_RESTRICT a,int lda) { assert ((m&(BLOCKING8-1))==0&&(n&(BLOCKING8-1))==0); assert (m==BLOCKING8); // 0 Left Lower NoTranspose Unit /* entry for column j and row i (when multiple of BLOCKING8) is at aBlocked+j*m+i*BLOCKING8 */ double * COIN_RESTRICT aBase2 = a; double * COIN_RESTRICT bBase2 = aBase2+lda*BLOCKING8; for (int jj=0;jjCILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm0(kkk,first,mid,m,a,b); dtrsm0(kkk,mid,last,m,a,b); cilk_sync; } else { const double * COIN_RESTRICT aBaseA = a+UNROLL_DTRSM*BLOCKING8X8+kkk*BLOCKING8; aBaseA += (first-mm)*BLOCKING8-BLOCKING8X8; aBaseA += m*kkk; for (int ii=first;ii(bBaseI)=b0; //_mm256_store_pd (bBaseI+4, b1); *reinterpret_cast<__m256d *>(bBaseI+4)=b1; #endif } } } } void CoinAbcDtrsm0(int m, double * COIN_RESTRICT a,double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 0 Left Lower NoTranspose Unit for (int kkk=0;kkkCILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm1(kkk,first,mid,m,a,b); dtrsm1(kkk,mid,last,m,a,b); cilk_sync; } else { for (int iii=last-BLOCKING8;iii>=first;iii-=BLOCKING8) { double * COIN_RESTRICT bBase2 = b+iii; const double * COIN_RESTRICT aBaseA= a+BLOCKING8X8+BLOCKING8*iii; for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { double * COIN_RESTRICT bBase = b+ii; const double * COIN_RESTRICT aBase=aBaseA+m*ii; #if AVX2 !=2 #ifndef ALTERNATE_INNER for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase-BLOCKING8); for (int k=BLOCKING8-1;k>=0;k--) { bBase2[k] -= bBase[i]*aBase[k]; } } #else double b0=bBase2[0]; double b1=bBase2[1]; double b2=bBase2[2]; double b3=bBase2[3]; double b4=bBase2[4]; double b5=bBase2[5]; double b6=bBase2[6]; double b7=bBase2[7]; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase-BLOCKING8); double bValue=bBase[i]; b0 -= bValue * aBase[0]; b1 -= bValue * aBase[1]; b2 -= bValue * aBase[2]; b3 -= bValue * aBase[3]; b4 -= bValue * aBase[4]; b5 -= bValue * aBase[5]; b6 -= bValue * aBase[6]; b7 -= bValue * aBase[7]; } bBase2[0]=b0; bBase2[1]=b1; bBase2[2]=b2; bBase2[3]=b3; bBase2[4]=b4; bBase2[5]=b5; bBase2[6]=b6; bBase2[7]=b7; #endif #else __m256d b0=_mm256_load_pd(bBase2); __m256d b1=_mm256_load_pd(bBase2+4); for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase5-BLOCKING8); __m256d bb = _mm256_broadcast_sd(bBase+i); __m256d a0 = _mm256_load_pd(aBase); b0 -= a0*bb; __m256d a1 = _mm256_load_pd(aBase+4); b1 -= a1*bb; } //_mm256_store_pd (bBase2, b0); *reinterpret_cast<__m256d *>(bBase2)=b0; //_mm256_store_pd (bBase2+4, b1); *reinterpret_cast<__m256d *>(bBase2+4)=b1; #endif } } } } void CoinAbcDtrsm1(int m, double * COIN_RESTRICT a,double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 1 Left Upper NoTranspose NonUnit for (int kkk=m-BLOCKING8;kkk>=0;kkk-=UNROLL_DTRSM*BLOCKING8) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { const double * COIN_RESTRICT aBase = a+m*ii+ii*BLOCKING8; double * COIN_RESTRICT bBase = b+ii; for (int i=BLOCKING8-1;i>=0;i--) { bBase[i] *= aBase[i*(BLOCKING8+1)]; for (int k=i-1;k>=0;k--) { bBase[k] -= bBase[i]*aBase[k+i*BLOCKING8]; } } double * COIN_RESTRICT bBase2 = bBase; for (int iii=ii;iii>mm;iii-=BLOCKING8) { bBase2 -= BLOCKING8; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; coin_prefetch_const(aBase-BLOCKING8); for (int k=BLOCKING8-1;k>=0;k--) { bBase2[k] -= bBase[i]*aBase[k]; } } } } dtrsm1(kkk, 0, mm, m, a, b); } } static void dtrsm2(int kkk, int first, int last, int m, double * COIN_RESTRICT a,double * COIN_RESTRICT b) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); assert ((last-first)%BLOCKING8==0); if (last-first>CILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm2(kkk,first,mid,m,a,b); dtrsm2(kkk,mid,last,m,a,b); cilk_sync; } else { for (int iii=last-BLOCKING8;iii>=first;iii-=BLOCKING8) { for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { const double * COIN_RESTRICT bBase = b+ii; double * COIN_RESTRICT bBase2=b+iii; const double * COIN_RESTRICT aBase=a+ii*BLOCKING8+m*iii+BLOCKING8X8; for (int j=BLOCKING8-1;j>=0;j-=4) { double bValue0=bBase2[j]; double bValue1=bBase2[j-1]; double bValue2=bBase2[j-2]; double bValue3=bBase2[j-3]; bValue0 -= aBase[-1*BLOCKING8+7]*bBase[7]; bValue1 -= aBase[-2*BLOCKING8+7]*bBase[7]; bValue2 -= aBase[-3*BLOCKING8+7]*bBase[7]; bValue3 -= aBase[-4*BLOCKING8+7]*bBase[7]; bValue0 -= aBase[-1*BLOCKING8+6]*bBase[6]; bValue1 -= aBase[-2*BLOCKING8+6]*bBase[6]; bValue2 -= aBase[-3*BLOCKING8+6]*bBase[6]; bValue3 -= aBase[-4*BLOCKING8+6]*bBase[6]; bValue0 -= aBase[-1*BLOCKING8+5]*bBase[5]; bValue1 -= aBase[-2*BLOCKING8+5]*bBase[5]; bValue2 -= aBase[-3*BLOCKING8+5]*bBase[5]; bValue3 -= aBase[-4*BLOCKING8+5]*bBase[5]; bValue0 -= aBase[-1*BLOCKING8+4]*bBase[4]; bValue1 -= aBase[-2*BLOCKING8+4]*bBase[4]; bValue2 -= aBase[-3*BLOCKING8+4]*bBase[4]; bValue3 -= aBase[-4*BLOCKING8+4]*bBase[4]; bValue0 -= aBase[-1*BLOCKING8+3]*bBase[3]; bValue1 -= aBase[-2*BLOCKING8+3]*bBase[3]; bValue2 -= aBase[-3*BLOCKING8+3]*bBase[3]; bValue3 -= aBase[-4*BLOCKING8+3]*bBase[3]; bValue0 -= aBase[-1*BLOCKING8+2]*bBase[2]; bValue1 -= aBase[-2*BLOCKING8+2]*bBase[2]; bValue2 -= aBase[-3*BLOCKING8+2]*bBase[2]; bValue3 -= aBase[-4*BLOCKING8+2]*bBase[2]; bValue0 -= aBase[-1*BLOCKING8+1]*bBase[1]; bValue1 -= aBase[-2*BLOCKING8+1]*bBase[1]; bValue2 -= aBase[-3*BLOCKING8+1]*bBase[1]; bValue3 -= aBase[-4*BLOCKING8+1]*bBase[1]; bValue0 -= aBase[-1*BLOCKING8+0]*bBase[0]; bValue1 -= aBase[-2*BLOCKING8+0]*bBase[0]; bValue2 -= aBase[-3*BLOCKING8+0]*bBase[0]; bValue3 -= aBase[-4*BLOCKING8+0]*bBase[0]; bBase2[j]=bValue0; bBase2[j-1]=bValue1; bBase2[j-2]=bValue2; bBase2[j-3]=bValue3; aBase -= 4*BLOCKING8; } } } } } void CoinAbcDtrsm2(int m, double * COIN_RESTRICT a,double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 2 Left Lower Transpose Unit for (int kkk=m-BLOCKING8;kkk>=0;kkk-=UNROLL_DTRSM*BLOCKING8) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { double * COIN_RESTRICT bBase = b+ii; double * COIN_RESTRICT bBase2 = bBase; const double * COIN_RESTRICT aBase=a+m*ii+(ii+BLOCKING8)*BLOCKING8; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; for (int k=i+1;k=mm;iii-=BLOCKING8) { bBase2 -= BLOCKING8; assert (bBase2==b+iii); aBase -= m*BLOCKING8; const double * COIN_RESTRICT aBase2 = aBase+BLOCKING8X8; for (int i=BLOCKING8-1;i>=0;i--) { aBase2 -= BLOCKING8; for (int k=BLOCKING8-1;k>=0;k--) { bBase2[i] -= aBase2[k]*bBase[k]; } } } } dtrsm2(kkk, 0, mm, m, a, b); } } #define UNROLL_DTRSM3 16 #define CILK_DTRSM3 32 static void dtrsm3(int kkk, int first, int last, int m, double * COIN_RESTRICT a,double * COIN_RESTRICT b) { //int mm=CoinMin(kkk+UNROLL_DTRSM3*BLOCKING8,m); assert ((last-first)%BLOCKING8==0); if (last-first>CILK_DTRSM3) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm3(kkk,first,mid,m,a,b); dtrsm3(kkk,mid,last,m,a,b); cilk_sync; } else { for (int kk=0;kklargest) { largest=value; pivotRow2=i; } } // other blocks int iBias=0; for (int ii=BLOCKING8;iilargest) { largest=value; pivotRow2=i; iBias=ii; } } } pivotRow=pivotRow2+iBias; ipiv[j]=pivotRow; if (largest) { if (j!=pivotRow) { double * COIN_RESTRICT aTop=aThis3; double * COIN_RESTRICT aNotTop=aThis3+iBias*BLOCKING8; for (int i=0;i=end CoinAbcDlaswp(n-end,a+end*lda,lda,start,end,ipiv); CoinAbcDtrsmFactor(newSize,n-end,a+(start*lda+start*BLOCKING8),lda); CoinAbcDgemm(n-end,n-end,newSize, a+start*lda+end*BLOCKING8,lda, a+end*lda+start*BLOCKING8,a+end*lda+end*BLOCKING8 #if ABC_PARALLEL==2 ,parallelMode #endif ); } } else { return returnCode; } } } return 0; } void CoinAbcDgetrs(char trans,int m, double * COIN_RESTRICT a, double * COIN_RESTRICT work) { assert ((m&(BLOCKING8-1))==0); if (trans=='N') { //CoinAbcDlaswp1(work,m,ipiv); CoinAbcDtrsm0(m,a,work); CoinAbcDtrsm1(m,a,work); } else { assert (trans=='T'); CoinAbcDtrsm3(m,a,work); CoinAbcDtrsm2(m,a,work); //CoinAbcDlaswp1Backwards(work,m,ipiv); } } #ifdef ABC_LONG_FACTORIZATION /// ****** Start long double version /* type 0 Left Lower NoTranspose Unit 1 Left Upper NoTranspose NonUnit 2 Left Lower Transpose Unit 3 Left Upper Transpose NonUnit */ static void CoinAbcDtrsmFactor(int m, int n, long double * COIN_RESTRICT a,int lda) { assert ((m&(BLOCKING8-1))==0&&(n&(BLOCKING8-1))==0); assert (m==BLOCKING8); // 0 Left Lower NoTranspose Unit /* entry for column j and row i (when multiple of BLOCKING8) is at aBlocked+j*m+i*BLOCKING8 */ long double * COIN_RESTRICT aBase2 = a; long double * COIN_RESTRICT bBase2 = aBase2+lda*BLOCKING8; for (int jj=0;jjCILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm0(kkk,first,mid,m,a,b); dtrsm0(kkk,mid,last,m,a,b); cilk_sync; } else { const long double * COIN_RESTRICT aBaseA = a+UNROLL_DTRSM*BLOCKING8X8+kkk*BLOCKING8; aBaseA += (first-mm)*BLOCKING8-BLOCKING8X8; aBaseA += m*kkk; for (int ii=first;ii(bBaseI)=b0; //_mm256_store_pd (bBaseI+4, b1); *reinterpret_cast<__m256d *>(bBaseI+4)=b1; #endif } } } } void CoinAbcDtrsm0(int m, long double * COIN_RESTRICT a,long double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 0 Left Lower NoTranspose Unit for (int kkk=0;kkkCILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm1(kkk,first,mid,m,a,b); dtrsm1(kkk,mid,last,m,a,b); cilk_sync; } else { for (int iii=last-BLOCKING8;iii>=first;iii-=BLOCKING8) { long double * COIN_RESTRICT bBase2 = b+iii; const long double * COIN_RESTRICT aBaseA= a+BLOCKING8X8+BLOCKING8*iii; for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { long double * COIN_RESTRICT bBase = b+ii; const long double * COIN_RESTRICT aBase=aBaseA+m*ii; #if AVX2 !=2 #ifndef ALTERNATE_INNER for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase-BLOCKING8); for (int k=BLOCKING8-1;k>=0;k--) { bBase2[k] -= bBase[i]*aBase[k]; } } #else long double b0=bBase2[0]; long double b1=bBase2[1]; long double b2=bBase2[2]; long double b3=bBase2[3]; long double b4=bBase2[4]; long double b5=bBase2[5]; long double b6=bBase2[6]; long double b7=bBase2[7]; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase-BLOCKING8); long double bValue=bBase[i]; b0 -= bValue * aBase[0]; b1 -= bValue * aBase[1]; b2 -= bValue * aBase[2]; b3 -= bValue * aBase[3]; b4 -= bValue * aBase[4]; b5 -= bValue * aBase[5]; b6 -= bValue * aBase[6]; b7 -= bValue * aBase[7]; } bBase2[0]=b0; bBase2[1]=b1; bBase2[2]=b2; bBase2[3]=b3; bBase2[4]=b4; bBase2[5]=b5; bBase2[6]=b6; bBase2[7]=b7; #endif #else __m256d b0=_mm256_load_pd(bBase2); __m256d b1=_mm256_load_pd(bBase2+4); for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; //coin_prefetch_const(aBase5-BLOCKING8); __m256d bb = _mm256_broadcast_sd(bBase+i); __m256d a0 = _mm256_load_pd(aBase); b0 -= a0*bb; __m256d a1 = _mm256_load_pd(aBase+4); b1 -= a1*bb; } //_mm256_store_pd (bBase2, b0); *reinterpret_cast<__m256d *>(bBase2)=b0; //_mm256_store_pd (bBase2+4, b1); *reinterpret_cast<__m256d *>(bBase2+4)=b1; #endif } } } } void CoinAbcDtrsm1(int m, long double * COIN_RESTRICT a,long double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 1 Left Upper NoTranspose NonUnit for (int kkk=m-BLOCKING8;kkk>=0;kkk-=UNROLL_DTRSM*BLOCKING8) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { const long double * COIN_RESTRICT aBase = a+m*ii+ii*BLOCKING8; long double * COIN_RESTRICT bBase = b+ii; for (int i=BLOCKING8-1;i>=0;i--) { bBase[i] *= aBase[i*(BLOCKING8+1)]; for (int k=i-1;k>=0;k--) { bBase[k] -= bBase[i]*aBase[k+i*BLOCKING8]; } } long double * COIN_RESTRICT bBase2 = bBase; for (int iii=ii;iii>mm;iii-=BLOCKING8) { bBase2 -= BLOCKING8; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; coin_prefetch_const(aBase-BLOCKING8); for (int k=BLOCKING8-1;k>=0;k--) { bBase2[k] -= bBase[i]*aBase[k]; } } } } dtrsm1(kkk, 0, mm, m, a, b); } } static void dtrsm2(int kkk, int first, int last, int m, long double * COIN_RESTRICT a,long double * COIN_RESTRICT b) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); assert ((last-first)%BLOCKING8==0); if (last-first>CILK_DTRSM) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm2(kkk,first,mid,m,a,b); dtrsm2(kkk,mid,last,m,a,b); cilk_sync; } else { for (int iii=last-BLOCKING8;iii>=first;iii-=BLOCKING8) { for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { const long double * COIN_RESTRICT bBase = b+ii; long double * COIN_RESTRICT bBase2=b+iii; const long double * COIN_RESTRICT aBase=a+ii*BLOCKING8+m*iii+BLOCKING8X8; for (int j=BLOCKING8-1;j>=0;j-=4) { long double bValue0=bBase2[j]; long double bValue1=bBase2[j-1]; long double bValue2=bBase2[j-2]; long double bValue3=bBase2[j-3]; bValue0 -= aBase[-1*BLOCKING8+7]*bBase[7]; bValue1 -= aBase[-2*BLOCKING8+7]*bBase[7]; bValue2 -= aBase[-3*BLOCKING8+7]*bBase[7]; bValue3 -= aBase[-4*BLOCKING8+7]*bBase[7]; bValue0 -= aBase[-1*BLOCKING8+6]*bBase[6]; bValue1 -= aBase[-2*BLOCKING8+6]*bBase[6]; bValue2 -= aBase[-3*BLOCKING8+6]*bBase[6]; bValue3 -= aBase[-4*BLOCKING8+6]*bBase[6]; bValue0 -= aBase[-1*BLOCKING8+5]*bBase[5]; bValue1 -= aBase[-2*BLOCKING8+5]*bBase[5]; bValue2 -= aBase[-3*BLOCKING8+5]*bBase[5]; bValue3 -= aBase[-4*BLOCKING8+5]*bBase[5]; bValue0 -= aBase[-1*BLOCKING8+4]*bBase[4]; bValue1 -= aBase[-2*BLOCKING8+4]*bBase[4]; bValue2 -= aBase[-3*BLOCKING8+4]*bBase[4]; bValue3 -= aBase[-4*BLOCKING8+4]*bBase[4]; bValue0 -= aBase[-1*BLOCKING8+3]*bBase[3]; bValue1 -= aBase[-2*BLOCKING8+3]*bBase[3]; bValue2 -= aBase[-3*BLOCKING8+3]*bBase[3]; bValue3 -= aBase[-4*BLOCKING8+3]*bBase[3]; bValue0 -= aBase[-1*BLOCKING8+2]*bBase[2]; bValue1 -= aBase[-2*BLOCKING8+2]*bBase[2]; bValue2 -= aBase[-3*BLOCKING8+2]*bBase[2]; bValue3 -= aBase[-4*BLOCKING8+2]*bBase[2]; bValue0 -= aBase[-1*BLOCKING8+1]*bBase[1]; bValue1 -= aBase[-2*BLOCKING8+1]*bBase[1]; bValue2 -= aBase[-3*BLOCKING8+1]*bBase[1]; bValue3 -= aBase[-4*BLOCKING8+1]*bBase[1]; bValue0 -= aBase[-1*BLOCKING8+0]*bBase[0]; bValue1 -= aBase[-2*BLOCKING8+0]*bBase[0]; bValue2 -= aBase[-3*BLOCKING8+0]*bBase[0]; bValue3 -= aBase[-4*BLOCKING8+0]*bBase[0]; bBase2[j]=bValue0; bBase2[j-1]=bValue1; bBase2[j-2]=bValue2; bBase2[j-3]=bValue3; aBase -= 4*BLOCKING8; } } } } } void CoinAbcDtrsm2(int m, long double * COIN_RESTRICT a,long double * COIN_RESTRICT b) { assert ((m&(BLOCKING8-1))==0); // 2 Left Lower Transpose Unit for (int kkk=m-BLOCKING8;kkk>=0;kkk-=UNROLL_DTRSM*BLOCKING8) { int mm=CoinMax(0,kkk-(UNROLL_DTRSM-1)*BLOCKING8); for (int ii=kkk;ii>=mm;ii-=BLOCKING8) { long double * COIN_RESTRICT bBase = b+ii; long double * COIN_RESTRICT bBase2 = bBase; const long double * COIN_RESTRICT aBase=a+m*ii+(ii+BLOCKING8)*BLOCKING8; for (int i=BLOCKING8-1;i>=0;i--) { aBase -= BLOCKING8; for (int k=i+1;k=mm;iii-=BLOCKING8) { bBase2 -= BLOCKING8; assert (bBase2==b+iii); aBase -= m*BLOCKING8; const long double * COIN_RESTRICT aBase2 = aBase+BLOCKING8X8; for (int i=BLOCKING8-1;i>=0;i--) { aBase2 -= BLOCKING8; for (int k=BLOCKING8-1;k>=0;k--) { bBase2[i] -= aBase2[k]*bBase[k]; } } } } dtrsm2(kkk, 0, mm, m, a, b); } } #define UNROLL_DTRSM3 16 #define CILK_DTRSM3 32 static void dtrsm3(int kkk, int first, int last, int m, long double * COIN_RESTRICT a,long double * COIN_RESTRICT b) { //int mm=CoinMin(kkk+UNROLL_DTRSM3*BLOCKING8,m); assert ((last-first)%BLOCKING8==0); if (last-first>CILK_DTRSM3) { int mid=((first+last)>>4)<<3; cilk_spawn dtrsm3(kkk,first,mid,m,a,b); dtrsm3(kkk,mid,last,m,a,b); cilk_sync; } else { for (int kk=0;kklargest) { largest=value; pivotRow2=i; } } // other blocks int iBias=0; for (int ii=BLOCKING8;iilargest) { largest=value; pivotRow2=i; iBias=ii; } } } pivotRow=pivotRow2+iBias; ipiv[j]=pivotRow; if (largest) { if (j!=pivotRow) { long double * COIN_RESTRICT aTop=aThis3; long double * COIN_RESTRICT aNotTop=aThis3+iBias*BLOCKING8; for (int i=0;i=end CoinAbcDlaswp(n-end,a+end*lda,lda,start,end,ipiv); CoinAbcDtrsmFactor(newSize,n-end,a+(start*lda+start*BLOCKING8),lda); CoinAbcDgemm(n-end,n-end,newSize, a+start*lda+end*BLOCKING8,lda, a+end*lda+start*BLOCKING8,a+end*lda+end*BLOCKING8 #if ABC_PARALLEL==2 ,parallelMode #endif ); } } else { return returnCode; } } } return 0; } void CoinAbcDgetrs(char trans,int m, long double * COIN_RESTRICT a, long double * COIN_RESTRICT work) { assert ((m&(BLOCKING8-1))==0); if (trans=='N') { //CoinAbcDlaswp1(work,m,ipiv); CoinAbcDtrsm0(m,a,work); CoinAbcDtrsm1(m,a,work); } else { assert (trans=='T'); CoinAbcDtrsm3(m,a,work); CoinAbcDtrsm2(m,a,work); //CoinAbcDlaswp1Backwards(work,m,ipiv); } } #endif Clp-1.15.10/src/AbcDualRowDantzig.cpp0000644000076600007660000003122112101105055015637 0ustar coincoin/* $Id: AbcDualRowDantzig.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "AbcSimplex.hpp" #include "AbcDualRowDantzig.hpp" #include "AbcSimplexFactorization.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #ifndef CLP_DUAL_COLUMN_MULTIPLIER #define CLP_DUAL_COLUMN_MULTIPLIER 1.01 #endif //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcDualRowDantzig::AbcDualRowDantzig () : AbcDualRowPivot(), infeasible_(NULL) { type_ = 1; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcDualRowDantzig::AbcDualRowDantzig (const AbcDualRowDantzig & rhs) : AbcDualRowPivot(rhs), infeasible_(NULL) { model_ = rhs.model_; if ((model_ && model_->whatsChanged() & 1) != 0) { if (rhs.infeasible_) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcDualRowDantzig::~AbcDualRowDantzig () { delete infeasible_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcDualRowDantzig & AbcDualRowDantzig::operator=(const AbcDualRowDantzig& rhs) { if (this != &rhs) { AbcDualRowPivot::operator=(rhs); delete infeasible_; if (rhs.infeasible_ != NULL) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } } return *this; } /* 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights */ void AbcDualRowDantzig::saveWeights(AbcSimplex * model, int mode) { model_ = model; int numberRows = model_->numberRows(); if (mode == 1) { // Check if size has changed if (infeasible_&&infeasible_->capacity() != numberRows) { // size has changed - clear everything delete infeasible_; infeasible_ = NULL; } } else if (mode !=3 && !infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberRows); } if (mode >= 2) { recomputeInfeasibilities(); } } // Recompute infeasibilities void AbcDualRowDantzig::recomputeInfeasibilities() { int numberRows = model_->numberRows(); infeasible_->clear(); double tolerance = model_->currentPrimalTolerance(); const double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); for (int iRow = 0; iRow < numberRows; iRow++) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; if (value < lower - tolerance) { value -= lower; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store in list infeasible_->quickAdd(iRow, fabs(value)); } else if (value > upper + tolerance) { value -= upper; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store in list infeasible_->quickAdd(iRow, fabs(value)); } } } #if ABC_PARALLEL==2 static void choose(CoinIndexedVector * infeasible, int & chosenRowSave,double & largestSave, int first, int last, double tolerance) { if (last-first>256) { int mid=(last+first)>>1; int chosenRow2=chosenRowSave; double largest2=largestSave; cilk_spawn choose(infeasible,chosenRow2,largest2, first, mid, tolerance); choose(infeasible,chosenRowSave,largestSave, mid, last, tolerance); cilk_sync; if (largest2>largestSave) { largestSave=largest2; chosenRowSave=chosenRow2; } } else { const int * index=infeasible->getIndices(); const double * infeas=infeasible->denseVector(); double largest=largestSave; int chosenRow=chosenRowSave; for (int i = first; i < last; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > largest) { largest=value; chosenRow=iRow; } } chosenRowSave=chosenRow; largestSave=largest; } } #endif // Returns pivot row, -1 if none int AbcDualRowDantzig::pivotRow() { assert(model_); double * COIN_RESTRICT infeas = infeasible_->denseVector(); int * COIN_RESTRICT index = infeasible_->getIndices(); int number = infeasible_->getNumElements(); double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error if (model_->largestPrimalError() > 1.0e-8) tolerance *= model_->largestPrimalError() / 1.0e-8; int numberRows = model_->numberRows(); const double * COIN_RESTRICT solutionBasic=model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic=model_->lowerBasic(); const double * COIN_RESTRICT upperBasic=model_->upperBasic(); const int * pivotVariable = model_->pivotVariable(); // code so has list of infeasibilities (like steepest) int numberWanted=CoinMax(2000,numberRows>>4); numberWanted=CoinMax(numberWanted,number>>2); if (model_->largestPrimalError() > 1.0e-3) numberWanted = number + 1; // be safe // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; double largest = tolerance; int chosenRow = -1; int saveNumberWanted=numberWanted; #ifdef DO_REDUCE bool doReduce=true; int lastChosen=-1; double lastLargest=0.0; #endif for (int iPass = 0; iPass < 2; iPass++) { int endThis = start[2*iPass+1]; int startThis=start[2*iPass]; while (startThis=0); if (model_->flagged(pivotVariable[chosenRow])|| (solutionBasic[chosenRow] <= upperBasic[chosenRow] + tolerance && solutionBasic[chosenRow] >= lowerBasic[chosenRow] - tolerance)) { doReduce=false; chosenRow=lastChosen; largest=lastLargest; } else { lastChosen=chosenRow; lastLargest=largest; } } } if (!doReduce) { #endif for (int i = startThis; i < end; i++) { int iRow = index[i]; double value = infeas[iRow]; if (value > largest) { if (!model_->flagged(pivotVariable[iRow])) { if (solutionBasic[iRow] > upperBasic[iRow] + tolerance || solutionBasic[iRow] < lowerBasic[iRow] - tolerance) { chosenRow = iRow; largest = value; } } } } #ifdef DO_REDUCE } #endif numberWanted-=(end-startThis); if (!numberWanted) { if(chosenRow>=0) break; else numberWanted=(saveNumberWanted+1)>>1; } startThis=end; } if (!numberWanted) { if(chosenRow>=0) break; else numberWanted=(saveNumberWanted+1)>>1; } } return chosenRow; } // FT update and returns pivot alpha double AbcDualRowDantzig::updateWeights(CoinIndexedVector & input,CoinIndexedVector & updatedColumn) { // Do FT update model_->factorization()->updateColumnFT(updatedColumn); // pivot element double alpha = 0.0; // look at updated column double * work = updatedColumn.denseVector(); int pivotRow = model_->lastPivotRow(); assert (pivotRow == model_->pivotRow()); assert (!updatedColumn.packedMode()); alpha = work[pivotRow]; return alpha; } double AbcDualRowDantzig::updateWeights1(CoinIndexedVector & input,CoinIndexedVector & updateColumn) { return updateWeights(input,updateColumn); } #if ABC_PARALLEL==2 static void update(int first, int last, const int * COIN_RESTRICT which, double * COIN_RESTRICT work, const double * COIN_RESTRICT lowerBasic,double * COIN_RESTRICT solutionBasic, const double * COIN_RESTRICT upperBasic,double theta,double tolerance) { if (last-first>256) { int mid=(last+first)>>1; cilk_spawn update(first,mid,which,work,lowerBasic,solutionBasic, upperBasic,theta,tolerance); update(mid,last,which,work,lowerBasic,solutionBasic, upperBasic,theta,tolerance); cilk_sync; } else { for (int i = first; i < last; i++) { int iRow = which[i]; double updateValue = work[iRow]; double value = solutionBasic[iRow]; double change = theta * updateValue; value -= change; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; solutionBasic[iRow] = value; if (value < lower - tolerance) { value -= lower; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif } else if (value > upper + tolerance) { value -= upper; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif } else { // feasible value=0.0; } // store work[iRow]=fabs(value); } } } #endif /* Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ void AbcDualRowDantzig::updatePrimalSolution(CoinIndexedVector & primalUpdate, double theta) { double * COIN_RESTRICT work = primalUpdate.denseVector(); int numberNonZero = primalUpdate.getNumElements(); int * which = primalUpdate.getIndices(); double tolerance = model_->currentPrimalTolerance(); double * COIN_RESTRICT infeas = infeasible_->denseVector(); double * COIN_RESTRICT solutionBasic = model_->solutionBasic(); const double * COIN_RESTRICT lowerBasic = model_->lowerBasic(); const double * COIN_RESTRICT upperBasic = model_->upperBasic(); assert (!primalUpdate.packedMode()); #if 0 //ABC_PARALLEL==2 update(0,numberNonZero,which,work, lowerBasic,solutionBasic,upperBasic, theta,tolerance); for (int i = 0; i < numberNonZero; i++) { int iRow = which[i]; double infeasibility=work[iRow]; work[iRow]=0.0; if (infeasibility) { if (infeas[iRow]) infeas[iRow] = infeasibility; // already there else infeasible_->quickAdd(iRow, infeasibility); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } #else for (int i = 0; i < numberNonZero; i++) { int iRow = which[i]; double updateValue = work[iRow]; work[iRow]=0.0; double value = solutionBasic[iRow]; double change = theta * updateValue; value -= change; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; solutionBasic[iRow] = value; if (value < lower - tolerance) { value -= lower; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store in list if (infeas[iRow]) infeas[iRow] = fabs(value); // already there else infeasible_->quickAdd(iRow, fabs(value)); } else if (value > upper + tolerance) { value -= upper; #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store in list if (infeas[iRow]) infeas[iRow] = fabs(value); // already there else infeasible_->quickAdd(iRow, fabs(value)); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } #endif primalUpdate.setNumElements(0); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- AbcDualRowPivot * AbcDualRowDantzig::clone(bool CopyData) const { if (CopyData) { return new AbcDualRowDantzig(*this); } else { return new AbcDualRowDantzig(); } } Clp-1.15.10/src/AbcNonLinearCost.hpp0000644000076600007660000002147412101105055015475 0ustar coincoin/* $Id: AbcNonLinearCost.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcNonLinearCost_H #define AbcNonLinearCost_H #include "CoinPragma.hpp" #include "AbcCommon.hpp" class AbcSimplex; class CoinIndexedVector; /** Trivial class to deal with non linear costs I don't make any explicit assumptions about convexity but I am sure I do make implicit ones. One interesting idea for normal LP's will be to allow non-basic variables to come into basis as infeasible i.e. if variable at lower bound has very large positive reduced cost (when problem is infeasible) could it reduce overall problem infeasibility more by bringing it into basis below its lower bound. Another feature would be to automatically discover when problems are convex piecewise linear and re-formulate to use non-linear. I did some work on this many years ago on "grade" problems, but while it improved primal interior point algorithms were much better for that particular problem. */ /* status has original status and current status 0 - below lower so stored is upper 1 - in range 2 - above upper so stored is lower 4 - (for current) - same as original */ #define CLP_BELOW_LOWER 0 #define CLP_FEASIBLE 1 #define CLP_ABOVE_UPPER 2 #define CLP_SAME 4 inline int originalStatus(unsigned char status) { return (status & 15); } inline int currentStatus(unsigned char status) { return (status >> 4); } inline void setOriginalStatus(unsigned char & status, int value) { status = static_cast(status & ~15); status = static_cast(status | value); } inline void setCurrentStatus(unsigned char &status, int value) { status = static_cast(status & ~(15 << 4)); status = static_cast(status | (value << 4)); } inline void setInitialStatus(unsigned char &status) { status = static_cast(CLP_FEASIBLE | (CLP_SAME << 4)); } inline void setSameStatus(unsigned char &status) { status = static_cast(status & ~(15 << 4)); status = static_cast(status | (CLP_SAME << 4)); } class AbcNonLinearCost { public: /**@name Constructors, destructor */ //@{ /// Default constructor. AbcNonLinearCost(); /** Constructor from simplex. This will just set up wasteful arrays for linear, but later may do dual analysis and even finding duplicate columns . */ AbcNonLinearCost(AbcSimplex * model); /// Destructor ~AbcNonLinearCost(); // Copy AbcNonLinearCost(const AbcNonLinearCost&); // Assignment AbcNonLinearCost& operator=(const AbcNonLinearCost&); //@} /**@name Actual work in primal */ //@{ /** Changes infeasible costs and computes number and cost of infeas Puts all non-basic (non free) variables to bounds and all free variables to zero if oldTolerance is non-zero - but does not move those <= oldTolerance away*/ void checkInfeasibilities(double oldTolerance = 0.0); /** Changes infeasible costs for each variable The indices are row indices and need converting to sequences */ void checkInfeasibilities(int numberInArray, const int * index); /** Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. On input array is empty (but indices exist). On exit just changed costs will be stored as normal CoinIndexedVector */ void checkChanged(int numberInArray, CoinIndexedVector * update); /** Goes through one bound for each variable. If multiplier*work[iRow]>0 goes down, otherwise up. The indices are row indices and need converting to sequences Temporary offsets may be set Rhs entries are increased */ void goThru(int numberInArray, double multiplier, const int * index, const double * work, double * rhs); /** Takes off last iteration (i.e. offsets closer to 0) */ void goBack(int numberInArray, const int * index, double * rhs); /** Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. At the end of this all temporary offsets are zero */ void goBackAll(const CoinIndexedVector * update); /// Temporary zeroing of feasible costs void zapCosts(); /// Refreshes costs always makes row costs zero void refreshCosts(const double * columnCosts); /// Puts feasible bounds into lower and upper void feasibleBounds(); /// Refresh - assuming regions OK void refresh(); /// Refresh - from original void refreshFromPerturbed(double tolerance); /** Sets bounds and cost for one variable Returns change in cost May need to be inline for speed */ double setOne(int sequence, double solutionValue); /** Sets bounds and cost for one variable Returns change in cost May need to be inline for speed */ double setOneBasic(int iRow, double solutionValue); /** Sets bounds and cost for outgoing variable may change value Returns direction */ int setOneOutgoing(int sequence, double &solutionValue); /// Returns nearest bound double nearest(int iRow, double solutionValue); /** Returns change in cost - one down if alpha >0.0, up if <0.0 Value is current - new */ inline double changeInCost(int /*sequence*/, double alpha) const { return (alpha > 0.0) ? infeasibilityWeight_ : -infeasibilityWeight_; } inline double changeUpInCost(int /*sequence*/) const { return -infeasibilityWeight_; } inline double changeDownInCost(int /*sequence*/) const { return infeasibilityWeight_; } /// This also updates next bound inline double changeInCost(int iRow, double alpha, double &rhs) { int sequence=model_->pivotVariable()[iRow]; double returnValue = 0.0; unsigned char iStatus = status_[sequence]; int iWhere = currentStatus(iStatus); if (iWhere == CLP_SAME) iWhere = originalStatus(iStatus); // rhs always increases if (iWhere == CLP_FEASIBLE) { if (alpha > 0.0) { // going below iWhere = CLP_BELOW_LOWER; rhs = COIN_DBL_MAX; } else { // going above iWhere = CLP_ABOVE_UPPER; rhs = COIN_DBL_MAX; } } else if (iWhere == CLP_BELOW_LOWER) { assert (alpha < 0); // going feasible iWhere = CLP_FEASIBLE; rhs += bound_[sequence] - model_->upperRegion()[sequence]; } else { assert (iWhere == CLP_ABOVE_UPPER); // going feasible iWhere = CLP_FEASIBLE; rhs += model_->lowerRegion()[sequence] - bound_[sequence]; } setCurrentStatus(status_[sequence], iWhere); returnValue = fabs(alpha) * infeasibilityWeight_; return returnValue; } //@} /**@name Gets and sets */ //@{ /// Number of infeasibilities inline int numberInfeasibilities() const { return numberInfeasibilities_; } /// Change in cost inline double changeInCost() const { return changeCost_; } /// Feasible cost inline double feasibleCost() const { return feasibleCost_; } /// Feasible cost with offset and direction (i.e. for reporting) double feasibleReportCost() const; /// Sum of infeasibilities inline double sumInfeasibilities() const { return sumInfeasibilities_; } /// Largest infeasibility inline double largestInfeasibility() const { return largestInfeasibility_; } /// Average theta inline double averageTheta() const { return averageTheta_; } inline void setAverageTheta(double value) { averageTheta_ = value; } inline void setChangeInCost(double value) { changeCost_ = value; } //@} ///@name Private functions to deal with infeasible regions inline unsigned char * statusArray() const { return status_; } inline int getCurrentStatus(int sequence) {return (status_[sequence] >> 4);} /// For debug void validate(); //@} private: /**@name Data members */ //@{ /// Change in cost because of infeasibilities double changeCost_; /// Feasible cost double feasibleCost_; /// Current infeasibility weight double infeasibilityWeight_; /// Largest infeasibility double largestInfeasibility_; /// Sum of infeasibilities double sumInfeasibilities_; /// Average theta - kept here as only for primal double averageTheta_; /// Number of rows (mainly for checking and copy) int numberRows_; /// Number of columns (mainly for checking and copy) int numberColumns_; /// Model AbcSimplex * model_; /// Number of infeasibilities found int numberInfeasibilities_; // new stuff /// Contains status at beginning and current unsigned char * status_; /// Bound which has been replaced in lower_ or upper_ double * bound_; /// Feasible cost array double * cost_; //@} }; #endif Clp-1.15.10/src/ClpDualRowPivot.cpp0000644000076600007660000000356111510657452015417 0ustar coincoin/* $Id: ClpDualRowPivot.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpDualRowPivot.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDualRowPivot::ClpDualRowPivot () : model_(NULL), type_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDualRowPivot::ClpDualRowPivot (const ClpDualRowPivot & source) : model_(source.model_), type_(source.type_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDualRowPivot::~ClpDualRowPivot () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDualRowPivot & ClpDualRowPivot::operator=(const ClpDualRowPivot& rhs) { if (this != &rhs) { type_ = rhs.type_; model_ = rhs.model_; } return *this; } void ClpDualRowPivot::saveWeights(ClpSimplex * model, int /*mode*/) { model_ = model; } // checks accuracy and may re-initialize (may be empty) void ClpDualRowPivot::checkAccuracy() { } void ClpDualRowPivot::unrollWeights() { } // Gets rid of all arrays void ClpDualRowPivot::clearArrays() { } Clp-1.15.10/src/ClpPdcoBase.cpp0000644000076600007660000000313212131314313014454 0ustar coincoin/* $Id: ClpPdcoBase.cpp 1941 2013-04-10 16:52:27Z 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). #include "CoinPragma.hpp" #include #include "ClpPdcoBase.hpp" #include "ClpPdco.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPdcoBase::ClpPdcoBase () : d1_(0.0), d2_(0.0), type_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPdcoBase::ClpPdcoBase (const ClpPdcoBase & source) : d1_(source.d1_), d2_(source.d2_), type_(source.type_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPdcoBase::~ClpPdcoBase () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPdcoBase & ClpPdcoBase::operator=(const ClpPdcoBase& rhs) { if (this != &rhs) { d1_ = rhs.d1_; d2_ = rhs.d2_; type_ = rhs.type_; } return *this; } Clp-1.15.10/src/MyMessageHandler.cpp0000644000076600007660000001300311557471077015551 0ustar coincoin/* $Id: MyMessageHandler.cpp 1726 2011-05-02 08:58:39Z 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) // move into CoinPragma.hpp ? #pragma warning(disable:4503) #endif #include #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpNonLinearCost.hpp" #include "MyMessageHandler.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyMessageHandler::MyMessageHandler () : CoinMessageHandler(), model_(NULL), feasibleExtremePoints_(), iterationNumber_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyMessageHandler::MyMessageHandler (const MyMessageHandler & rhs) : CoinMessageHandler(rhs), model_(rhs.model_), feasibleExtremePoints_(rhs.feasibleExtremePoints_), iterationNumber_(rhs.iterationNumber_) { } MyMessageHandler::MyMessageHandler (const CoinMessageHandler & rhs) : CoinMessageHandler(rhs), model_(NULL), feasibleExtremePoints_(), iterationNumber_(-1) { } // Constructor with pointer to model MyMessageHandler::MyMessageHandler(ClpSimplex * model, FILE * /*userPointer*/) : CoinMessageHandler(), model_(model), feasibleExtremePoints_(), iterationNumber_(-1) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyMessageHandler::~MyMessageHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyMessageHandler & MyMessageHandler::operator=(const MyMessageHandler& rhs) { if (this != &rhs) { CoinMessageHandler::operator=(rhs); model_ = rhs.model_; feasibleExtremePoints_ = rhs.feasibleExtremePoints_; iterationNumber_ = rhs.iterationNumber_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- CoinMessageHandler * MyMessageHandler::clone() const { return new MyMessageHandler(*this); } int MyMessageHandler::print() { if (currentSource() == "Clp") { if (currentMessage().externalNumber() == 102) { printf("There are %d primal infeasibilities\n", model_->nonLinearCost()->numberInfeasibilities()); // Feasibility if (!model_->nonLinearCost()->numberInfeasibilities()) { // Column solution int numberColumns = model_->numberColumns(); const double * solution = model_->solutionRegion(1); // Create vector to contain solution StdVectorDouble feasibleExtremePoint; const double *objective = model_->objective(); double objectiveValue = 0; if (!model_->columnScale()) { // No scaling for (int i = 0; i < numberColumns; i++) { feasibleExtremePoint.push_back(solution[i]); objectiveValue += solution[i] * objective[i]; } } else { // scaled const double * columnScale = model_->columnScale(); for (int i = 0; i < numberColumns; i++) { feasibleExtremePoint.push_back(solution[i]*columnScale[i]); objectiveValue += solution[i] * objective[i] * columnScale[i]; } } std::cout << "Objective " << objectiveValue << std::endl; // Save solution feasibleExtremePoints_.push_front(feasibleExtremePoint); // Want maximum of 10 solutions, so if more then 10 get rid of oldest size_t numExtremePointsSaved = feasibleExtremePoints_.size(); if ( numExtremePointsSaved >= 10 ) { feasibleExtremePoints_.pop_back(); assert( feasibleExtremePoints_.size() == numExtremePointsSaved - 1 ); }; } return 0; // skip printing } } // If one wants access to the message text, // it is available using method messageBuffer(). // For example, one could code: // std::cout < & MyMessageHandler::getFeasibleExtremePoints() const { return feasibleExtremePoints_; } void MyMessageHandler::clearFeasibleExtremePoints() { feasibleExtremePoints_.clear(); } Clp-1.15.10/src/AbcDualRowPivot.cpp0000644000076600007660000000426012101105055015343 0ustar coincoin/* $Id: AbcDualRowPivot.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "AbcSimplex.hpp" #include "AbcDualRowPivot.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcDualRowPivot::AbcDualRowPivot () : model_(NULL), type_(-1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcDualRowPivot::AbcDualRowPivot (const AbcDualRowPivot & source) : model_(source.model_), type_(source.type_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcDualRowPivot::~AbcDualRowPivot () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcDualRowPivot & AbcDualRowPivot::operator=(const AbcDualRowPivot& rhs) { if (this != &rhs) { type_ = rhs.type_; model_ = rhs.model_; } return *this; } void AbcDualRowPivot::saveWeights(AbcSimplex * model, int /*mode*/) { model_ = model; } // Recompute infeasibilities void AbcDualRowPivot::recomputeInfeasibilities() { } void AbcDualRowPivot::updatePrimalSolutionAndWeights(CoinIndexedVector & weightsVector, CoinIndexedVector & updateColumn, double theta) { // finish doing weights updateWeights2(weightsVector,updateColumn); updatePrimalSolution(updateColumn,theta); } // checks accuracy and may re-initialize (may be empty) void AbcDualRowPivot::checkAccuracy() { } // Gets rid of all arrays void AbcDualRowPivot::clearArrays() { } Clp-1.15.10/src/ClpPrimalColumnPivot.hpp0000644000076600007660000001146311571121105016435 0ustar coincoin/* $Id: ClpPrimalColumnPivot.hpp 1732 2011-05-31 08:09: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 ClpPrimalcolumnPivot_H #define ClpPrimalcolumnPivot_H class ClpSimplex; class CoinIndexedVector; //############################################################################# /** Primal Column Pivot Abstract Base Class Abstract Base Class for describing an interface to an algorithm to choose column pivot in primal simplex algorithm. For some algorithms e.g. Dantzig choice then some functions may be null. For Dantzig the only one of any importance is pivotColumn. If you wish to inherit from this look at ClpPrimalColumnDantzig.cpp as that is simplest version. */ class ClpPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none Normally updates reduced costs using result of last iteration before selecting incoming column. The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row Inside pivotColumn the pivotRow_ and reduced cost from last iteration are also used. So in the simplest case i.e. feasible we compute the row of the tableau corresponding to last pivot and add a multiple of this to current reduced costs. We can use other arrays to help updates */ virtual int pivotColumn(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) = 0; /// Updates weights - part 1 (may be empty) virtual void updateWeights(CoinIndexedVector * input); /** Saves any weights round factorization as pivot rows may change Will be empty unless steepest edge (will save model) May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) forces some initialization e.g. weights Also sets model */ virtual void saveWeights(ClpSimplex * model, int mode) = 0; /** Signals pivot row choice: -2 (default) - use normal pivot row choice -1 to numberRows-1 - use this (will be checked) way should be -1 to go to lower bound, +1 to upper bound */ virtual int pivotRow(double & way) { way = 0; return -2; } /// Gets rid of all arrays (may be empty) virtual void clearArrays(); /// Returns true if would not find any column virtual bool looksOptimal() const { return looksOptimal_; } /// Sets optimality flag (for advanced use) virtual void setLooksOptimal(bool flag) { looksOptimal_ = flag; } //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpPrimalColumnPivot(); /// Copy constructor ClpPrimalColumnPivot(const ClpPrimalColumnPivot &); /// Assignment operator ClpPrimalColumnPivot & operator=(const ClpPrimalColumnPivot& rhs); /// Destructor virtual ~ClpPrimalColumnPivot (); /// Clone virtual ClpPrimalColumnPivot * clone(bool copyData = true) const = 0; //@} ///@name Other //@{ /// Returns model inline ClpSimplex * model() { return model_; } /// Sets model inline void setModel(ClpSimplex * newmodel) { model_ = newmodel; } /// Returns type (above 63 is extra information) inline int type() { return type_; } /** Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ virtual int numberSprintColumns(int & numberIterations) const; /// Switch off sprint idea virtual void switchOffSprint(); /// Called when maximum pivots changes virtual void maximumPivotsChanged() {} //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Pointer to model ClpSimplex * model_; /// Type of column pivot algorithm int type_; /// Says if looks optimal (normally computed) bool looksOptimal_; //@} }; #ifndef CLP_PRIMAL_SLACK_MULTIPLIER #define CLP_PRIMAL_SLACK_MULTIPLIER 1.01 #endif #endif Clp-1.15.10/src/ClpDualRowPivot.hpp0000644000076600007660000000744611571121105015416 0ustar coincoin/* $Id: ClpDualRowPivot.hpp 1732 2011-05-31 08:09: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 ClpDualRowPivot_H #define ClpDualRowPivot_H class ClpSimplex; class CoinIndexedVector; //############################################################################# /** Dual Row Pivot Abstract Base Class Abstract Base Class for describing an interface to an algorithm to choose row pivot in dual simplex algorithm. For some algorithms e.g. Dantzig choice then some functions may be null. */ class ClpDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow() = 0; /** Updates weights and returns pivot alpha. Also does FT update */ virtual double updateWeights(CoinIndexedVector * input, CoinIndexedVector * spare, CoinIndexedVector * spare2, CoinIndexedVector * updatedColumn) = 0; /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function Would be faster if we kept basic regions, but on other hand it means everything is always in sync */ /* FIXME: this was pure virtul (=0). Why? */ virtual void updatePrimalSolution(CoinIndexedVector * input, double theta, double & changeInObjective) = 0; /** Saves any weights round factorization as pivot rows may change Will be empty unless steepest edge (will save model) May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) for strong branching - initialize , infeasibilities */ virtual void saveWeights(ClpSimplex * model, int mode); /// checks accuracy and may re-initialize (may be empty) virtual void checkAccuracy(); /// Gets rid of last update (may be empty) virtual void unrollWeights(); /// Gets rid of all arrays (may be empty) virtual void clearArrays(); /// Returns true if would not find any row virtual bool looksOptimal() const { return false; } /// Called when maximum pivots changes virtual void maximumPivotsChanged() {} //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpDualRowPivot(); /// Copy constructor ClpDualRowPivot(const ClpDualRowPivot &); /// Assignment operator ClpDualRowPivot & operator=(const ClpDualRowPivot& rhs); /// Destructor virtual ~ClpDualRowPivot (); /// Clone virtual ClpDualRowPivot * clone(bool copyData = true) const = 0; //@} ///@name Other //@{ /// Returns model inline ClpSimplex * model() { return model_; } /// Sets model (normally to NULL) inline void setModel(ClpSimplex * newmodel) { model_ = newmodel; } /// Returns type (above 63 is extra information) inline int type() { return type_; } //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Pointer to model ClpSimplex * model_; /// Type of row pivot algorithm int type_; //@} }; #ifndef CLP_DUAL_COLUMN_MULTIPLIER //#define CLP_DUAL_COLUMN_MULTIPLIER 0.99999 #endif #endif Clp-1.15.10/src/CoinAbcDenseFactorization.cpp0000644000076600007660000005576512101105055017370 0ustar coincoin/* $Id: CoinAbcDenseFactorization.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinUtilsConfig.h" #include "CoinPragma.hpp" #include #include #include "CoinAbcDenseFactorization.hpp" #include "CoinAbcCommonFactorization.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinFinite.hpp" //:class CoinAbcDenseFactorization. Deals with Factorization and Updates // CoinAbcDenseFactorization. Constructor CoinAbcDenseFactorization::CoinAbcDenseFactorization ( ) : CoinAbcAnyFactorization() { gutsOfInitialize(); } /// Copy constructor CoinAbcDenseFactorization::CoinAbcDenseFactorization ( const CoinAbcDenseFactorization &other) : CoinAbcAnyFactorization(other) { gutsOfInitialize(); gutsOfCopy(other); } // Clone CoinAbcAnyFactorization * CoinAbcDenseFactorization::clone() const { return new CoinAbcDenseFactorization(*this); } /// The real work of constructors etc void CoinAbcDenseFactorization::gutsOfDestructor() { delete [] elements_; delete [] pivotRow_; delete [] workArea_; elements_ = NULL; pivotRow_ = NULL; workArea_ = NULL; numberRows_ = 0; numberGoodU_ = 0; status_ = -1; maximumRows_=0; #if ABC_PARALLEL==2 parallelMode_=0; #endif maximumSpace_=0; maximumRowsAdjusted_=0; solveMode_=0; } void CoinAbcDenseFactorization::gutsOfInitialize() { pivotTolerance_ = 1.0e-1; minimumPivotTolerance_ = 1.0e-1; zeroTolerance_ = 1.0e-13; areaFactor_=1.0; numberDense_=0; maximumPivots_=200; relaxCheck_=1.0; numberRows_ = 0; numberGoodU_ = 0; status_ = -1; numberSlacks_ = 0; numberPivots_ = 0; maximumRows_=0; #if ABC_PARALLEL==2 parallelMode_=0; #endif maximumSpace_=0; maximumRowsAdjusted_=0; elements_ = NULL; pivotRow_ = NULL; workArea_ = NULL; solveMode_=0; } // ~CoinAbcDenseFactorization. Destructor CoinAbcDenseFactorization::~CoinAbcDenseFactorization ( ) { gutsOfDestructor(); } // = CoinAbcDenseFactorization & CoinAbcDenseFactorization::operator = ( const CoinAbcDenseFactorization & other ) { if (this != &other) { gutsOfDestructor(); gutsOfInitialize(); gutsOfCopy(other); } return *this; } #define WORK_MULT 2 void CoinAbcDenseFactorization::gutsOfCopy(const CoinAbcDenseFactorization &other) { pivotTolerance_ = other.pivotTolerance_; minimumPivotTolerance_ = other.minimumPivotTolerance_; zeroTolerance_ = other.zeroTolerance_; areaFactor_=other.areaFactor_; numberDense_=other.numberDense_; relaxCheck_ = other.relaxCheck_; numberRows_ = other.numberRows_; maximumRows_ = other.maximumRows_; #if ABC_PARALLEL==2 parallelMode_=other.parallelMode_; #endif maximumSpace_ = other.maximumSpace_; maximumRowsAdjusted_ = other.maximumRowsAdjusted_; solveMode_ = other.solveMode_; numberGoodU_ = other.numberGoodU_; maximumPivots_ = other.maximumPivots_; numberPivots_ = other.numberPivots_; factorElements_ = other.factorElements_; status_ = other.status_; numberSlacks_ = other.numberSlacks_; if (other.pivotRow_) { pivotRow_ = new int [2*maximumRowsAdjusted_+maximumPivots_]; CoinMemcpyN(other.pivotRow_,(2*maximumRowsAdjusted_+numberPivots_),pivotRow_); elements_ = new CoinFactorizationDouble [maximumSpace_]; CoinMemcpyN(other.elements_,(maximumRowsAdjusted_+numberPivots_)*maximumRowsAdjusted_,elements_); workArea_ = new CoinFactorizationDouble [maximumRowsAdjusted_*WORK_MULT]; CoinZeroN(workArea_,maximumRowsAdjusted_*WORK_MULT); } else { elements_ = NULL; pivotRow_ = NULL; workArea_ = NULL; } } // getAreas. Gets space for a factorization //called by constructors void CoinAbcDenseFactorization::getAreas ( int numberOfRows, int /*numberOfColumns*/, CoinBigIndex , CoinBigIndex ) { numberRows_ = numberOfRows; numberDense_=numberRows_; if ((numberRows_&(BLOCKING8-1))!=0) numberDense_ += (BLOCKING8-(numberRows_&(BLOCKING8-1))); CoinBigIndex size = numberDense_*(2*numberDense_+CoinMax(maximumPivots_,(numberDense_+1)>>1)); if (size>maximumSpace_) { delete [] elements_; elements_ = new CoinFactorizationDouble [size]; maximumSpace_ = size; } if (numberRows_>maximumRows_) { maximumRows_ = numberRows_; maximumRowsAdjusted_ = maximumRows_; if ((maximumRows_&(BLOCKING8-1))!=0) maximumRowsAdjusted_ += (BLOCKING8-(maximumRows_&(BLOCKING8-1))); delete [] pivotRow_; delete [] workArea_; pivotRow_ = new int [2*maximumRowsAdjusted_+maximumPivots_]; workArea_ = new CoinFactorizationDouble [maximumRowsAdjusted_*WORK_MULT]; } } // preProcess. void CoinAbcDenseFactorization::preProcess () { CoinBigIndex put = numberDense_*numberDense_; CoinFactorizationDouble * COIN_RESTRICT area = elements_+maximumSpace_-put; CoinAbcMemset0(area,put); int *indexRow = reinterpret_cast (elements_+numberRows_*numberRows_); CoinBigIndex * starts = reinterpret_cast (pivotRow_); CoinFactorizationDouble * COIN_RESTRICT column = area; //if (solveMode_==10) //solveMode_=1; if ((solveMode_%10)!=0) { for (int i=0;i>3; iRow=iRow&(BLOCKING8-1); column[iRow+BLOCKING8X8*iBlock]=elements_[j]; } if ((i&(BLOCKING8-1))!=(BLOCKING8-1)) column += BLOCKING8; else column += numberDense_*BLOCKING8-(BLOCKING8-1)*BLOCKING8; } for (int i=numberRows_;i>3; iRow=iRow&(BLOCKING8-1); column[iRow+BLOCKING8X8*iBlock]=1.0; if ((i&(BLOCKING8-1))!=(BLOCKING8-1)) column += BLOCKING8; //else //column += numberDense_*BLOCKING8-(BLOCKING8-1)*BLOCKING8; } } else { // first or bad for (int i=0;ilargest) { largest=value; iRow=j; } } if (iRow>=0) { if (iRow!=i) { // swap assert (iRow>i); CoinFactorizationDouble * elementsA = area; for (int k=0;k<=i;k++) { // swap CoinFactorizationDouble value = elementsA[i]; elementsA[i]=elementsA[iRow]; elementsA[iRow]=value; elementsA += numberDense_; } int iPivot = pivotRow_[i+numberDense_]; pivotRow_[i+numberDense_]=pivotRow_[iRow+numberDense_]; pivotRow_[iRow+numberDense_]=iPivot; } CoinFactorizationDouble pivotValue = 1.0/elements[i]; elements[i]=pivotValue; for (int j=i+1;j (workArea_); int i; for ( i=0;i=0); for ( i=numberGoodU_;idenseVector ( ); int *regionIndex = regionSparse->getIndices ( ); int numberNonZero = regionSparse->getNumElements ( ); int i; memset(elements,0,numberRows_*sizeof(CoinFactorizationDouble)); CoinFactorizationDouble pivotValue = pivotCheck; if (fabs(pivotValue)packedMode()) { for (i=0;ipackedMode()) { for (i=0;idenseVector ( ); int *regionIndex = tableauColumn->getIndices ( ); int numberNonZero = tableauColumn->getNumElements ( ); int i; memset(elements,0,numberRows_*sizeof(CoinFactorizationDouble)); double pivotValue = 1.0/alpha; if ((solveMode_%10)==0) { if (tableauColumn->packedMode()) { for (i=0;ipackedMode()) { for (i=0;i=0;i--) { int ip=ipiv[i]; if (ip!=i) { double temp=a[i]; a[i]=a[ip]; a[ip]=temp; } } } /* This version has same effect as above with FTUpdate==false so number returned is always >=0 */ int CoinAbcDenseFactorization::updateColumn (CoinIndexedVector & regionSparse) const { double *region = regionSparse.denseVector ( ); CoinBigIndex put = numberDense_*numberDense_; CoinFactorizationDouble * COIN_RESTRICT area = elements_+maximumSpace_-put; CoinFactorizationDouble * COIN_RESTRICT elements = area; if ((solveMode_%10)==0) { // base factorization L for (int i=0;i=0;i--) { elements -= numberDense_; CoinFactorizationDouble value = region[i]*elements[i]; region[i] = value; for (int j=0;j=0;i--) { elements -= numberDense_; int iPivot = pivotRow_[i+2*numberDense_]; CoinFactorizationDouble value = region[iPivot]; //*elements[iPivot]; for (int j=0;j=0;i--) { elements -= numberDense_; CoinFactorizationDouble value = region[i]; for (int j=i+1;j0.0&&value<=1.0) { pivotTolerance_=CoinMax(value,minimumPivotTolerance_); } } void CoinAbcAnyFactorization::minimumPivotTolerance ( double value ) { if (value>0.0&&value<=1.0) { minimumPivotTolerance_=value; } } void CoinAbcAnyFactorization::zeroTolerance ( double value ) { if (value>0.0&&value<1.0) { zeroTolerance_=value; } } void CoinAbcAnyFactorization::maximumPivots ( int value ) { if (value>maximumPivots_) { delete [] pivotRow_; int n=maximumRows_; if ((n&(BLOCKING8-1))!=0) n += (BLOCKING8-(n&(BLOCKING8-1))); pivotRow_ = new int[2*n+value]; } maximumPivots_ = value; } // Number of entries in each row int * CoinAbcAnyFactorization::numberInRow() const { return reinterpret_cast (workArea_);} // Number of entries in each column int * CoinAbcAnyFactorization::numberInColumn() const { return (reinterpret_cast (workArea_))+numberRows_;} // Returns array to put basis starts in CoinBigIndex * CoinAbcAnyFactorization::starts() const { return reinterpret_cast (pivotRow_);} // Returns array to put basis elements in CoinFactorizationDouble * CoinAbcAnyFactorization::elements() const { return elements_;} // Returns pivot row int * CoinAbcAnyFactorization::pivotRow() const { return pivotRow_;} // Returns work area CoinFactorizationDouble * CoinAbcAnyFactorization::workArea() const { return workArea_;} // Returns int work area int * CoinAbcAnyFactorization::intWorkArea() const { return reinterpret_cast (workArea_);} // Returns permute back int * CoinAbcAnyFactorization::permuteBack() const { return pivotRow_+numberRows_;} // Returns pivot column int * CoinAbcAnyFactorization::pivotColumn() const { return permute();} // Returns true if wants tableauColumn in replaceColumn bool CoinAbcAnyFactorization::wantsTableauColumn() const { return true;} /* Useful information for factorization 0 - iteration number whereFrom is 0 for factorize and 1 for replaceColumn */ void CoinAbcAnyFactorization::setUsefulInformation(const int * ,int ) { } Clp-1.15.10/src/Makefile.am0000644000076600007660000002170512253625222013704 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 2010 2013-12-16 16:30:10Z tkr $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # libClp # ######################################################################## # Name of the library compiled in this directory. We want it to be installed # in the 'lib' directory lib_LTLIBRARIES = libClp.la # List all source files for this library, including headers libClp_la_SOURCES = \ ClpConfig.h \ ClpCholeskyBase.cpp ClpCholeskyBase.hpp \ ClpCholeskyDense.cpp ClpCholeskyDense.hpp \ ClpConstraint.cpp ClpConstraint.hpp \ ClpConstraintLinear.cpp ClpConstraintLinear.hpp \ ClpConstraintQuadratic.cpp ClpConstraintQuadratic.hpp \ Clp_C_Interface.cpp Clp_C_Interface.h \ ClpDualRowDantzig.cpp ClpDualRowDantzig.hpp \ ClpDualRowPivot.cpp ClpDualRowPivot.hpp \ ClpDualRowSteepest.cpp ClpDualRowSteepest.hpp \ ClpDummyMatrix.cpp ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.cpp ClpDynamicExampleMatrix.hpp \ ClpDynamicMatrix.cpp ClpDynamicMatrix.hpp \ ClpEventHandler.cpp ClpEventHandler.hpp \ ClpFactorization.cpp ClpFactorization.hpp \ ClpGubDynamicMatrix.cpp ClpGubDynamicMatrix.hpp \ ClpGubMatrix.cpp ClpGubMatrix.hpp \ ClpHelperFunctions.cpp ClpHelperFunctions.hpp \ ClpInterior.cpp ClpInterior.hpp \ ClpLinearObjective.cpp ClpLinearObjective.hpp \ ClpMatrixBase.cpp ClpMatrixBase.hpp \ ClpMessage.cpp ClpMessage.hpp \ ClpModel.cpp ClpModel.hpp \ ClpNetworkBasis.cpp ClpNetworkBasis.hpp \ ClpNetworkMatrix.cpp ClpNetworkMatrix.hpp \ ClpNonLinearCost.cpp ClpNonLinearCost.hpp \ ClpNode.cpp ClpNode.hpp \ ClpObjective.cpp ClpObjective.hpp \ ClpPackedMatrix.cpp ClpPackedMatrix.hpp \ ClpParameters.hpp \ ClpPlusMinusOneMatrix.cpp ClpPlusMinusOneMatrix.hpp \ ClpPredictorCorrector.cpp ClpPredictorCorrector.hpp \ ClpPdco.cpp ClpPdco.hpp \ ClpPdcoBase.cpp ClpPdcoBase.hpp \ ClpLsqr.cpp ClpLsqr.hpp \ ClpPresolve.cpp ClpPresolve.hpp \ ClpPrimalColumnDantzig.cpp ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.cpp ClpPrimalColumnPivot.hpp \ ClpPrimalColumnSteepest.cpp ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.cpp ClpQuadraticObjective.hpp \ ClpSimplex.cpp ClpSimplex.hpp \ ClpSimplexDual.cpp ClpSimplexDual.hpp \ ClpSimplexNonlinear.cpp ClpSimplexNonlinear.hpp \ ClpSimplexOther.cpp ClpSimplexOther.hpp \ ClpSimplexPrimal.cpp ClpSimplexPrimal.hpp \ ClpSolve.cpp ClpSolve.hpp \ Idiot.cpp Idiot.hpp \ IdiSolve.cpp if COIN_HAS_ABC libClp_la_SOURCES += \ AbcCommon.hpp \ AbcDualRowDantzig.cpp AbcDualRowDantzig.hpp \ AbcDualRowPivot.cpp AbcDualRowPivot.hpp \ AbcDualRowSteepest.cpp AbcDualRowSteepest.hpp \ AbcMatrix.cpp AbcMatrix.hpp \ AbcNonLinearCost.cpp AbcNonLinearCost.hpp \ AbcPrimalColumnDantzig.cpp AbcPrimalColumnDantzig.hpp \ AbcPrimalColumnPivot.cpp AbcPrimalColumnPivot.hpp \ AbcPrimalColumnSteepest.cpp AbcPrimalColumnSteepest.hpp \ AbcSimplex.cpp AbcSimplex.hpp \ AbcSimplexDual.cpp AbcSimplexDual.hpp \ AbcSimplexPrimal.cpp AbcSimplexPrimal.hpp \ AbcSimplexParallel.cpp \ AbcSimplexFactorization.cpp AbcSimplexFactorization.hpp \ AbcWarmStart.cpp AbcWarmStart.hpp \ CoinAbcBaseFactorization.hpp \ CoinAbcBaseFactorization1.cpp \ CoinAbcBaseFactorization2.cpp \ CoinAbcBaseFactorization3.cpp \ CoinAbcBaseFactorization4.cpp \ CoinAbcBaseFactorization5.cpp \ CoinAbcCommonFactorization.hpp \ CoinAbcCommon.hpp \ CoinAbcDenseFactorization.cpp \ CoinAbcDenseFactorization.hpp \ CoinAbcFactorization.hpp \ CoinAbcFactorization1.cpp \ CoinAbcFactorization2.cpp \ CoinAbcFactorization3.cpp \ CoinAbcFactorization4.cpp \ CoinAbcFactorization5.cpp \ CoinAbcHelperFunctions.cpp CoinAbcHelperFunctions.hpp \ CoinAbcOrderedFactorization1.cpp \ CoinAbcOrderedFactorization2.cpp \ CoinAbcOrderedFactorization3.cpp \ CoinAbcOrderedFactorization4.cpp \ CoinAbcOrderedFactorization5.cpp \ CoinAbcSmallFactorization1.cpp \ CoinAbcSmallFactorization2.cpp \ CoinAbcSmallFactorization3.cpp \ CoinAbcSmallFactorization4.cpp \ CoinAbcSmallFactorization5.cpp endif # if AMD, CHOLMOD, or GLPK is available, then compile ClpCholeskyUfl.cpp if COIN_HAS_AMD libClp_la_SOURCES += ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp else if COIN_HAS_CHOLMOD libClp_la_SOURCES += ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp else if COIN_HAS_GLPK libClp_la_SOURCES += ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp endif endif endif if COIN_HAS_MUMPS libClp_la_SOURCES += ClpCholeskyMumps.cpp ClpCholeskyMumps.hpp endif if COIN_HAS_WSMP libClp_la_SOURCES += ClpCholeskyWssmp.cpp ClpCholeskyWssmp.hpp ClpCholeskyWssmpKKT.cpp ClpCholeskyWssmpKKT.hpp endif # List all additionally required libraries if DEPENDENCY_LINKING libClp_la_LIBADD = $(CLPLIB_LIBS) endif # This is for libtool libClp_la_LDFLAGS = $(LT_LDFLAGS) ######################################################################## # clp program # ######################################################################## # Name of the executable compiled in this directory. We want it to be # installed in the 'bin' directory bin_PROGRAMS = clp # List all source files for this executable, including headers clp_SOURCES = \ ClpMain.cpp \ CbcOrClpParam.cpp CbcOrClpParam.hpp \ MyEventHandler.cpp MyEventHandler.hpp \ MyMessageHandler.cpp MyMessageHandler.hpp \ unitTest.cpp # List all additionally required libraries clp_LDADD = libClp.la $(CLPLIB_LIBS) # List all dependency libraries (similar to LDADD, but without -l, -L flags) clp_DEPENDENCIES = libClp.la $(CLPLIB_DEPENDENCIES) ######################################################################## # Additional flags # ######################################################################## # CbcOrClpParam seem to require COIN_HAS_CLP so that it knows that it is build within Clp AM_CPPFLAGS = $(CLPLIB_CFLAGS) -DCOIN_HAS_CLP if COIN_HAS_CHOLMOD AM_CPPFLAGS += -I`$(CYGPATH_W) $(CHOLMODINCDIR)` endif if COIN_HAS_AMD AM_CPPFLAGS += -I`$(CYGPATH_W) $(AMDINCDIR)` endif # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` ######################################################################## # 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 = \ Clp_C_Interface.h \ ClpCholeskyBase.hpp \ ClpCholeskyDense.hpp \ ClpConstraint.hpp \ ClpConstraintLinear.hpp \ ClpConstraintQuadratic.hpp \ ClpDualRowDantzig.hpp \ ClpDualRowPivot.hpp \ ClpDualRowSteepest.hpp \ ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.hpp \ ClpDynamicMatrix.hpp \ ClpEventHandler.hpp \ ClpFactorization.hpp \ ClpGubDynamicMatrix.hpp \ ClpGubMatrix.hpp \ ClpInterior.hpp \ ClpLinearObjective.hpp \ ClpMatrixBase.hpp \ ClpMessage.hpp \ ClpModel.hpp \ ClpNetworkMatrix.hpp \ ClpNonLinearCost.hpp \ ClpNode.hpp \ ClpObjective.hpp \ ClpPackedMatrix.hpp \ ClpPdcoBase.hpp \ ClpPlusMinusOneMatrix.hpp \ ClpParameters.hpp \ ClpPresolve.hpp \ ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.hpp \ ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.hpp \ ClpSimplex.hpp \ ClpSimplexNonlinear.hpp \ ClpSimplexOther.hpp \ ClpSimplexDual.hpp \ ClpSimplexPrimal.hpp \ ClpSolve.hpp \ CbcOrClpParam.hpp \ Idiot.hpp if COIN_HAS_ABC includecoin_HEADERS += AbcSimplex.hpp CoinAbcCommon.hpp AbcCommon.hpp endif # if AMD, CHOLMOD, or GLPK is available, then install ClpCholeskyUfl.hpp (for advanced users) if COIN_HAS_AMD includecoin_HEADERS += ClpCholeskyUfl.hpp else if COIN_HAS_CHOLMOD includecoin_HEADERS += ClpCholeskyUfl.hpp else if COIN_HAS_GLPK includecoin_HEADERS += ClpCholeskyUfl.hpp endif endif endif if COIN_HAS_MUMPS includecoin_HEADERS += ClpCholeskyMumps.hpp endif if COIN_HAS_WSMP includecoin_HEADERS += ClpCholeskyWssmp.hpp ClpCholeskyWssmpKKT.hpp endif # needed by Cbc includecoin_HEADERS += CbcOrClpParam.cpp ######################################################################## # Installing manifest (MSVC++) # ######################################################################## if COIN_CXX_IS_CL install-exec-hook: test -s clp.exe.manifest && \ mt -manifest clp.exe.manifest -outputresource:clp.exe;\ cp clp.exe $(bindir)/clp.exe endif ####################################################################### # Create the Config.h file that has all public defines and install it # ####################################################################### install-exec-local: $(install_sh_DATA) config_clp.h $(DESTDIR)$(includecoindir)/ClpConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/ClpConfig.h Clp-1.15.10/src/ClpDualRowSteepest.hpp0000644000076600007660000001063311510657452016115 0ustar coincoin/* $Id: ClpDualRowSteepest.hpp 1665 2011-01-04 17:55:54Z 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 ClpDualRowSteepest_H #define ClpDualRowSteepest_H #include "ClpDualRowPivot.hpp" class CoinIndexedVector; //############################################################################# /** Dual Row Pivot Steepest Edge Algorithm Class See Forrest-Goldfarb paper for algorithm */ class ClpDualRowSteepest : public ClpDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow(); /** Updates weights and returns pivot alpha. Also does FT update */ virtual double updateWeights(CoinIndexedVector * input, CoinIndexedVector * spare, CoinIndexedVector * spare2, CoinIndexedVector * updatedColumn); /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ virtual void updatePrimalSolution(CoinIndexedVector * input, double theta, double & changeInObjective); /** Saves any weights round factorization as pivot rows may change Save model May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) for strong branching - initialize (uninitialized) , infeasibilities */ virtual void saveWeights(ClpSimplex * model, int mode); /// Gets rid of last update virtual void unrollWeights(); /// Gets rid of all arrays virtual void clearArrays(); /// Returns true if would not find any row virtual bool looksOptimal() const; /// Called when maximum pivots changes virtual void maximumPivotsChanged(); //@} /** enums for persistence */ enum Persistence { normal = 0x00, // create (if necessary) and destroy keep = 0x01 // create (if necessary) and leave }; ///@name Constructors and destructors //@{ /** Default Constructor 0 is uninitialized, 1 full, 2 is partial uninitialized, 3 starts as 2 but may switch to 1. By partial is meant that the weights are updated as normal but only part of the infeasible basic variables are scanned. This can be faster on very easy problems. */ ClpDualRowSteepest(int mode = 3); /// Copy constructor ClpDualRowSteepest(const ClpDualRowSteepest &); /// Assignment operator ClpDualRowSteepest & operator=(const ClpDualRowSteepest& rhs); /// Fill most values void fill(const ClpDualRowSteepest& rhs); /// Destructor virtual ~ClpDualRowSteepest (); /// Clone virtual ClpDualRowPivot * clone(bool copyData = true) const; //@} /**@name gets and sets */ //@{ /// Mode inline int mode() const { return mode_; } /// Set/ get persistence inline void setPersistence(Persistence life) { persistence_ = life; } inline Persistence persistence() const { return persistence_ ; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data /** Status 0) Normal -1) Needs initialization 1) Weights are stored by sequence number */ int state_; /** If 0 then we are using uninitialized weights, 1 then full, if 2 then uninitialized partial, 3 switchable */ int mode_; /// Life of weights Persistence persistence_; /// weight array double * weights_; /// square of infeasibility array (just for infeasible rows) CoinIndexedVector * infeasible_; /// alternate weight array (so we can unroll) CoinIndexedVector * alternateWeights_; /// save weight array (so we can use checkpoint) CoinIndexedVector * savedWeights_; /// Dubious weights int * dubiousWeights_; //@} }; #endif Clp-1.15.10/src/ClpPlusMinusOneMatrix.cpp0000644000076600007660000022317611510657452016614 0ustar coincoin/* $Id: ClpPlusMinusOneMatrix.cpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinPackedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" // at end to get min/max! #include "ClpPlusMinusOneMatrix.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPlusMinusOneMatrix::ClpPlusMinusOneMatrix () : ClpMatrixBase() { setType(12); matrix_ = NULL; startPositive_ = NULL; startNegative_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = 0; numberColumns_ = 0; columnOrdered_ = true; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPlusMinusOneMatrix::ClpPlusMinusOneMatrix (const ClpPlusMinusOneMatrix & rhs) : ClpMatrixBase(rhs) { matrix_ = NULL; startPositive_ = NULL; startNegative_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; columnOrdered_ = rhs.columnOrdered_; if (numberColumns_) { CoinBigIndex numberElements = rhs.startPositive_[numberColumns_]; indices_ = new int [ numberElements]; CoinMemcpyN(rhs.indices_, numberElements, indices_); startPositive_ = new CoinBigIndex [ numberColumns_+1]; CoinMemcpyN(rhs.startPositive_, (numberColumns_ + 1), startPositive_); startNegative_ = new CoinBigIndex [ numberColumns_]; CoinMemcpyN(rhs.startNegative_, numberColumns_, startNegative_); } int numberRows = getNumRows(); if (rhs.rhsOffset_ && numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_, numberRows); } else { rhsOffset_ = NULL; } } // Constructor from arrays ClpPlusMinusOneMatrix::ClpPlusMinusOneMatrix(int numberRows, int numberColumns, bool columnOrdered, const int * indices, const CoinBigIndex * startPositive, const CoinBigIndex * startNegative) : ClpMatrixBase() { setType(12); matrix_ = NULL; lengths_ = NULL; numberRows_ = numberRows; numberColumns_ = numberColumns; columnOrdered_ = columnOrdered; int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; int numberElements = startPositive[numberMajor]; startPositive_ = ClpCopyOfArray(startPositive, numberMajor + 1); startNegative_ = ClpCopyOfArray(startNegative, numberMajor); indices_ = ClpCopyOfArray(indices, numberElements); // Check valid checkValid(false); } ClpPlusMinusOneMatrix::ClpPlusMinusOneMatrix (const CoinPackedMatrix & rhs) : ClpMatrixBase() { setType(12); matrix_ = NULL; startPositive_ = NULL; startNegative_ = NULL; lengths_ = NULL; indices_ = NULL; int iColumn; assert (rhs.isColOrdered()); // get matrix data pointers const int * row = rhs.getIndices(); const CoinBigIndex * columnStart = rhs.getVectorStarts(); const int * columnLength = rhs.getVectorLengths(); const double * elementByColumn = rhs.getElements(); numberColumns_ = rhs.getNumCols(); numberRows_ = -1; indices_ = new int[rhs.getNumElements()]; startPositive_ = new CoinBigIndex [numberColumns_+1]; startNegative_ = new CoinBigIndex [numberColumns_]; int * temp = new int [rhs.getNumRows()]; CoinBigIndex j = 0; CoinBigIndex numberGoodP = 0; CoinBigIndex numberGoodM = 0; CoinBigIndex numberBad = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex k; int iNeg = 0; startPositive_[iColumn] = j; for (k = columnStart[iColumn]; k < columnStart[iColumn] + columnLength[iColumn]; k++) { int iRow; if (fabs(elementByColumn[k] - 1.0) < 1.0e-10) { iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j++] = iRow; numberGoodP++; } else if (fabs(elementByColumn[k] + 1.0) < 1.0e-10) { iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); temp[iNeg++] = iRow; numberGoodM++; } else { numberBad++; } } // move negative startNegative_[iColumn] = j; for (k = 0; k < iNeg; k++) { indices_[j++] = temp[k]; } } startPositive_[numberColumns_] = j; delete [] temp; if (numberBad) { delete [] indices_; indices_ = NULL; numberRows_ = 0; numberColumns_ = 0; delete [] startPositive_; delete [] startNegative_; // Put in statistics startPositive_ = new CoinBigIndex [3]; startPositive_[0] = numberGoodP; startPositive_[1] = numberGoodM; startPositive_[2] = numberBad; startNegative_ = NULL; } else { numberRows_ ++; // correct // but number should be same as rhs assert (numberRows_ <= rhs.getNumRows()); numberRows_ = rhs.getNumRows(); columnOrdered_ = true; } // Check valid if (!numberBad) checkValid(false); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPlusMinusOneMatrix::~ClpPlusMinusOneMatrix () { delete matrix_; delete [] startPositive_; delete [] startNegative_; delete [] lengths_; delete [] indices_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPlusMinusOneMatrix & ClpPlusMinusOneMatrix::operator=(const ClpPlusMinusOneMatrix& rhs) { if (this != &rhs) { ClpMatrixBase::operator=(rhs); delete matrix_; delete [] startPositive_; delete [] startNegative_; delete [] lengths_; delete [] indices_; matrix_ = NULL; startPositive_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; columnOrdered_ = rhs.columnOrdered_; if (numberColumns_) { CoinBigIndex numberElements = rhs.startPositive_[numberColumns_]; indices_ = new int [ numberElements]; CoinMemcpyN(rhs.indices_, numberElements, indices_); startPositive_ = new CoinBigIndex [ numberColumns_+1]; CoinMemcpyN(rhs.startPositive_, (numberColumns_ + 1), startPositive_); startNegative_ = new CoinBigIndex [ numberColumns_]; CoinMemcpyN(rhs.startNegative_, numberColumns_, startNegative_); } } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpPlusMinusOneMatrix::clone() const { return new ClpPlusMinusOneMatrix(*this); } /* Subset clone (without gaps). Duplicates are allowed and order is as given */ ClpMatrixBase * ClpPlusMinusOneMatrix::subsetClone (int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const { return new ClpPlusMinusOneMatrix(*this, numberRows, whichRows, numberColumns, whichColumns); } /* Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpPlusMinusOneMatrix::ClpPlusMinusOneMatrix ( const ClpPlusMinusOneMatrix & rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn) : ClpMatrixBase(rhs) { matrix_ = NULL; startPositive_ = NULL; startNegative_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = 0; numberColumns_ = 0; columnOrdered_ = rhs.columnOrdered_; if (numberRows <= 0 || numberColumns <= 0) { startPositive_ = new CoinBigIndex [1]; startPositive_[0] = 0; } else { numberColumns_ = numberColumns; numberRows_ = numberRows; const int * index1 = rhs.indices_; CoinBigIndex * startPositive1 = rhs.startPositive_; int numberMinor = (!columnOrdered_) ? numberColumns_ : numberRows_; int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; int numberMinor1 = (!columnOrdered_) ? rhs.numberColumns_ : rhs.numberRows_; int numberMajor1 = (columnOrdered_) ? rhs.numberColumns_ : rhs.numberRows_; // Also swap incoming if not column ordered if (!columnOrdered_) { int temp1 = numberRows; numberRows = numberColumns; numberColumns = temp1; const int * temp2; temp2 = whichRow; whichRow = whichColumn; whichColumn = temp2; } // Throw exception if rhs empty if (numberMajor1 <= 0 || numberMinor1 <= 0) throw CoinError("empty rhs", "subset constructor", "ClpPlusMinusOneMatrix"); // Array to say if an old row is in new copy int * newRow = new int [numberMinor1]; int iRow; for (iRow = 0; iRow < numberMinor1; iRow++) newRow[iRow] = -1; // and array for duplicating rows int * duplicateRow = new int [numberMinor]; int numberBad = 0; for (iRow = 0; iRow < numberMinor; iRow++) { duplicateRow[iRow] = -1; int kRow = whichRow[iRow]; if (kRow >= 0 && kRow < numberMinor1) { if (newRow[kRow] < 0) { // first time newRow[kRow] = iRow; } else { // duplicate int lastRow = newRow[kRow]; newRow[kRow] = iRow; duplicateRow[iRow] = lastRow; } } else { // bad row numberBad++; } } if (numberBad) throw CoinError("bad minor entries", "subset constructor", "ClpPlusMinusOneMatrix"); // now get size and check columns CoinBigIndex size = 0; int iColumn; numberBad = 0; for (iColumn = 0; iColumn < numberMajor; iColumn++) { int kColumn = whichColumn[iColumn]; if (kColumn >= 0 && kColumn < numberMajor1) { CoinBigIndex i; for (i = startPositive1[kColumn]; i < startPositive1[kColumn+1]; i++) { int kRow = index1[i]; kRow = newRow[kRow]; while (kRow >= 0) { size++; kRow = duplicateRow[kRow]; } } } else { // bad column numberBad++; printf("%d %d %d %d\n", iColumn, numberMajor, numberMajor1, kColumn); } } if (numberBad) throw CoinError("bad major entries", "subset constructor", "ClpPlusMinusOneMatrix"); // now create arrays startPositive_ = new CoinBigIndex [numberMajor+1]; startNegative_ = new CoinBigIndex [numberMajor]; indices_ = new int[size]; // and fill them size = 0; startPositive_[0] = 0; CoinBigIndex * startNegative1 = rhs.startNegative_; for (iColumn = 0; iColumn < numberMajor; iColumn++) { int kColumn = whichColumn[iColumn]; CoinBigIndex i; for (i = startPositive1[kColumn]; i < startNegative1[kColumn]; i++) { int kRow = index1[i]; kRow = newRow[kRow]; while (kRow >= 0) { indices_[size++] = kRow; kRow = duplicateRow[kRow]; } } startNegative_[iColumn] = size; for (; i < startPositive1[kColumn+1]; i++) { int kRow = index1[i]; kRow = newRow[kRow]; while (kRow >= 0) { indices_[size++] = kRow; kRow = duplicateRow[kRow]; } } startPositive_[iColumn+1] = size; } delete [] newRow; delete [] duplicateRow; } // Check valid checkValid(false); } /* Returns a new matrix in reverse order without gaps */ ClpMatrixBase * ClpPlusMinusOneMatrix::reverseOrderedCopy() const { int numberMinor = (!columnOrdered_) ? numberColumns_ : numberRows_; int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; // count number in each row/column CoinBigIndex * tempP = new CoinBigIndex [numberMinor]; CoinBigIndex * tempN = new CoinBigIndex [numberMinor]; memset(tempP, 0, numberMinor * sizeof(CoinBigIndex)); memset(tempN, 0, numberMinor * sizeof(CoinBigIndex)); CoinBigIndex j = 0; int i; for (i = 0; i < numberMajor; i++) { for (; j < startNegative_[i]; j++) { int iRow = indices_[j]; tempP[iRow]++; } for (; j < startPositive_[i+1]; j++) { int iRow = indices_[j]; tempN[iRow]++; } } int * newIndices = new int [startPositive_[numberMajor]]; CoinBigIndex * newP = new CoinBigIndex [numberMinor+1]; CoinBigIndex * newN = new CoinBigIndex[numberMinor]; int iRow; j = 0; // do starts for (iRow = 0; iRow < numberMinor; iRow++) { newP[iRow] = j; j += tempP[iRow]; tempP[iRow] = newP[iRow]; newN[iRow] = j; j += tempN[iRow]; tempN[iRow] = newN[iRow]; } newP[numberMinor] = j; j = 0; for (i = 0; i < numberMajor; i++) { for (; j < startNegative_[i]; j++) { int iRow = indices_[j]; CoinBigIndex put = tempP[iRow]; newIndices[put++] = i; tempP[iRow] = put; } for (; j < startPositive_[i+1]; j++) { int iRow = indices_[j]; CoinBigIndex put = tempN[iRow]; newIndices[put++] = i; tempN[iRow] = put; } } delete [] tempP; delete [] tempN; ClpPlusMinusOneMatrix * newCopy = new ClpPlusMinusOneMatrix(); newCopy->passInCopy(numberMinor, numberMajor, !columnOrdered_, newIndices, newP, newN); return newCopy; } //unscaled versions void ClpPlusMinusOneMatrix::times(double scalar, const double * x, double * y) const { int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; int i; CoinBigIndex j; assert (columnOrdered_); for (i = 0; i < numberMajor; i++) { double value = scalar * x[i]; if (value) { for (j = startPositive_[i]; j < startNegative_[i]; j++) { int iRow = indices_[j]; y[iRow] += value; } for (; j < startPositive_[i+1]; j++) { int iRow = indices_[j]; y[iRow] -= value; } } } } void ClpPlusMinusOneMatrix::transposeTimes(double scalar, const double * x, double * y) const { int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; int i; CoinBigIndex j = 0; assert (columnOrdered_); for (i = 0; i < numberMajor; i++) { double value = 0.0; for (; j < startNegative_[i]; j++) { int iRow = indices_[j]; value += x[iRow]; } for (; j < startPositive_[i+1]; j++) { int iRow = indices_[j]; value -= x[iRow]; } y[i] += scalar * value; } } void ClpPlusMinusOneMatrix::times(double scalar, const double * x, double * y, const double * /*rowScale*/, const double * /*columnScale*/) const { // we know it is not scaled times(scalar, x, y); } void ClpPlusMinusOneMatrix::transposeTimes( double scalar, const double * x, double * y, const double * /*rowScale*/, const double * /*columnScale*/, double * /*spare*/) const { // we know it is not scaled transposeTimes(scalar, x, y); } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpPlusMinusOneMatrix::transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { // we know it is not scaled columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); int numberRows = model->numberRows(); bool packed = rowArray->packedMode(); #ifndef NO_RTTI ClpPlusMinusOneMatrix* rowCopy = dynamic_cast< ClpPlusMinusOneMatrix*>(model->rowCopy()); #else ClpPlusMinusOneMatrix* rowCopy = static_cast< ClpPlusMinusOneMatrix*>(model->rowCopy()); #endif double factor = 0.3; // We may not want to do by row if there may be cache problems int numberColumns = model->numberColumns(); // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberColumns * sizeof(double) > 1000000) { if (numberRows * 10 < numberColumns) factor = 0.1; else if (numberRows * 4 < numberColumns) factor = 0.15; else if (numberRows * 2 < numberColumns) factor = 0.2; } if (numberInRowArray > factor * numberRows || !rowCopy) { assert (!y->getNumElements()); // do by column // Need to expand if packed mode int iColumn; CoinBigIndex j = 0; assert (columnOrdered_); if (packed) { // need to expand pi into y assert(y->capacity() >= numberRows); double * piOld = pi; pi = y->denseVector(); const int * whichRow = rowArray->getIndices(); int i; // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i]; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double value = 0.0; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; value += pi[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; value -= pi[iRow]; } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double value = 0.0; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; value += pi[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; value -= pi[iRow]; } value *= scalar; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } columnArray->setNumElements(numberNonZero); } else { // do by row rowCopy->transposeTimesByRow(model, scalar, rowArray, y, columnArray); } } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpPlusMinusOneMatrix::transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); const int * column = indices_; const CoinBigIndex * startPositive = startPositive_; const CoinBigIndex * startNegative = startNegative_; const int * whichRow = rowArray->getIndices(); bool packed = rowArray->packedMode(); if (numberInRowArray > 2) { // do by rows int iRow; double * markVector = y->denseVector(); // probably empty .. but int numberOriginal = 0; int i; if (packed) { numberNonZero = 0; // and set up mark as char array char * marked = reinterpret_cast (index + columnArray->capacity()); double * array2 = y->denseVector(); #ifdef CLP_DEBUG int numberColumns = model->numberColumns(); for (i = 0; i < numberColumns; i++) { assert(!marked[i]); assert(!array2[i]); } #endif for (i = 0; i < numberInRowArray; i++) { iRow = whichRow[i]; double value = pi[i] * scalar; CoinBigIndex j; for (j = startPositive[iRow]; j < startNegative[iRow]; j++) { int iColumn = column[j]; if (!marked[iColumn]) { marked[iColumn] = 1; index[numberNonZero++] = iColumn; } array2[iColumn] += value; } for (j = startNegative[iRow]; j < startPositive[iRow+1]; j++) { int iColumn = column[j]; if (!marked[iColumn]) { marked[iColumn] = 1; index[numberNonZero++] = iColumn; } array2[iColumn] -= value; } } // get rid of tiny values and zero out marked numberOriginal = numberNonZero; numberNonZero = 0; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; if (marked[iColumn]) { double value = array2[iColumn]; array2[iColumn] = 0.0; marked[iColumn] = 0; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } } else { numberNonZero = 0; // and set up mark as char array char * marked = reinterpret_cast (markVector); for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; marked[iColumn] = 0; } for (i = 0; i < numberInRowArray; i++) { iRow = whichRow[i]; double value = pi[iRow] * scalar; CoinBigIndex j; for (j = startPositive[iRow]; j < startNegative[iRow]; j++) { int iColumn = column[j]; if (!marked[iColumn]) { marked[iColumn] = 1; index[numberNonZero++] = iColumn; } array[iColumn] += value; } for (j = startNegative[iRow]; j < startPositive[iRow+1]; j++) { int iColumn = column[j]; if (!marked[iColumn]) { marked[iColumn] = 1; index[numberNonZero++] = iColumn; } array[iColumn] -= value; } } // get rid of tiny values and zero out marked numberOriginal = numberNonZero; numberNonZero = 0; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; marked[iColumn] = 0; if (fabs(array[iColumn]) > zeroTolerance) { index[numberNonZero++] = iColumn; } else { array[iColumn] = 0.0; } } } } else if (numberInRowArray == 2) { /* do by rows when two rows (do longer first when not packed and shorter first if packed */ int iRow0 = whichRow[0]; int iRow1 = whichRow[1]; CoinBigIndex j; if (packed) { double pi0 = pi[0]; double pi1 = pi[1]; if (startPositive[iRow0+1] - startPositive[iRow0] > startPositive[iRow1+1] - startPositive[iRow1]) { int temp = iRow0; iRow0 = iRow1; iRow1 = temp; pi0 = pi1; pi1 = pi[0]; } // and set up mark as char array char * marked = reinterpret_cast (index + columnArray->capacity()); int * lookup = y->getIndices(); double value = pi0 * scalar; for (j = startPositive[iRow0]; j < startNegative[iRow0]; j++) { int iColumn = column[j]; array[numberNonZero] = value; marked[iColumn] = 1; lookup[iColumn] = numberNonZero; index[numberNonZero++] = iColumn; } for (j = startNegative[iRow0]; j < startPositive[iRow0+1]; j++) { int iColumn = column[j]; array[numberNonZero] = -value; marked[iColumn] = 1; lookup[iColumn] = numberNonZero; index[numberNonZero++] = iColumn; } int numberOriginal = numberNonZero; value = pi1 * scalar; for (j = startPositive[iRow1]; j < startNegative[iRow1]; j++) { int iColumn = column[j]; if (marked[iColumn]) { int iLookup = lookup[iColumn]; array[iLookup] += value; } else { if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } for (j = startNegative[iRow1]; j < startPositive[iRow1+1]; j++) { int iColumn = column[j]; if (marked[iColumn]) { int iLookup = lookup[iColumn]; array[iLookup] -= value; } else { if (fabs(value) > zeroTolerance) { array[numberNonZero] = -value; index[numberNonZero++] = iColumn; } } } // get rid of tiny values and zero out marked int nDelete = 0; for (j = 0; j < numberOriginal; j++) { int iColumn = index[j]; marked[iColumn] = 0; if (fabs(array[j]) <= zeroTolerance) nDelete++; } if (nDelete) { numberOriginal = numberNonZero; numberNonZero = 0; for (j = 0; j < numberOriginal; j++) { int iColumn = index[j]; double value = array[j]; array[j] = 0.0; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } } else { if (startPositive[iRow0+1] - startPositive[iRow0] < startPositive[iRow1+1] - startPositive[iRow1]) { int temp = iRow0; iRow0 = iRow1; iRow1 = temp; } int numberOriginal; int i; numberNonZero = 0; double value; value = pi[iRow0] * scalar; CoinBigIndex j; for (j = startPositive[iRow0]; j < startNegative[iRow0]; j++) { int iColumn = column[j]; index[numberNonZero++] = iColumn; array[iColumn] = value; } for (j = startNegative[iRow0]; j < startPositive[iRow0+1]; j++) { int iColumn = column[j]; index[numberNonZero++] = iColumn; array[iColumn] = -value; } value = pi[iRow1] * scalar; for (j = startPositive[iRow1]; j < startNegative[iRow1]; j++) { int iColumn = column[j]; double value2 = array[iColumn]; if (value2) { value2 += value; } else { value2 = value; index[numberNonZero++] = iColumn; } array[iColumn] = value2; } for (j = startNegative[iRow1]; j < startPositive[iRow1+1]; j++) { int iColumn = column[j]; double value2 = array[iColumn]; if (value2) { value2 -= value; } else { value2 = -value; index[numberNonZero++] = iColumn; } array[iColumn] = value2; } // get rid of tiny values and zero out marked numberOriginal = numberNonZero; numberNonZero = 0; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; if (fabs(array[iColumn]) > zeroTolerance) { index[numberNonZero++] = iColumn; } else { array[iColumn] = 0.0; } } } } else if (numberInRowArray == 1) { // Just one row int iRow = rowArray->getIndices()[0]; numberNonZero = 0; double value; iRow = whichRow[0]; CoinBigIndex j; if (packed) { value = pi[0] * scalar; if (fabs(value) > zeroTolerance) { for (j = startPositive[iRow]; j < startNegative[iRow]; j++) { int iColumn = column[j]; array[numberNonZero] = value; index[numberNonZero++] = iColumn; } for (j = startNegative[iRow]; j < startPositive[iRow+1]; j++) { int iColumn = column[j]; array[numberNonZero] = -value; index[numberNonZero++] = iColumn; } } } else { value = pi[iRow] * scalar; if (fabs(value) > zeroTolerance) { for (j = startPositive[iRow]; j < startNegative[iRow]; j++) { int iColumn = column[j]; array[iColumn] = value; index[numberNonZero++] = iColumn; } for (j = startNegative[iRow]; j < startPositive[iRow+1]; j++) { int iColumn = column[j]; array[iColumn] = -value; index[numberNonZero++] = iColumn; } } } } columnArray->setNumElements(numberNonZero); if (packed) columnArray->setPacked(); y->setNumElements(0); } /* Return x *A in z but just for indices in y. */ void ClpPlusMinusOneMatrix::subsetTransposeTimes(const ClpSimplex * , const CoinIndexedVector * rowArray, const CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); double * array = columnArray->denseVector(); int jColumn; int numberToDo = y->getNumElements(); const int * which = y->getIndices(); assert (!rowArray->packedMode()); columnArray->setPacked(); for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; value += pi[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; value -= pi[iRow]; } array[jColumn] = value; } } /// returns number of elements in column part of basis, CoinBigIndex ClpPlusMinusOneMatrix::countBasis(const int * whichColumn, int & numberColumnBasic) { int i; CoinBigIndex numberElements = 0; for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; numberElements += startPositive_[iColumn+1] - startPositive_[iColumn]; } return numberElements; } void ClpPlusMinusOneMatrix::fillBasis(ClpSimplex * , const int * whichColumn, int & numberColumnBasic, int * indexRowU, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * elementU) { int i; CoinBigIndex numberElements = start[0]; assert (columnOrdered_); for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = 1.0; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = -1.0; } start[i+1] = numberElements; columnCount[i] = numberElements - start[i]; } } /* Unpacks a column into an CoinIndexedvector */ void ClpPlusMinusOneMatrix::unpack(const ClpSimplex * , CoinIndexedVector * rowArray, int iColumn) const { CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; rowArray->add(iRow, 1.0); } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; rowArray->add(iRow, -1.0); } } /* Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ void ClpPlusMinusOneMatrix::unpackPacked(ClpSimplex * , CoinIndexedVector * rowArray, int iColumn) const { int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); int number = 0; CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; array[number] = 1.0; index[number++] = iRow; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; array[number] = -1.0; index[number++] = iRow; } rowArray->setNumElements(number); rowArray->setPackedMode(true); } /* Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ void ClpPlusMinusOneMatrix::add(const ClpSimplex * , CoinIndexedVector * rowArray, int iColumn, double multiplier) const { CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; rowArray->quickAdd(iRow, multiplier); } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; rowArray->quickAdd(iRow, -multiplier); } } /* Adds multiple of a column into an array */ void ClpPlusMinusOneMatrix::add(const ClpSimplex * , double * array, int iColumn, double multiplier) const { CoinBigIndex j = startPositive_[iColumn]; for (; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; array[iRow] += multiplier; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; array[iRow] -= multiplier; } } // Return a complete CoinPackedMatrix CoinPackedMatrix * ClpPlusMinusOneMatrix::getPackedMatrix() const { if (!matrix_) { int numberMinor = (!columnOrdered_) ? numberColumns_ : numberRows_; int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; int numberElements = startPositive_[numberMajor]; double * elements = new double [numberElements]; CoinBigIndex j = 0; int i; for (i = 0; i < numberMajor; i++) { for (; j < startNegative_[i]; j++) { elements[j] = 1.0; } for (; j < startPositive_[i+1]; j++) { elements[j] = -1.0; } } matrix_ = new CoinPackedMatrix(columnOrdered_, numberMinor, numberMajor, getNumElements(), elements, indices_, startPositive_, getVectorLengths()); delete [] elements; delete [] lengths_; lengths_ = NULL; } return matrix_; } /* A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ const double * ClpPlusMinusOneMatrix::getElements() const { if (!matrix_) getPackedMatrix(); return matrix_->getElements(); } const CoinBigIndex * ClpPlusMinusOneMatrix::getVectorStarts() const { return startPositive_; } /* The lengths of the major-dimension vectors. */ const int * ClpPlusMinusOneMatrix::getVectorLengths() const { if (!lengths_) { int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; lengths_ = new int [numberMajor]; int i; for (i = 0; i < numberMajor; i++) { lengths_[i] = startPositive_[i+1] - startPositive_[i]; } } return lengths_; } /* Delete the columns whose indices are listed in indDel. */ void ClpPlusMinusOneMatrix::deleteCols(const int numDel, const int * indDel) { int iColumn; CoinBigIndex newSize = startPositive_[numberColumns_];; int numberBad = 0; // Use array to make sure we can have duplicates int * which = new int[numberColumns_]; memset(which, 0, numberColumns_ * sizeof(int)); int nDuplicate = 0; for (iColumn = 0; iColumn < numDel; iColumn++) { int jColumn = indDel[iColumn]; if (jColumn < 0 || jColumn >= numberColumns_) { numberBad++; } else { newSize -= startPositive_[jColumn+1] - startPositive_[jColumn]; if (which[jColumn]) nDuplicate++; else which[jColumn] = 1; } } if (numberBad) throw CoinError("Indices out of range", "deleteCols", "ClpPlusMinusOneMatrix"); int newNumber = numberColumns_ - numDel + nDuplicate; // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; CoinBigIndex * newPositive = new CoinBigIndex [newNumber+1]; CoinBigIndex * newNegative = new CoinBigIndex [newNumber]; int * newIndices = new int [newSize]; newNumber = 0; newSize = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (!which[iColumn]) { CoinBigIndex start, end; CoinBigIndex i; start = startPositive_[iColumn]; end = startNegative_[iColumn]; newPositive[newNumber] = newSize; for (i = start; i < end; i++) newIndices[newSize++] = indices_[i]; start = startNegative_[iColumn]; end = startPositive_[iColumn+1]; newNegative[newNumber++] = newSize; for (i = start; i < end; i++) newIndices[newSize++] = indices_[i]; } } newPositive[newNumber] = newSize; delete [] which; delete [] startPositive_; startPositive_ = newPositive; delete [] startNegative_; startNegative_ = newNegative; delete [] indices_; indices_ = newIndices; numberColumns_ = newNumber; } /* Delete the rows whose indices are listed in indDel. */ void ClpPlusMinusOneMatrix::deleteRows(const int numDel, const int * indDel) { int iRow; int numberBad = 0; // Use array to make sure we can have duplicates int * which = new int[numberRows_]; memset(which, 0, numberRows_ * sizeof(int)); int nDuplicate = 0; for (iRow = 0; iRow < numDel; iRow++) { int jRow = indDel[iRow]; if (jRow < 0 || jRow >= numberRows_) { numberBad++; } else { if (which[jRow]) nDuplicate++; else which[jRow] = 1; } } if (numberBad) throw CoinError("Indices out of range", "deleteRows", "ClpPlusMinusOneMatrix"); CoinBigIndex iElement; CoinBigIndex numberElements = startPositive_[numberColumns_]; CoinBigIndex newSize = 0; for (iElement = 0; iElement < numberElements; iElement++) { iRow = indices_[iElement]; if (!which[iRow]) newSize++; } int newNumber = numberRows_ - numDel + nDuplicate; // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; int * newIndices = new int [newSize]; newSize = 0; int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex start, end; CoinBigIndex i; start = startPositive_[iColumn]; end = startNegative_[iColumn]; startPositive_[newNumber] = newSize; for (i = start; i < end; i++) { iRow = indices_[i]; if (!which[iRow]) newIndices[newSize++] = iRow; } start = startNegative_[iColumn]; end = startPositive_[iColumn+1]; startNegative_[newNumber] = newSize; for (i = start; i < end; i++) { iRow = indices_[i]; if (!which[iRow]) newIndices[newSize++] = iRow; } } startPositive_[numberColumns_] = newSize; delete [] which; delete [] indices_; indices_ = newIndices; numberRows_ = newNumber; } bool ClpPlusMinusOneMatrix::isColOrdered() const { return columnOrdered_; } /* Number of entries in the packed matrix. */ CoinBigIndex ClpPlusMinusOneMatrix::getNumElements() const { int numberMajor = (columnOrdered_) ? numberColumns_ : numberRows_; if (startPositive_) return startPositive_[numberMajor]; else return 0; } // pass in copy (object takes ownership) void ClpPlusMinusOneMatrix::passInCopy(int numberRows, int numberColumns, bool columnOrdered, int * indices, CoinBigIndex * startPositive, CoinBigIndex * startNegative) { columnOrdered_ = columnOrdered; startPositive_ = startPositive; startNegative_ = startNegative; indices_ = indices; numberRows_ = numberRows; numberColumns_ = numberColumns; // Check valid checkValid(false); } // Just checks matrix valid - will say if dimensions not quite right if detail void ClpPlusMinusOneMatrix::checkValid(bool detail) const { int maxIndex = -1; int minIndex = columnOrdered_ ? numberRows_ : numberColumns_; int number = !columnOrdered_ ? numberRows_ : numberColumns_; int numberElements = getNumElements(); CoinBigIndex last = -1; int bad = 0; for (int i = 0; i < number; i++) { if(startPositive_[i] < last) bad++; else last = startPositive_[i]; if(startNegative_[i] < last) bad++; else last = startNegative_[i]; } if(startPositive_[number] < last) bad++; CoinAssertHint(!bad, "starts are not monotonic"); for (CoinBigIndex cbi = 0; cbi < numberElements; cbi++) { maxIndex = CoinMax(indices_[cbi], maxIndex); minIndex = CoinMin(indices_[cbi], minIndex); } CoinAssert(maxIndex < (columnOrdered_ ? numberRows_ : numberColumns_)); CoinAssert(minIndex >= 0); if (detail) { if (minIndex > 0 || maxIndex + 1 < (columnOrdered_ ? numberRows_ : numberColumns_)) printf("Not full range of indices - %d to %d\n", minIndex, maxIndex); } } /* Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ CoinBigIndex * ClpPlusMinusOneMatrix::dubiousWeights(const ClpSimplex * model, int * inputWeights) const { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int number = numberRows + numberColumns; CoinBigIndex * weights = new CoinBigIndex[number]; int i; for (i = 0; i < numberColumns; i++) { CoinBigIndex j; CoinBigIndex count = 0; for (j = startPositive_[i]; j < startPositive_[i+1]; j++) { int iRow = indices_[j]; count += inputWeights[iRow]; } weights[i] = count; } for (i = 0; i < numberRows; i++) { weights[i+numberColumns] = inputWeights[i]; } return weights; } // Append Columns void ClpPlusMinusOneMatrix::appendCols(int number, const CoinPackedVectorBase * const * columns) { int iColumn; CoinBigIndex size = 0; int numberBad = 0; for (iColumn = 0; iColumn < number; iColumn++) { int n = columns[iColumn]->getNumElements(); const double * element = columns[iColumn]->getElements(); size += n; int i; for (i = 0; i < n; i++) { if (fabs(element[i]) != 1.0) numberBad++; } } if (numberBad) throw CoinError("Not +- 1", "appendCols", "ClpPlusMinusOneMatrix"); // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; int numberNow = startPositive_[numberColumns_]; CoinBigIndex * temp; temp = new CoinBigIndex [numberColumns_+1+number]; CoinMemcpyN(startPositive_, (numberColumns_ + 1), temp); delete [] startPositive_; startPositive_ = temp; temp = new CoinBigIndex [numberColumns_+number]; CoinMemcpyN(startNegative_, numberColumns_, temp); delete [] startNegative_; startNegative_ = temp; int * temp2 = new int [numberNow+size]; CoinMemcpyN(indices_, numberNow, temp2); delete [] indices_; indices_ = temp2; // now add size = numberNow; for (iColumn = 0; iColumn < number; iColumn++) { int n = columns[iColumn]->getNumElements(); const int * row = columns[iColumn]->getIndices(); const double * element = columns[iColumn]->getElements(); int i; for (i = 0; i < n; i++) { if (element[i] == 1.0) indices_[size++] = row[i]; } startNegative_[iColumn+numberColumns_] = size; for (i = 0; i < n; i++) { if (element[i] == -1.0) indices_[size++] = row[i]; } startPositive_[iColumn+numberColumns_+1] = size; } numberColumns_ += number; } // Append Rows void ClpPlusMinusOneMatrix::appendRows(int number, const CoinPackedVectorBase * const * rows) { // Allocate arrays to use for counting int * countPositive = new int [numberColumns_+1]; memset(countPositive, 0, numberColumns_ * sizeof(int)); int * countNegative = new int [numberColumns_]; memset(countNegative, 0, numberColumns_ * sizeof(int)); int iRow; CoinBigIndex size = 0; int numberBad = 0; for (iRow = 0; iRow < number; iRow++) { int n = rows[iRow]->getNumElements(); const int * column = rows[iRow]->getIndices(); const double * element = rows[iRow]->getElements(); size += n; int i; for (i = 0; i < n; i++) { int iColumn = column[i]; if (element[i] == 1.0) countPositive[iColumn]++; else if (element[i] == -1.0) countNegative[iColumn]++; else numberBad++; } } if (numberBad) throw CoinError("Not +- 1", "appendRows", "ClpPlusMinusOneMatrix"); // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; int numberNow = startPositive_[numberColumns_]; int * newIndices = new int [numberNow+size]; // Update starts and turn counts into positions // also move current indices int iColumn; CoinBigIndex numberAdded = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { int n, move; CoinBigIndex now; now = startPositive_[iColumn]; move = startNegative_[iColumn] - now; n = countPositive[iColumn]; startPositive_[iColumn] += numberAdded; CoinMemcpyN(newIndices + startPositive_[iColumn], move, indices_ + now); countPositive[iColumn] = startNegative_[iColumn] + numberAdded; numberAdded += n; now = startNegative_[iColumn]; move = startPositive_[iColumn+1] - now; n = countNegative[iColumn]; startNegative_[iColumn] += numberAdded; CoinMemcpyN(newIndices + startNegative_[iColumn], move, indices_ + now); countNegative[iColumn] = startPositive_[iColumn+1] + numberAdded; numberAdded += n; } delete [] indices_; indices_ = newIndices; startPositive_[numberColumns_] += numberAdded; // Now put in for (iRow = 0; iRow < number; iRow++) { int newRow = numberRows_ + iRow; int n = rows[iRow]->getNumElements(); const int * column = rows[iRow]->getIndices(); const double * element = rows[iRow]->getElements(); int i; for (i = 0; i < n; i++) { int iColumn = column[i]; int put; if (element[i] == 1.0) { put = countPositive[iColumn]; countPositive[iColumn] = put + 1; } else { put = countNegative[iColumn]; countNegative[iColumn] = put + 1; } indices_[put] = newRow; } } delete [] countPositive; delete [] countNegative; numberRows_ += number; } /* Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ void ClpPlusMinusOneMatrix::rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive) { int iColumn; bool plusOne = false; bool minusOne = false; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (startNegative_[iColumn] > startPositive_[iColumn]) plusOne = true; if (startPositive_[iColumn+1] > startNegative_[iColumn]) minusOne = true; } if (minusOne) { smallestNegative = -1.0; largestNegative = -1.0; } else { smallestNegative = 0.0; largestNegative = 0.0; } if (plusOne) { smallestPositive = 1.0; largestPositive = 1.0; } else { smallestPositive = 0.0; largestPositive = 0.0; } } // Says whether it can do partial pricing bool ClpPlusMinusOneMatrix::canDoPartialPricing() const { return true; } // Partial pricing void ClpPlusMinusOneMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; int start = static_cast (startFraction * numberColumns_); int end = CoinMin(static_cast (endFraction * numberColumns_ + 1), numberColumns_); CoinBigIndex j; double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); const double * cost = model->costRegion(); double bestDj; if (bestSequence >= 0) bestDj = fabs(reducedCost[bestSequence]); else bestDj = tolerance; int sequenceOut = model->sequenceOut(); int saveSequence = bestSequence; int iSequence; for (iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = cost[iSequence]; j = startPositive_[iSequence]; for (; j < startNegative_[iSequence]; j++) { int iRow = indices_[j]; value -= duals[iRow]; } for (; j < startPositive_[iSequence+1]; j++) { int iRow = indices_[j]; value += duals[iRow]; } value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence]; j = startPositive_[iSequence]; for (; j < startNegative_[iSequence]; j++) { int iRow = indices_[j]; value -= duals[iRow]; } for (; j < startPositive_[iSequence+1]; j++) { int iRow = indices_[j]; value += duals[iRow]; } if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = cost[iSequence]; j = startPositive_[iSequence]; for (; j < startNegative_[iSequence]; j++) { int iRow = indices_[j]; value -= duals[iRow]; } for (; j < startPositive_[iSequence+1]; j++) { int iRow = indices_[j]; value += duals[iRow]; } value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = cost[bestSequence]; j = startPositive_[bestSequence]; for (; j < startNegative_[bestSequence]; j++) { int iRow = indices_[j]; value -= duals[iRow]; } for (; j < startPositive_[bestSequence+1]; j++) { int iRow = indices_[j]; value += duals[iRow]; } reducedCost[bestSequence] = value; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } currentWanted_ = numberWanted; } // Allow any parts of a created CoinMatrix to be deleted void ClpPlusMinusOneMatrix::releasePackedMatrix() const { delete matrix_; delete [] lengths_; matrix_ = NULL; lengths_ = NULL; } /* Returns true if can combine transposeTimes and subsetTransposeTimes and if it would be faster */ bool ClpPlusMinusOneMatrix::canCombine(const ClpSimplex * model, const CoinIndexedVector * pi) const { int numberInRowArray = pi->getNumElements(); int numberRows = model->numberRows(); bool packed = pi->packedMode(); // factor should be smaller if doing both with two pi vectors double factor = 0.27; // We may not want to do by row if there may be cache problems // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberColumns_ * sizeof(double) > 1000000) { if (numberRows * 10 < numberColumns_) factor *= 0.333333333; else if (numberRows * 4 < numberColumns_) factor *= 0.5; else if (numberRows * 2 < numberColumns_) factor *= 0.66666666667; //if (model->numberIterations()%50==0) //printf("%d nonzero\n",numberInRowArray); } // if not packed then bias a bit more towards by column if (!packed) factor *= 0.9; return (numberInRowArray > factor * numberRows || !model->rowCopy()); } // These have to match ClpPrimalColumnSteepest version #define reference(i) (((reference[i>>5]>>(i&31))&1)!=0) // Updates two arrays for steepest void ClpPlusMinusOneMatrix::transposeTimes2(const ClpSimplex * model, const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * spare, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { // put row of tableau in dj1 double * pi = pi1->denseVector(); int numberNonZero = 0; int * index = dj1->getIndices(); double * array = dj1->denseVector(); int numberInRowArray = pi1->getNumElements(); double zeroTolerance = model->zeroTolerance(); bool packed = pi1->packedMode(); // do by column int iColumn; assert (!spare->getNumElements()); double * piWeight = pi2->denseVector(); assert (!pi2->packedMode()); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; // Note scale factor was -1.0 if (packed) { // need to expand pi into y assert(spare->capacity() >= model->numberRows()); double * piOld = pi; pi = spare->denseVector(); const int * whichRow = pi1->getIndices(); int i; // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = piOld[i]; } CoinBigIndex j; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double value = 0.0; for (j = startPositive_[iColumn]; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; value -= pi[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; value += pi[iRow]; } if (fabs(value) > zeroTolerance) { // and do other array double modification = 0.0; for (j = startPositive_[iColumn]; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; modification += piWeight[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; modification -= piWeight[iRow]; } double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } // zero out for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { CoinBigIndex j; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double value = 0.0; for (j = startPositive_[iColumn]; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; value -= pi[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; value += pi[iRow]; } if (fabs(value) > zeroTolerance) { // and do other array double modification = 0.0; for (j = startPositive_[iColumn]; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; modification += piWeight[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; modification -= piWeight[iRow]; } double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[iColumn] = value; index[numberNonZero++] = iColumn; } } } } dj1->setNumElements(numberNonZero); spare->setNumElements(0); if (packed) dj1->setPackedMode(true); } // Updates second array for steepest and does devex weights void ClpPlusMinusOneMatrix::subsetTimes2(const ClpSimplex * , CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector *, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { int number = dj1->getNumElements(); const int * index = dj1->getIndices(); double * array = dj1->denseVector(); assert( dj1->packedMode()); double * piWeight = pi2->denseVector(); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; for (int k = 0; k < number; k++) { int iColumn = index[k]; double pivot = array[k] * scaleFactor; if (killDjs) array[k] = 0.0; // and do other array double modification = 0.0; CoinBigIndex j; for (j = startPositive_[iColumn]; j < startNegative_[iColumn]; j++) { int iRow = indices_[j]; modification += piWeight[iRow]; } for (; j < startPositive_[iColumn+1]; j++) { int iRow = indices_[j]; modification -= piWeight[iRow]; } double thisWeight = weights[iColumn]; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; } } /* Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ void ClpPlusMinusOneMatrix::setDimensions(int newnumrows, int newnumcols) { if (newnumrows < 0) newnumrows = numberRows_; if (newnumrows < numberRows_) throw CoinError("Bad new rownum (less than current)", "setDimensions", "CoinPackedMatrix"); if (newnumcols < 0) newnumcols = numberColumns_; if (newnumcols < numberColumns_) throw CoinError("Bad new colnum (less than current)", "setDimensions", "CoinPackedMatrix"); int number = 0; int length = 0; if (columnOrdered_) { length = numberColumns_; numberColumns_ = newnumcols; number = numberColumns_; } else { length = numberRows_; numberRows_ = newnumrows; number = numberRows_; } if (number > length) { CoinBigIndex * temp; int i; CoinBigIndex end = startPositive_[length]; temp = new CoinBigIndex [number+1]; CoinMemcpyN(startPositive_, (length + 1), temp); delete [] startPositive_; for (i = length + 1; i < number + 1; i++) temp[i] = end; startPositive_ = temp; temp = new CoinBigIndex [number]; CoinMemcpyN(startNegative_, length, temp); delete [] startNegative_; for (i = length; i < number; i++) temp[i] = end; startNegative_ = temp; } } #ifndef SLIM_CLP /* Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ int ClpPlusMinusOneMatrix::appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int /*numberOther*/) { int numberErrors = 0; // make into CoinPackedVector CoinPackedVectorBase ** vectors = new CoinPackedVectorBase * [number]; int iVector; for (iVector = 0; iVector < number; iVector++) { int iStart = starts[iVector]; vectors[iVector] = new CoinPackedVector(starts[iVector+1] - iStart, index + iStart, element + iStart); } if (type == 0) { // rows appendRows(number, vectors); } else { // columns appendCols(number, vectors); } for (iVector = 0; iVector < number; iVector++) delete vectors[iVector]; delete [] vectors; return numberErrors; } #endif Clp-1.15.10/src/CoinAbcCommon.hpp0000644000076600007660000002351512101105055015016 0ustar coincoin/* $Id: CoinAbcCommon.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2000, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CoinAbcCommon_H #define CoinAbcCommon_H #ifndef COIN_FAC_NEW #define COIN_FAC_NEW #endif #include "CoinPragma.hpp" #include "CoinUtilsConfig.h" #include #include #include #include #include #include "AbcCommon.hpp" #include "CoinHelperFunctions.hpp" //#include "config.h" typedef double CoinSimplexDouble; typedef int CoinSimplexInt; typedef unsigned int CoinSimplexUnsignedInt; //#define MOVE_REPLACE_PART1A #if defined(_MSC_VER) #define ABC_INLINE __forceinline #elif defined(__GNUC__) #define ABC_INLINE __attribute__((always_inline)) #else #define ABC_INLINE #endif #ifndef ABC_PARALLEL #ifdef HAS_CILK #define ABC_PARALLEL 2 #else #define ABC_PARALLEL 0 #endif #endif #if ABC_PARALLEL==2 //#define EARLY_FACTORIZE #ifndef FAKE_CILK #include #else #define cilk_for for #define cilk_spawn #define cilk_sync #endif #else #define cilk_for for #define cilk_spawn #define cilk_sync //#define ABC_PARALLEL 1 #endif #define SLACK_VALUE 1 #define ABC_INSTRUMENT 1 //2 #if ABC_INSTRUMENT!=2 // Below so can do deterministic B&B #define instrument_start(name,x) #define instrument_add(x) #define instrument_end() // one off #define instrument_do(name,x) // as end but multiply by factor #define instrument_end_and_adjust(x) #else void instrument_start(const char * type,int numberRowsEtc); void instrument_add(int count); void instrument_do(const char * type,double count); void instrument_end(); void instrument_end_and_adjust(double factor); #endif #ifndef __BYTE_ORDER #include #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define ABC_INTEL #endif #if COIN_BIG_DOUBLE==1 #undef USE_TEST_ZERO #undef USE_TEST_REALLY_ZERO #undef USE_TEST_ZERO_REGISTER #undef USE_TEST_LESS_TOLERANCE #undef USE_TEST_LESS_TOLERANCE_REGISTER #define CoinFabs(x) fabsl(x) #else #define CoinFabs(x) fabs(x) #endif #ifdef USE_TEST_ZERO #if __BYTE_ORDER == __LITTLE_ENDIAN #define TEST_DOUBLE_NONZERO(x) ((reinterpret_cast(&x))[1]!=0) #else #define TEST_DOUBLE_NONZERO(x) ((reinterpret_cast(&x))[0]!=0) #endif #else //always drop through #define TEST_DOUBLE_NONZERO(x) (true) #endif #define USE_TEST_INT_ZERO #ifdef USE_TEST_INT_ZERO #define TEST_INT_NONZERO(x) (x) #else //always drop through #define TEST_INT_NONZERO(x) (true) #endif #ifdef USE_TEST_REALLY_ZERO #if __BYTE_ORDER == __LITTLE_ENDIAN #define TEST_DOUBLE_REALLY_NONZERO(x) ((reinterpret_cast(&x))[1]!=0) #else #define TEST_DOUBLE_REALLY_NONZERO(x) ((reinterpret_cast(&x))[0]!=0) #endif #else #define TEST_DOUBLE_REALLY_NONZERO(x) (x) #endif #ifdef USE_TEST_ZERO_REGISTER #if __BYTE_ORDER == __LITTLE_ENDIAN #define TEST_DOUBLE_NONZERO_REGISTER(x) ((reinterpret_cast(&x))[1]!=0) #else #define TEST_DOUBLE_NONZERO_REGISTER(x) ((reinterpret_cast(&x))[0]!=0) #endif #else //always drop through #define TEST_DOUBLE_NONZERO_REGISTER(x) (true) #endif #define USE_FIXED_ZERO_TOLERANCE #ifdef USE_FIXED_ZERO_TOLERANCE // 3d400000... 0.5**43 approx 1.13687e-13 #ifdef USE_TEST_LESS_TOLERANCE #if __BYTE_ORDER == __LITTLE_ENDIAN #define TEST_LESS_THAN_TOLERANCE(x) ((reinterpret_cast(&x))[1]&0x7ff00000<0x3d400000) #define TEST_LESS_THAN_UPDATE_TOLERANCE(x) ((reinterpret_cast(&x))[1]&0x7ff00000<0x3d400000) #else #define TEST_LESS_THAN_TOLERANCE(x) ((reinterpret_cast(&x))[0]&0x7ff00000<0x3d400000) #define TEST_LESS_THAN_UPDATE_TOLERANCE(x) ((reinterpret_cast(&x))[0]&0x7ff00000<0x3d400000) #endif #else #define TEST_LESS_THAN_TOLERANCE(x) (fabs(x)(&x))[1]&0x7ff00000<0x3d400000) #else #define TEST_LESS_THAN_TOLERANCE_REGISTER(x) ((reinterpret_cast(&x))[0]&0x7ff00000<0x3d400000) #endif #else #define TEST_LESS_THAN_TOLERANCE_REGISTER(x) (fabs(x)(&x))[1]&0x7ff00000) #else #define ABC_EXPONENT(x) ((reinterpret_cast(&x))[0]&0x7ff00000) #endif #define TEST_EXPONENT_LESS_THAN_TOLERANCE(x) (x<0x3d400000) #define TEST_EXPONENT_LESS_THAN_UPDATE_TOLERANCE(x) (x<0x3d400000) #define TEST_EXPONENT_NON_ZERO(x) (x) #else typedef long double CoinExponent; #define ABC_EXPONENT(x) (x) #define TEST_EXPONENT_LESS_THAN_TOLERANCE(x) (fabs(x) inline void CoinAbcMemset0(register T* to, const int size) { #ifndef NDEBUG // Some debug so check if (size < 0) throw CoinError("trying to fill negative number of entries", "CoinAbcMemset0", ""); #endif std::memset(to,0,size*sizeof(T)); } template inline void CoinAbcMemcpy(register T* to, register const T* from, const int size ) { #ifndef NDEBUG // Some debug so check if (size < 0) throw CoinError("trying to copy negative number of entries", "CoinAbcMemcpy", ""); #endif std::memcpy(to,from,size*sizeof(T)); } class ClpSimplex; class AbcSimplex; class AbcTolerancesEtc { public: ///@name Constructors and destructors //@{ /// Default Constructor AbcTolerancesEtc(); /// Useful Constructors AbcTolerancesEtc(const ClpSimplex * model); AbcTolerancesEtc(const AbcSimplex * model); /// Copy constructor AbcTolerancesEtc(const AbcTolerancesEtc &); /// Assignment operator AbcTolerancesEtc & operator=(const AbcTolerancesEtc& rhs); /// Destructor ~AbcTolerancesEtc (); //@} //--------------------------------------------------------------------------- public: ///@name Public member data //@{ /// Zero tolerance double zeroTolerance_; /// Primal tolerance needed to make dual feasible (= incomingInfeasibility this is always possible altough you may end up with an all slack basis. Defaults are 1.0,10.0 */ double incomingInfeasibility_; double allowedInfeasibility_; /// Iteration when we entered dual or primal int baseIteration_; /// How many iterative refinements to do int numberRefinements_; /** Now for some reliability aids This forces re-factorization early */ int forceFactorization_; /** Perturbation: -50 to +50 - perturb by this power of ten (-6 sounds good) 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 */ int perturbation_; /// If may skip final factorize then allow up to this pivots (default 20) int dontFactorizePivots_; /// For factorization /// Maximum number of pivots before factorization int maximumPivots_; //@} }; #endif Clp-1.15.10/src/ClpSimplexDual.hpp0000644000076600007660000003064011605104000015227 0ustar coincoin/* $Id: ClpSimplexDual.hpp 1761 2011-07-06 16:06:24Z 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). /* Authors John Forrest */ #ifndef ClpSimplexDual_H #define ClpSimplexDual_H #include "ClpSimplex.hpp" /** This solves LPs using the dual simplex method It inherits from ClpSimplex. It has no data of its own and is never created - only cast from a ClpSimplex object at algorithm time. */ class ClpSimplexDual : public ClpSimplex { public: /**@name Description of algorithm */ //@{ /** Dual algorithm Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of updatedDualBound_ being given to getting dual feasible. In this version I have used the idea that this weight can be thought of as a fake bound. If the distance between the lower and upper bounds on a variable is less than the feasibility weight then we are always better off flipping to other bound to make dual feasible. If the distance is greater then we make up a fake bound updatedDualBound_ away from one bound. If we end up optimal or primal infeasible, we check to see if bounds okay. If so we have finished, if not we increase updatedDualBound_ and continue (after checking if unbounded). I am undecided about free variables - there is coding but I am not sure about it. At present I put them in basis anyway. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find outgoing variable for Dantzig row choice. For steepest edge we keep an updated list of infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and some of what I think is the dual analog of Gill et al. I am still not sure of the exact details. The flow of dual is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by flipping variables so dual feasible. If looks finished check fake dual bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot row (outgoing variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot row in tableau Choose incoming column. If we don't find one then we look primal infeasible so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find incoming column, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve flipping variables to stay dual feasible. } } TODO's (or maybe not) At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot out option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. for use of exotic parameter startFinishoptions see Clpsimplex.hpp */ int dual(int ifValuesPass, int startFinishOptions = 0); /** For strong branching. On input lower and upper are new bounds while on output they are change in objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) Solutions are filled in as well - even down, odd up - also status and number of iterations */ int strongBranching(int numberVariables, const int * variables, double * newLower, double * newUpper, double ** outputSolution, int * outputStatus, int * outputIterations, bool stopOnFirstInfeasible = true, bool alwaysFinish = false, int startFinishOptions = 0); /// This does first part of StrongBranching ClpFactorization * setupForStrongBranching(char * arrays, int numberRows, int numberColumns, bool solveLp = false); /// This cleans up after strong branching void cleanupAfterStrongBranching(ClpFactorization * factorization); //@} /**@name Functions used in dual */ //@{ /** This has the flow between re-factorizations Broken out for clarity and will be used by strong branching Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations If givenPi not NULL then in values pass */ int whileIterating(double * & givenPi, int ifValuesPass); /** The duals are updated by the given arrays. Returns number of infeasibilities. After rowArray and columnArray will just have those which have been flipped. Variables may be flipped between bounds to stay dual feasible. The output vector has movement of primal solution (row length array) */ int updateDualsInDual(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * outputArray, double theta, double & objectiveChange, bool fullRecompute); /** The duals are updated by the given arrays. This is in values pass - so no changes to primal is made */ void updateDualsInValuesPass(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double theta); /** While updateDualsInDual sees what effect is of flip this does actual flipping. */ void flipBounds(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray); /** Row array has row part of pivot row Column array has column part. This chooses pivot column. Spare arrays are used to save pivots which will go infeasible We will check for basic so spare array will never overflow. If necessary will modify costs For speed, we may need to go to a bucket approach when many variables are being flipped. Returns best possible pivot value */ double dualColumn(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * spareArray, CoinIndexedVector * spareArray2, double accpetablePivot, CoinBigIndex * dubiousWeights); /// Does first bit of dualColumn int dualColumn0(const CoinIndexedVector * rowArray, const CoinIndexedVector * columnArray, CoinIndexedVector * spareArray, double acceptablePivot, double & upperReturn, double &bestReturn, double & badFree); /** Row array has row part of pivot row Column array has column part. This sees what is best thing to do in dual values pass if sequenceIn==sequenceOut can change dual on chosen row and leave variable in basis */ void checkPossibleValuesMove(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double acceptablePivot); /** Row array has row part of pivot row Column array has column part. This sees what is best thing to do in branch and bound cleanup If sequenceIn_ < 0 then can't do anything */ void checkPossibleCleanup(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double acceptablePivot); /** This sees if we can move duals in dual values pass. This is done before any pivoting */ void doEasyOnesInValuesPass(double * givenReducedCosts); /** Chooses dual pivot row Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first rows we look at If alreadyChosen >=0 then in values pass and that row has been selected */ void dualRow(int alreadyChosen); /** Checks if any fake bounds active - if so returns number and modifies updatedDualBound_ and everything. Free variables will be left as free Returns number of bounds changed if >=0 Returns -1 if not initialize and no effect Fills in changeVector which can be used to see if unbounded and cost of change vector If 2 sets to original (just changed) */ int changeBounds(int initialize, CoinIndexedVector * outputArray, double & changeCost); /** As changeBounds but just changes new bounds for a single variable. Returns true if change */ bool changeBound( int iSequence); /// Restores bound to original bound void originalBound(int iSequence); /** Checks if tentative optimal actually means unbounded in dual Returns -3 if not, 2 if is unbounded */ int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, double changeCost); /** Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void statusOfProblemInDual(int & lastCleaned, int type, double * givenDjs, ClpDataSave & saveData, int ifValuesPass); /** Perturbs problem (method depends on perturbation()) returns nonzero if should go to dual */ int perturb(); /** Fast iterations. Misses out a lot of initialization. Normally stops on maximum iterations, first re-factorization or tentative optimum. If looks interesting then continues as normal. Returns 0 if finished properly, 1 otherwise. */ int fastDual(bool alwaysFinish = false); /** Checks number of variables at fake bounds. This is used by fastDual so can exit gracefully before end */ int numberAtFakeBound(); /** Pivot in a variable and choose an outgoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Return codes as before but -1 means no acceptable pivot */ int pivotResultPart1(); /** Get next free , -1 if none */ int nextSuperBasic(); /** Startup part of dual (may be extended to other algorithms) returns 0 if good, 1 if bad */ int startupSolve(int ifValuesPass, double * saveDuals, int startFinishOptions); void finishSolve(int startFinishOptions); void gutsOfDual(int ifValuesPass, double * & saveDuals, int initialStatus, ClpDataSave & saveData); //int dual2(int ifValuesPass,int startFinishOptions=0); void resetFakeBounds(int type); //@} }; #endif Clp-1.15.10/src/ClpPdco.hpp0000644000076600007660000000335311510657452013711 0ustar coincoin/* $Id: ClpPdco.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). /* Authors John Tomlin */ #ifndef ClpPdco_H #define ClpPdco_H #include "ClpInterior.hpp" /** This solves problems in Primal Dual Convex Optimization It inherits from ClpInterior. It has no data of its own and is never created - only cast from a ClpInterior object at algorithm time. */ class ClpPdco : public ClpInterior { public: /**@name Description of algorithm */ //@{ /** Pdco algorithm Method */ int pdco(); // ** Temporary version int pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo); //@} /**@name Functions used in pdco */ //@{ /// LSQR void lsqr(); void matVecMult( int, double *, double *); void matVecMult( int, CoinDenseVector &, double *); void matVecMult( int, CoinDenseVector &, CoinDenseVector &); void matVecMult( int, CoinDenseVector *, CoinDenseVector *); void getBoundTypes( int *, int *, int *, int**); void getGrad(CoinDenseVector &x, CoinDenseVector &grad); void getHessian(CoinDenseVector &x, CoinDenseVector &H); double getObj(CoinDenseVector &x); void matPrecon( double, double *, double *); void matPrecon( double, CoinDenseVector &, double *); void matPrecon( double, CoinDenseVector &, CoinDenseVector &); void matPrecon( double, CoinDenseVector *, CoinDenseVector *); //@} }; #endif Clp-1.15.10/src/CoinAbcOrderedFactorization1.cpp0000644000076600007660000000107712101105055017762 0ustar coincoin/* $Id: CoinAbcOrderedFactorization1.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -1 #define ABC_ORDERED_FACTORIZATION #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization1.cpp" #endif Clp-1.15.10/src/OsiClp/0000755000076600007660000000000012377556130013044 5ustar coincoinClp-1.15.10/src/OsiClp/OsiClpSolverInterface.hpp0000644000076600007660000016051512130015370017751 0ustar coincoin// $Id$ // 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 OsiClpSolverInterface_H #define OsiClpSolverInterface_H #include #include #include #include "ClpSimplex.hpp" #include "ClpLinearObjective.hpp" #include "CoinPackedMatrix.hpp" #include "OsiSolverInterface.hpp" #include "CoinWarmStartBasis.hpp" #include "ClpEventHandler.hpp" #include "ClpNode.hpp" #include "CoinIndexedVector.hpp" #include "CoinFinite.hpp" class OsiRowCut; class OsiClpUserSolver; class OsiClpDisasterHandler; class CoinSet; static const double OsiClpInfinity = COIN_DBL_MAX; //############################################################################# /** Clp Solver Interface Instantiation of OsiClpSolverInterface for the Model Algorithm. */ class OsiClpSolverInterface : virtual public OsiSolverInterface { friend void OsiClpSolverInterfaceUnitTest(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(); /// Resolve an LP relaxation after problem modification (try GUB) virtual void resolveGub(int needed); /// Invoke solver's built-in enumeration algorithm virtual void branchAndBound(); /** Solve when primal column and dual row solutions are near-optimal options - 0 no presolve (use primal and dual) 1 presolve (just use primal) 2 no presolve (just use primal) basis - 0 use all slack basis 1 try and put some in basis */ void crossover(int options,int basis); //@} /*! @name OsiSimplexInterface methods \brief Methods for the Osi Simplex API. The current implementation should work for both minimisation and maximisation in mode 1 (tableau access). In mode 2 (single pivot), only minimisation is supported as of 100907. */ //@{ /** \brief Simplex API capability. Returns - 0 if no simplex API - 1 if can just do getBInv etc - 2 if has all OsiSimplex methods */ virtual int canDoSimplexInterface() const; /*! \brief Enables simplex mode 1 (tableau access) Tells solver that calls to getBInv etc are about to take place. Underlying code may need mutable as this may be called from CglCut::generateCuts which is const. If that is too horrific then each solver e.g. BCP or CBC will have to do something outside main loop. */ virtual void enableFactorization() const; /*! \brief Undo any setting changes made by #enableFactorization */ virtual void disableFactorization() const; /** Returns true if a basis is available AND problem is optimal. This should be used to see if the BInvARow type operations are possible and meaningful. */ virtual bool basisIsAvailable() const; /** The following two methods may be replaced by the methods of OsiSolverInterface using OsiWarmStartBasis if: 1. OsiWarmStartBasis resize operation is implemented more efficiently and 2. It is ensured that effects on the solver are the same Returns a basis status of the structural/artificial variables At present as warm start i.e 0 free, 1 basic, 2 upper, 3 lower NOTE artificials are treated as +1 elements so for <= rhs artificial will be at lower bound if constraint is tight This means that Clpsimplex flips artificials as it works in terms of row activities */ virtual void getBasisStatus(int* cstat, int* rstat) const; /** Set the status of structural/artificial variables and factorize, update solution etc NOTE artificials are treated as +1 elements so for <= rhs artificial will be at lower bound if constraint is tight This means that Clpsimplex flips artificials as it works in terms of row activities Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ... */ virtual int setBasisStatus(const int* cstat, const int* rstat); ///Get the reduced gradient for the cost vector c virtual void getReducedGradient(double* columnReducedCosts, double * duals, const double * c) const ; ///Get a row of the tableau (slack part in slack if not NULL) virtual void getBInvARow(int row, double* z, double * slack=NULL) const; /** Get a row of the tableau (slack part in slack if not NULL) If keepScaled is true then scale factors not applied after so user has to use coding similar to what is in this method */ virtual void getBInvARow(int row, CoinIndexedVector * z, CoinIndexedVector * slack=NULL, bool keepScaled=false) const; ///Get a row of the basis inverse virtual void getBInvRow(int row, double* z) const; ///Get a column of the tableau virtual void getBInvACol(int col, double* vec) const ; ///Get a column of the tableau virtual void getBInvACol(int col, CoinIndexedVector * vec) const ; /** Update (i.e. ftran) the vector passed in. Unscaling is applied after - can't be applied before */ virtual void getBInvACol(CoinIndexedVector * vec) const ; ///Get a column of the basis inverse virtual void getBInvCol(int col, double* vec) const ; /** Get basic indices (order of indices corresponds to the order of elements in a vector retured by getBInvACol() and getBInvCol()). */ virtual void getBasics(int* index) const; /*! \brief Enables simplex mode 2 (individual pivot control) This method is supposed to ensure that all typical things (like reduced costs, etc.) are updated when individual pivots are executed and can be queried by other methods. */ virtual void enableSimplexInterface(bool doingPrimal); /// Copy across enabled stuff from one solver to another void copyEnabledSuff(OsiClpSolverInterface & rhs); /*! \brief Undo setting changes made by #enableSimplexInterface */ virtual void disableSimplexInterface(); /// Copy across enabled stuff from one solver to another void copyEnabledStuff(ClpSimplex & rhs); /** Perform a pivot by substituting a colIn for colOut in the basis. The status of the leaving variable is given in statOut. Where 1 is to upper bound, -1 to lower bound Return code is 0 for okay, 1 if inaccuracy forced re-factorization (should be okay) and -1 for singular factorization */ virtual int pivot(int colIn, int colOut, int outStatus); /** Obtain a result of the primal pivot Outputs: colOut -- leaving column, outStatus -- its status, t -- step size, and, if dx!=NULL, *dx -- primal ray direction. Inputs: colIn -- entering column, sign -- direction of its change (+/-1). Both for colIn and colOut, artificial variables are index by the negative of the row index minus 1. Return code (for now): 0 -- leaving variable found, -1 -- everything else? Clearly, more informative set of return values is required Primal and dual solutions are updated */ virtual int primalPivotResult(int colIn, int sign, int& colOut, int& outStatus, double& t, CoinPackedVector* dx); /** Obtain a result of the dual pivot (similar to the previous method) Differences: entering variable and a sign of its change are now the outputs, the leaving variable and its statuts -- the inputs If dx!=NULL, then *dx contains dual ray Return code: same */ virtual int dualPivotResult(int& colIn, int& sign, int colOut, int outStatus, double& t, CoinPackedVector* dx); //@} //--------------------------------------------------------------------------- /**@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 clp 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); //@} //--------------------------------------------------------------------------- ///@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; /// Get warmstarting information inline CoinWarmStartBasis* getPointerToWarmStart() { return &basis_;} /// Get warmstarting information inline const CoinWarmStartBasis* getConstPointerToWarmStart() const { return &basis_;} /** Set warmstarting information. Return true/false depending on whether the warmstart information was accepted or not. */ virtual bool setWarmStart(const CoinWarmStart* warmstart); /** \brief Get warm start information. Return warm start information for the current state of the solver interface. If there is no valid warm start information, an empty warm start object wil be returned. This does not necessarily create an object - may just point to one. must Delete set true if user should delete returned object. OsiClp version always returns pointer and false. */ virtual CoinWarmStart* getPointerToWarmStart(bool & mustDelete) ; //@} //--------------------------------------------------------------------------- /**@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(); /** Start faster dual - returns negative if problems 1 if infeasible, Options to pass to solver 1 - create external reduced costs for columns 2 - create external reduced costs for rows 4 - create external row activity (columns always done) Above only done if feasible When set resolve does less work */ int startFastDual(int options); /// Stop fast dual void stopFastDual(); /// Sets integer tolerance and increment void setStuff(double tolerance,double increment); //@} //--------------------------------------------------------------------------- /**@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 { return modelPtr_->numberColumns(); } /// Get number of rows virtual int getNumRows() const { return modelPtr_->numberRows(); } /// Get number of nonzero elements virtual int getNumElements() const { int retVal = 0; const CoinPackedMatrix * matrix =modelPtr_->matrix(); if ( matrix != NULL ) retVal=matrix->getNumElements(); return retVal; } /// Return name of row if one exists or Rnnnnnnn /// maxLen is currently ignored and only there to match the signature from the base class! virtual std::string getRowName(int rowIndex, unsigned maxLen = static_cast(std::string::npos)) const; /// Return name of column if one exists or Cnnnnnnn /// maxLen is currently ignored and only there to match the signature from the base class! virtual std::string getColName(int colIndex, unsigned maxLen = static_cast(std::string::npos)) const; /// Get pointer to array[getNumCols()] of column lower bounds virtual const double * getColLower() const { return modelPtr_->columnLower(); } /// Get pointer to array[getNumCols()] of column upper bounds virtual const double * getColUpper() const { return modelPtr_->columnUpper(); } /** 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 { return modelPtr_->rowLower(); } /// Get pointer to array[getNumRows()] of row upper bounds virtual const double * getRowUpper() const { return modelPtr_->rowUpper(); } /// Get pointer to array[getNumCols()] of objective function coefficients virtual const double * getObjCoefficients() const { if (fakeMinInSimplex_) return linearObjective_ ; else return modelPtr_->objective(); } /// Get objective function sense (1 for min (default), -1 for max) virtual double getObjSense() const { return ((fakeMinInSimplex_)?-modelPtr_->optimizationDirection(): modelPtr_->optimizationDirection()); } /// Return true if column is continuous virtual bool isContinuous(int colNumber) const; /// Return true if variable is binary virtual bool isBinary(int colIndex) const; /** Return true if column is integer. Note: This function returns true if the the column is binary or a general integer. */ virtual bool isInteger(int colIndex) const; /// Return true if variable is general integer virtual bool isIntegerNonBinary(int colIndex) const; /// Return true if variable is binary and not fixed at either bound virtual bool isFreeBinary(int colIndex) const; /** Return array of column length 0 - continuous 1 - binary (may get fixed later) 2 - general integer (may get fixed later) */ virtual const char * getColType(bool refresh=false) const; /** Return true if column is integer but does not have to be declared as such. Note: This function returns true if the the column is binary or a general integer. */ bool isOptionalInteger(int colIndex) const; /** Set the index-th variable to be an optional integer variable */ void setOptionalInteger(int index); /// 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 pointer to mutable column-wise copy of matrix virtual CoinPackedMatrix * getMutableMatrixByCol() const; /// Get solver's value for infinity virtual double getInfinity() const { return OsiClpInfinity; } //@} /**@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 { return modelPtr_->numberIterations(); } /** 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 Problem modifying methods */ //@{ //------------------------------------------------------------------------- /**@name Changing bounds on variables and constraints */ //@{ /** Set an objective function coefficient */ virtual void setObjCoeff( int elementIndex, double elementValue ); /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ virtual void setColLower( int elementIndex, double elementValue ); /** 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); /** Set the objective coefficients for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ virtual void setObjective(const double * array); /** Set the lower bounds for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ virtual void setColLower(const double * array); /** Set the upper bounds for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ virtual void setColUpper(const double * array); // using OsiSolverInterface::setRowName ; /// Set name of row // virtual void setRowName(int rowIndex, std::string & name) ; virtual void setRowName(int rowIndex, std::string name) ; // using OsiSolverInterface::setColName ; /// Set name of column // virtual void setColName(int colIndex, std::string & name) ; virtual void setColName(int colIndex, std::string name) ; //@} //------------------------------------------------------------------------- /**@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); /// Number of SOS sets inline int numberSOS() const { return numberSOS_;} /// SOS set info inline const CoinSet * setInfo() const { return setInfo_;} /** \brief Identify integer variables and SOS and create corresponding objects. Record integer variables and create an OsiSimpleInteger object for each one. All existing OsiSimpleInteger objects will be destroyed. If the solver supports SOS then do the same for SOS. If justCount then no objects created and we just store numberIntegers_ Returns number of SOS */ virtual int findIntegersAndSOS(bool justCount); //@} //------------------------------------------------------------------------- /// Set objective function sense (1 for min (default), -1 for max,) virtual void setObjSense(double s ) { modelPtr_->setOptimizationDirection( s < 0 ? -1 : 1); } /** 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); /*! \brief Add a named column (primal variable) to the problem. */ virtual void addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj, std::string name) ; /** 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) ; /*! \brief Add a named 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, std::string name) ; /** */ virtual void addCols(const int numcols, const CoinPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj); /** */ virtual void addCols(const int numcols, const int * columnStarts, const int * rows, const double * elements, const double* collb, const double* colub, const double* obj); /** */ virtual void deleteCols(const int num, const int * colIndices); /** */ virtual void addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub); /** */ /*! \brief Add a named row (constraint) to the problem. The default implementation adds the row, then changes the name. This can surely be made more efficient within an OsiXXX class. */ virtual void addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub, std::string name) ; virtual void addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng); /** Add a row (constraint) to the problem. */ virtual void addRow(int numberElements, const int * columns, const double * element, const double rowlb, const double rowub) ; /*! \brief Add a named row (constraint) to the problem. */ virtual void addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng, std::string name) ; /** */ 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 addRows(const int numrows, const int * rowStarts, const int * columns, const double * element, const double* rowlb, const double* rowub); /// void modifyCoefficient(int row, int column, double newElement, bool keepZero=false) {modelPtr_->modifyCoefficient(row,column,newElement, keepZero);} /** */ virtual void deleteRows(const int num, const int * rowIndices); /** If solver wants it can save a copy of "base" (continuous) model here */ virtual void saveBaseModel() ; /** Strip off rows to get to this number of rows. If solver wants it can restore a copy of "base" (continuous) model here */ virtual void restoreBaseModel(int numberRows); //----------------------------------------------------------------------- /** 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); /** Apply a collection of cuts. Only cuts which have an effectiveness >= effectivenessLb are applied.
  • ReturnCode.getNumineffective() -- number of cuts which were not applied because they had an effectiveness < effectivenessLb
  • ReturnCode.getNuminconsistent() -- number of invalid cuts
  • ReturnCode.getNuminconsistentWrtIntegerModel() -- number of cuts that are invalid with respect to this integer model
  • ReturnCode.getNuminfeasible() -- number of cuts that would make this integer model infeasible
  • ReturnCode.getNumApplied() -- number of integer cuts which were applied to the integer model
  • cs.size() == getNumineffective() + getNuminconsistent() + getNuminconsistentWrtIntegerModel() + getNuminfeasible() + getNumApplied()
*/ virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs, double effectivenessLb = 0.0); //@} //@} //--------------------------------------------------------------------------- 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 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
*/ 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 NULL 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 as a ClpMatrixBase. */ virtual void loadProblem(const ClpMatrixBase& matrix, 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 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); /// This loads a model from a coinModel object - returns number of errors virtual int loadFromCoinModel ( CoinModel & modelObject, bool keepSolution=false); 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") ; /** Read an mps file from the given filename returns number of errors (see OsiMpsReader class) */ int readMps(const char *filename,bool keepNames,bool allowErrors); /// Read an mps file virtual int readMps (const char *filename, const char*extension, int & numberSets, CoinSet ** & sets); /** 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 ; /// Read file in LP format (with names) virtual int readLp(const char *filename, const double epsilon = 1e-5); /** Write the problem into an Lp 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. This version calls writeLpNative with names */ virtual void writeLp(const char *filename, const char *extension = "lp", double epsilon = 1e-5, int numberAcross = 10, int decimals = 5, double objSense = 0.0, bool useRowNames = true) const; /** Write the problem into the file pointed to by the parameter fp. Other parameters are similar to those of writeLp() with first parameter filename. */ virtual void writeLp(FILE *fp, double epsilon = 1e-5, int numberAcross = 10, int decimals = 5, double objSense = 0.0, bool useRowNames = true) const; /** I (JJF) am getting annoyed because I can't just replace a matrix. The default behavior of this is do nothing so only use where that would not matter e.g. strengthening a matrix for MIP */ virtual void replaceMatrixOptional(const CoinPackedMatrix & matrix); /// And if it does matter (not used at present) virtual void replaceMatrix(const CoinPackedMatrix & matrix) ; //@} /**@name Message handling (extra for Clp messages). Normally I presume you would want the same language. If not then you could use underlying model pointer */ //@{ /** 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); /// Set language void newLanguage(CoinMessages::Language language); void setLanguage(CoinMessages::Language language) {newLanguage(language);} /// Set log level (will also set underlying solver's log level) void setLogLevel(int value); /// Create C++ lines to get to current state void generateCpp( FILE * fp); //@} //--------------------------------------------------------------------------- /**@name Clp specific public interfaces */ //@{ /// Get pointer to Clp model ClpSimplex * getModelPtr() const ; /// Set pointer to Clp model and return old inline ClpSimplex * swapModelPtr(ClpSimplex * newModel) { ClpSimplex * model = modelPtr_; modelPtr_=newModel;return model;} /// Get special options inline unsigned int specialOptions() const { return specialOptions_;} void setSpecialOptions(unsigned int value); /// Last algorithm used , 1 = primal, 2 = dual other unknown inline int lastAlgorithm() const { return lastAlgorithm_;} /// Set last algorithm used , 1 = primal, 2 = dual other unknown inline void setLastAlgorithm(int value) { lastAlgorithm_ = value;} /// Get scaling action option inline int cleanupScaling() const { return cleanupScaling_;} /** Set Scaling option When scaling is on it is possible that the scaled problem is feasible but the unscaled is not. Clp returns a secondary status code to that effect. This option allows for a cleanup. If you use it I would suggest 1. This only affects actions when scaled optimal 0 - no action 1 - clean up using dual if primal infeasibility 2 - clean up using dual if dual infeasibility 3 - clean up using dual if primal or dual infeasibility 11,12,13 - as 1,2,3 but use primal */ inline void setCleanupScaling(int value) { cleanupScaling_=value;} /** Get smallest allowed element in cut. If smaller than this then ignored */ inline double smallestElementInCut() const { return smallestElementInCut_;} /** Set smallest allowed element in cut. If smaller than this then ignored */ inline void setSmallestElementInCut(double value) { smallestElementInCut_=value;} /** Get smallest change in cut. If (upper-lower)*element < this then element is taken out and cut relaxed. (upper-lower) is taken to be at least 1.0 and this is assumed >= smallestElementInCut_ */ inline double smallestChangeInCut() const { return smallestChangeInCut_;} /** Set smallest change in cut. If (upper-lower)*element < this then element is taken out and cut relaxed. (upper-lower) is taken to be at least 1.0 and this is assumed >= smallestElementInCut_ */ inline void setSmallestChangeInCut(double value) { smallestChangeInCut_=value;} /// Pass in initial solve options inline void setSolveOptions(const ClpSolve & options) { solveOptions_ = options;} /** Tighten bounds - lightweight or very lightweight 0 - normal, 1 lightweight but just integers, 2 lightweight and all */ virtual int tightenBounds(int lightweight=0); /// Return number of entries in L part of current factorization virtual CoinBigIndex getSizeL() const; /// Return number of entries in U part of current factorization virtual CoinBigIndex getSizeU() const; /// Get disaster handler const OsiClpDisasterHandler * disasterHandler() const { return disasterHandler_;} /// Pass in disaster handler void passInDisasterHandler(OsiClpDisasterHandler * handler); /// Get fake objective ClpLinearObjective * fakeObjective() const { return fakeObjective_;} /// Set fake objective (and take ownership) void setFakeObjective(ClpLinearObjective * fakeObjective); /// Set fake objective void setFakeObjective(double * fakeObjective); /*! \brief Set up solver for repeated use by Osi interface. The normal usage does things like keeping factorization around so can be used. Will also do things like keep scaling and row copy of matrix if matrix does not change. \p senseOfAdventure: - 0 - safe stuff as above - 1 - will take more risks - if it does not work then bug which will be fixed - 2 - don't bother doing most extreme termination checks e.g. don't bother re-factorizing if less than 20 iterations. - 3 - Actually safer than 1 (mainly just keeps factorization) \p printOut - -1 always skip round common messages instead of doing some work - 0 skip if normal defaults - 1 leaves */ void setupForRepeatedUse(int senseOfAdventure=0, int printOut=0); /// Synchronize model (really if no cuts in tree) virtual void synchronizeModel(); /*! \brief Set special options in underlying clp solver. Safe as const because #modelPtr_ is mutable. */ void setSpecialOptionsMutable(unsigned int value) const; //@} //--------------------------------------------------------------------------- /**@name Constructors and destructors */ //@{ /// Default Constructor OsiClpSolverInterface (); /// Clone virtual OsiSolverInterface * clone(bool copyData = true) const; /// Copy constructor OsiClpSolverInterface (const OsiClpSolverInterface &); /// Borrow constructor - only delete one copy OsiClpSolverInterface (ClpSimplex * rhs, bool reallyOwn=false); /// Releases so won't error void releaseClp(); /// Assignment operator OsiClpSolverInterface & operator=(const OsiClpSolverInterface& rhs); /// Destructor virtual ~OsiClpSolverInterface (); /// Resets as if default constructor virtual void reset(); //@} //--------------------------------------------------------------------------- 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); //@} //--------------------------------------------------------------------------- protected: /**@name Protected methods */ //@{ /// The real work of a copy constructor (used by copy and assignment) void gutsOfDestructor(); /// Deletes all mutable stuff void freeCachedResults() const; /// Deletes all mutable stuff for row ranges etc void freeCachedResults0() const; /// Deletes all mutable stuff for matrix etc void freeCachedResults1() const; /// A method that fills up the rowsense_, rhs_ and rowrange_ arrays void extractSenseRhsRange() const; /// void fillParamMaps(); /** Warm start NOTE artificials are treated as +1 elements so for <= rhs artificial will be at lower bound if constraint is tight This means that Clpsimplex flips artificials as it works in terms of row activities */ CoinWarmStartBasis getBasis(ClpSimplex * model) const; /** Sets up working basis as a copy of input NOTE artificials are treated as +1 elements so for <= rhs artificial will be at lower bound if constraint is tight This means that Clpsimplex flips artificials as it works in terms of row activities */ void setBasis( const CoinWarmStartBasis & basis, ClpSimplex * model); /// Crunch down problem a bit void crunch(); /// Extend scale factors void redoScaleFactors(int numberRows,const CoinBigIndex * starts, const int * indices, const double * elements); public: /** Sets up working basis as a copy of input and puts in as basis */ void setBasis( const CoinWarmStartBasis & basis); /// Just puts current basis_ into ClpSimplex model inline void setBasis( ) { setBasis(basis_,modelPtr_);} /// Warm start difference from basis_ to statusArray CoinWarmStartDiff * getBasisDiff(const unsigned char * statusArray) const ; /// Warm start from statusArray CoinWarmStartBasis * getBasis(const unsigned char * statusArray) const ; /// Delete all scale factor stuff and reset option void deleteScaleFactors(); /// If doing fast hot start then ranges are computed inline const double * upRange() const { return rowActivity_;} inline const double * downRange() const { return columnActivity_;} /// Pass in range array inline void passInRanges(int * array) { whichRange_=array;} /// Pass in sos stuff from AMPl void setSOSData(int numberSOS,const char * type, const int * start,const int * indices, const double * weights=NULL); /// Compute largest amount any at continuous away from bound void computeLargestAway(); /// Get largest amount continuous away from bound inline double largestAway() const { return largestAway_;} /// Set largest amount continuous away from bound inline void setLargestAway(double value) { largestAway_ = value;} /// Sort of lexicographic resolve void lexSolve(); //@} protected: /**@name Protected member data */ //@{ /// Clp model represented by this class instance mutable ClpSimplex * modelPtr_; //@} /**@name Cached information derived from the OSL model */ //@{ /// Pointer to dense vector of row sense indicators mutable char *rowsense_; /// Pointer to dense vector of row right-hand side values mutable double *rhs_; /** Pointer to dense vector of slack upper bounds for range constraints (undefined for non-range rows) */ mutable double *rowrange_; /** A pointer to the warmstart information to be used in the hotstarts. This is NOT efficient and more thought should be given to it... */ mutable CoinWarmStartBasis* ws_; /** also save row and column information for hot starts only used in hotstarts so can be casual */ mutable double * rowActivity_; mutable double * columnActivity_; /// Stuff for fast dual ClpNodeStuff stuff_; /// Number of SOS sets int numberSOS_; /// SOS set info CoinSet * setInfo_; /// Alternate model (hot starts) - but also could be permanent and used for crunch ClpSimplex * smallModel_; /// factorization for hot starts ClpFactorization * factorization_; /** Smallest allowed element in cut. If smaller than this then ignored */ double smallestElementInCut_; /** Smallest change in cut. If (upper-lower)*element < this then element is taken out and cut relaxed. */ double smallestChangeInCut_; /// Largest amount continuous away from bound double largestAway_; /// Arrays for hot starts char * spareArrays_; /** Warmstart information to be used in resolves. */ CoinWarmStartBasis basis_; /** The original iteration limit before hotstarts started. */ int itlimOrig_; /*! \brief Last algorithm used Coded as - 0 invalid - 1 primal - 2 dual - -911 disaster in the algorithm that was attempted - 999 current solution no longer optimal due to change in problem or basis */ mutable int lastAlgorithm_; /// To say if destructor should delete underlying model bool notOwned_; /// Pointer to row-wise copy of problem matrix coefficients. mutable CoinPackedMatrix *matrixByRow_; /// Pointer to row-wise copy of continuous problem matrix coefficients. CoinPackedMatrix *matrixByRowAtContinuous_; /// Pointer to integer information char * integerInformation_; /** Pointer to variables for which we want range information The number is in [0] memory is not owned by OsiClp */ int * whichRange_; //std::map intParamMap_; //std::map dblParamMap_; //std::map strParamMap_; /*! \brief Faking min to get proper dual solution signs in simplex API */ mutable bool fakeMinInSimplex_ ; /*! \brief Linear objective Normally a pointer to the linear coefficient array in the clp objective. An independent copy when #fakeMinInSimplex_ is true, because we need something permanent to point to when #getObjCoefficients is called. */ mutable double *linearObjective_; /// To save data in OsiSimplex stuff mutable ClpDataSave saveData_; /// Options for initialSolve ClpSolve solveOptions_; /** Scaling option When scaling is on it is possible that the scaled problem is feasible but the unscaled is not. Clp returns a secondary status code to that effect. This option allows for a cleanup. If you use it I would suggest 1. This only affects actions when scaled optimal 0 - no action 1 - clean up using dual if primal infeasibility 2 - clean up using dual if dual infeasibility 3 - clean up using dual if primal or dual infeasibility 11,12,13 - as 1,2,3 but use primal */ int cleanupScaling_; /** Special options 0x80000000 off 0 simple stuff for branch and bound 1 try and keep work regions as much as possible 2 do not use any perturbation 4 allow exit before re-factorization 8 try and re-use factorization if no cuts 16 use standard strong branching rather than clp's 32 Just go to first factorization in fast dual 64 try and tighten bounds in crunch 128 Model will only change in column bounds 256 Clean up model before hot start 512 Give user direct access to Clp regions in getBInvARow etc (i.e., do not unscale, and do not return result in getBInv parameters; you have to know where to look for the answer) 1024 Don't "borrow" model in initialSolve 2048 Don't crunch 4096 quick check for optimality Bits above 8192 give where called from in Cbc At present 0 is normal, 1 doing fast hotstarts, 2 is can do quick check 65536 Keep simple i.e. no crunch etc 131072 Try and keep scaling factors around 262144 Don't try and tighten bounds (funny global cuts) 524288 Fake objective and 0-1 1048576 Don't recompute ray after crunch 2097152 */ mutable unsigned int specialOptions_; /// Copy of model when option 131072 set ClpSimplex * baseModel_; /// Number of rows when last "scaled" int lastNumberRows_; /// Continuous model ClpSimplex * continuousModel_; /// Possible disaster handler OsiClpDisasterHandler * disasterHandler_ ; /// Fake objective ClpLinearObjective * fakeObjective_; /// Row scale factors (has inverse at end) CoinDoubleArrayWithLength rowScale_; /// Column scale factors (has inverse at end) CoinDoubleArrayWithLength columnScale_; //@} }; class OsiClpDisasterHandler : public ClpDisasterHandler { public: /**@name Virtual methods that the derived classe should provide. */ //@{ /// Into simplex virtual void intoSimplex(); /// Checks if disaster virtual bool check() const ; /// saves information for next attempt virtual void saveInfo(); /// Type of disaster 0 can fix, 1 abort virtual int typeOfDisaster(); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ OsiClpDisasterHandler(OsiClpSolverInterface * model = NULL); /** Destructor */ virtual ~OsiClpDisasterHandler(); // Copy OsiClpDisasterHandler(const OsiClpDisasterHandler&); // Assignment OsiClpDisasterHandler& operator=(const OsiClpDisasterHandler&); /// Clone virtual ClpDisasterHandler * clone() const; //@} /**@name Sets/gets */ //@{ /** set model. */ void setOsiModel(OsiClpSolverInterface * model); /// Get model inline OsiClpSolverInterface * osiModel() const { return osiModel_;} /// Set where from inline void setWhereFrom(int value) { whereFrom_=value;} /// Get where from inline int whereFrom() const { return whereFrom_;} /// Set phase inline void setPhase(int value) { phase_=value;} /// Get phase inline int phase() const { return phase_;} /// are we in trouble inline bool inTrouble() const { return inTrouble_;} //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer to model OsiClpSolverInterface * osiModel_; /** Where from 0 dual (resolve) 1 crunch 2 primal (resolve) 4 dual (initialSolve) 6 primal (initialSolve) */ int whereFrom_; /** phase 0 initial 1 trying continuing with back in and maybe different perturb 2 trying continuing with back in and different scaling 3 trying dual from all slack 4 trying primal from previous stored basis */ int phase_; /// Are we in trouble bool inTrouble_; //@} }; // So unit test can find out if NDEBUG set bool OsiClpHasNDEBUG(); //############################################################################# /** A function that tests the methods in the OsiClpSolverInterface class. */ void OsiClpSolverInterfaceUnitTest(const std::string & mpsDir, const std::string & netlibDir); #endif Clp-1.15.10/src/OsiClp/osi-clp-uninstalled.pc.in0000644000076600007660000000045511507672206017664 0ustar coincoinprefix=@prefix@ libdir=@ABSBUILDDIR@/src/OsiClp Name: OsiClp Description: COIN-OR Open Solver Interface for CLP URL: https://projects.coin-or.org/Osi Version: @PACKAGE_VERSION@ Libs: ${libdir}/libOsiClp.la @OSICLPLIB_PCLIBS@ Cflags: -I@abs_source_dir@/src/OsiClp Requires: clp @OSICLPLIB_PCREQUIRES@ Clp-1.15.10/src/OsiClp/osi-clp.pc.in0000644000076600007660000000050411510106324015322 0ustar coincoinprefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/coin Name: OsiClp Description: COIN-OR Open Solver Interface for CLP URL: https://projects.coin-or.org/Osi Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lOsiClp @OSICLPLIB_PCLIBS@ Cflags: -I${includedir} Requires: clp @OSICLPLIB_PCREQUIRES@ Clp-1.15.10/src/OsiClp/OsiClpSolverInterface.cpp0000644000076600007660000113321412376326417017764 0ustar coincoin// $Id$ // 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 #ifdef CBC_STATISTICS extern int osi_crunch; extern int osi_primal; extern int osi_dual; extern int osi_hot; #endif #include "CoinTime.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "CoinModel.hpp" #include "CoinMpsIO.hpp" #include "CoinSort.hpp" #include "ClpDualRowSteepest.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpPackedMatrix.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpFactorization.hpp" #include "ClpObjective.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #include "ClpSimplexPrimal.hpp" #include "ClpSimplexDual.hpp" #include "ClpNonLinearCost.hpp" #include "OsiClpSolverInterface.hpp" #include "OsiBranchingObject.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "ClpPresolve.hpp" #include "CoinLpIO.hpp" static double totalTime=0.0; //#define SAVE_MODEL 1 #ifdef SAVE_MODEL static int resolveTry=0; static int loResolveTry=0; static int hiResolveTry=9999999; #endif //############################################################################# // Solve methods //############################################################################# void OsiClpSolverInterface::initialSolve() { #define KEEP_SMALL #ifdef KEEP_SMALL if (smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; delete smallModel_; smallModel_=NULL; } #endif if ((specialOptions_&2097152)!=0||(specialOptions_&4194304)!=0) { bool takeHint; OsiHintStrength strength; int algorithm = 0; getHintParam(OsiDoDualInInitial,takeHint,strength); if (strength!=OsiHintIgnore) algorithm = takeHint ? -1 : 1; if (algorithm>0||(specialOptions_&4194304)!=0) { // Gub resolveGub((9*modelPtr_->numberRows())/10); return; } } bool deleteSolver; ClpSimplex * solver; double time1 = CoinCpuTime(); int userFactorizationFrequency = modelPtr_->factorization()->maximumPivots(); int totalIterations=0; bool abortSearch=false; ClpObjective * savedObjective=NULL; double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit]; if (fakeObjective_) { // Clear (no objective, 0-1 and in B&B) modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128)); // See if all with costs fixed int numberColumns = modelPtr_->numberColumns_; const double * obj = modelPtr_->objective(); const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); int i; for (i=0;iobjective_; modelPtr_->objective_=fakeObjective_; modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX; } else { // Set (no objective, 0-1 and in B&B) modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128); } } } // Check (in branch and bound) if ((specialOptions_&1024)==0) { solver = new ClpSimplex(true); deleteSolver=true; solver->borrowModel(*modelPtr_); // See if user set factorization frequency // borrowModel does not move solver->factorization()->maximumPivots(userFactorizationFrequency); } else { solver = modelPtr_; deleteSolver=false; } // Treat as if user simplex not enabled int saveSolveType=solver->solveType(); bool doingPrimal = solver->algorithm()>0; if (saveSolveType==2) { disableSimplexInterface(); solver->setSolveType(1); } int saveOptions = solver->specialOptions(); solver->setSpecialOptions(saveOptions|64|32768); // go as far as possible // get original log levels int saveMessageLevel=modelPtr_->logLevel(); int messageLevel=messageHandler()->logLevel(); int saveMessageLevel2 = messageLevel; // Set message handler if (!defaultHandler_) solver->passInMessageHandler(handler_); // But keep log level solver->messageHandler()->setLogLevel(saveMessageLevel); // set reasonable defaults bool takeHint; OsiHintStrength strength; // Switch off printing if asked to bool gotHint = (getHintParam(OsiDoReducePrint,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { if (messageLevel>0) messageLevel--; } if (messageLevelmessageHandler()->setLogLevel(messageLevel); // Allow for specialOptions_==1+8 forcing saving factorization int startFinishOptions=0; if ((specialOptions_&9)==(1+8)) { startFinishOptions =1+2+4; // allow re-use of factorization } bool defaultHints=true; { int hint; for (hint=OsiDoPresolveInInitial;hint (hint),yesNo,strength); if (yesNo) { defaultHints=false; break; } if (strength != OsiHintIgnore) { defaultHints=false; break; } } } } ClpPresolve * pinfo = NULL; /* If basis then do primal (as user could do dual with resolve) If not then see if dual feasible (and allow for gubs etc?) */ bool doPrimal = (basis_.numberBasicStructurals()>0); setBasis(basis_,solver); bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0; if ((!defaultHints||doPrimal)&&!solveOptions_.getSpecialOption(6)) { // scaling // save initial state const double * rowScale1 = solver->rowScale(); if (modelPtr_->solveType()==1) { gotHint = (getHintParam(OsiDoScale,takeHint,strength)); assert (gotHint); if (strength==OsiHintIgnore||takeHint) { if (!solver->scalingFlag()) solver->scaling(3); } else { solver->scaling(0); } } else { solver->scaling(0); } //solver->setDualBound(1.0e6); //solver->setDualTolerance(1.0e-7); //ClpDualRowSteepest steep; //solver->setDualRowPivotAlgorithm(steep); //solver->setPrimalTolerance(1.0e-8); //ClpPrimalColumnSteepest steepP; //solver->setPrimalColumnPivotAlgorithm(steepP); // sort out hints; // algorithm 0 whatever, -1 force dual, +1 force primal int algorithm = 0; gotHint = (getHintParam(OsiDoDualInInitial,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore) algorithm = takeHint ? -1 : 1; // crash 0 do lightweight if all slack, 1 do, -1 don't int doCrash=0; gotHint = (getHintParam(OsiDoCrash,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore) doCrash = takeHint ? 1 : -1; // doPrimal set true if any structurals in basis so switch off crash if (doPrimal) doCrash = -1; // presolve gotHint = (getHintParam(OsiDoPresolveInInitial,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { pinfo = new ClpPresolve(); ClpSimplex * model2 = pinfo->presolvedModel(*solver,1.0e-8); if (!model2) { // problem found to be infeasible - whats best? model2 = solver; delete pinfo; pinfo = NULL; } else { model2->setSpecialOptions(solver->specialOptions()); } // change from 200 (unless changed) if (modelPtr_->factorization()->maximumPivots()==200) model2->factorization()->maximumPivots(100+model2->numberRows()/50); else model2->factorization()->maximumPivots(userFactorizationFrequency); int savePerturbation = model2->perturbation(); if (savePerturbation==100) model2->setPerturbation(50); if (!doPrimal) { // faster if bounds tightened //int numberInfeasibilities = model2->tightenPrimalBounds(); model2->tightenPrimalBounds(); // look further bool crashResult=false; if (doCrash>0) crashResult = (solver->crash(1000.0,1)>0); else if (doCrash==0&&algorithm>0) crashResult = (solver->crash(1000.0,1)>0); doPrimal=crashResult; } if (algorithm<0) doPrimal=false; else if (algorithm>0) doPrimal=true; if (!doPrimal) { //if (numberInfeasibilities) //std::cout<<"** Analysis indicates model infeasible" // <setDualBound(1.0e11); disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(model2); disasterHandler_->setWhereFrom(4); model2->setDisasterHandler(disasterHandler_); } model2->dual(0); totalIterations += model2->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in disasterHandler_->setPhase(1); model2->dual(); totalIterations += model2->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,model2); model2->primal(); totalIterations += model2->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } model2->setProblemStatus(1); } } // reset model2->setDisasterHandler(NULL); } // check if clp thought it was in a loop if (model2->status()==3&&!model2->hitMaximumIterations()) { // switch algorithm disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(model2); disasterHandler_->setWhereFrom(6); model2->setDisasterHandler(disasterHandler_); } model2->primal(); totalIterations += model2->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in (but with dual) disasterHandler_->setPhase(1); model2->dual(); totalIterations += model2->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,model2); model2->dual(); totalIterations += model2->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } model2->setProblemStatus(1); } } // reset model2->setDisasterHandler(NULL); } } } else { // up infeasibility cost for safety //model2->setInfeasibilityCost(1.0e10); disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(model2); disasterHandler_->setWhereFrom(6); model2->setDisasterHandler(disasterHandler_); } model2->primal(1); totalIterations += model2->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in (but with dual) disasterHandler_->setPhase(1); model2->dual(); totalIterations += model2->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,model2); model2->dual(); totalIterations += model2->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } model2->setProblemStatus(1); } } // reset model2->setDisasterHandler(NULL); } // check if clp thought it was in a loop if (model2->status()==3&&!model2->hitMaximumIterations()) { // switch algorithm disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(model2); disasterHandler_->setWhereFrom(4); model2->setDisasterHandler(disasterHandler_); } model2->dual(0); totalIterations += model2->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in disasterHandler_->setPhase(1); model2->dual(); totalIterations += model2->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,model2); model2->primal(); totalIterations += model2->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } model2->setProblemStatus(1); } } // reset model2->setDisasterHandler(NULL); } } } model2->setPerturbation(savePerturbation); if (model2!=solver) { int presolvedStatus = model2->status(); pinfo->postsolve(true); delete pinfo; pinfo = NULL; delete model2; int oldStatus=solver->status(); solver->setProblemStatus(presolvedStatus); if (solver->logLevel()==63) // for gcc 4.6 bug printf("pstat %d stat %d\n",presolvedStatus,oldStatus); //printf("Resolving from postsolved model\n"); // later try without (1) and check duals before solve if (presolvedStatus!=3 &&(presolvedStatus||oldStatus==-1)) { if (!inCbcOrOther||presolvedStatus!=1) { disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(solver); // as "borrowed" disasterHandler_->setWhereFrom(6); solver->setDisasterHandler(disasterHandler_); } solver->primal(1); totalIterations += solver->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in (but with dual) disasterHandler_->setPhase(1); solver->dual(); totalIterations += solver->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,solver); solver->dual(); totalIterations += solver->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } solver->setProblemStatus(1); } } // reset solver->setDisasterHandler(NULL); } } } } lastAlgorithm_=1; // primal //if (solver->numberIterations()) //printf("****** iterated %d\n",solver->numberIterations()); } else { // do we want crash if (doCrash>0) solver->crash(1000.0,2); else if (doCrash==0) solver->crash(1000.0,0); if (algorithm<0) doPrimal=false; else if (algorithm>0) doPrimal=true; disasterHandler_->setOsiModel(this); disasterHandler_->setSimplex(solver); // as "borrowed" bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0; if (!doPrimal) disasterHandler_->setWhereFrom(4); else disasterHandler_->setWhereFrom(6); if (inCbcOrOther) solver->setDisasterHandler(disasterHandler_); if (!doPrimal) { //printf("doing dual\n"); solver->dual(0); totalIterations += solver->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in disasterHandler_->setPhase(1); solver->dual(); totalIterations += solver->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("dual trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,solver); solver->primal(); totalIterations += solver->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } solver->setProblemStatus(1); } } // reset solver->setDisasterHandler(NULL); } lastAlgorithm_=2; // dual // check if clp thought it was in a loop if (solver->status()==3&&!solver->hitMaximumIterations()) { // switch algorithm solver->primal(0); totalIterations += solver->numberIterations(); lastAlgorithm_=1; // primal } } else { //printf("doing primal\n"); solver->primal(1); totalIterations += solver->numberIterations(); if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble a\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in (but with dual) disasterHandler_->setPhase(1); solver->dual(); totalIterations += solver->numberIterations(); if (disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("primal trouble b\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,solver); solver->dual(); totalIterations += solver->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } solver->setProblemStatus(1); } } // reset solver->setDisasterHandler(NULL); } lastAlgorithm_=1; // primal // check if clp thought it was in a loop if (solver->status()==3&&!solver->hitMaximumIterations()) { // switch algorithm solver->dual(0); totalIterations += solver->numberIterations(); lastAlgorithm_=2; // dual } } } // If scaled feasible but unscaled infeasible take action if (!solver->status()&&cleanupScaling_) { solver->cleanup(cleanupScaling_); } basis_ = getBasis(solver); //basis_.print(); const double * rowScale2 = solver->rowScale(); solver->setSpecialOptions(saveOptions); if (!rowScale1&&rowScale2) { // need to release memory if (!solver->savedRowScale_) { solver->setRowScale(NULL); solver->setColumnScale(NULL); } else { solver->rowScale_=NULL; solver->columnScale_=NULL; } } } else { // User doing nothing and all slack basis ClpSolve options=solveOptions_; bool yesNo; OsiHintStrength strength; getHintParam(OsiDoInBranchAndCut,yesNo,strength); if (yesNo) { solver->setSpecialOptions(solver->specialOptions()|1024); } solver->initialSolve(options); totalIterations += solver->numberIterations(); lastAlgorithm_ = 2; // say dual // If scaled feasible but unscaled infeasible take action if (!solver->status()&&cleanupScaling_) { solver->cleanup(cleanupScaling_); } basis_ = getBasis(solver); //basis_.print(); } solver->messageHandler()->setLogLevel(saveMessageLevel); disaster: if (deleteSolver) { solver->returnModel(*modelPtr_); delete solver; } if (startFinishOptions) { int save = modelPtr_->logLevel(); if (save<2) modelPtr_->setLogLevel(0); modelPtr_->dual(0,startFinishOptions); totalIterations += modelPtr_->numberIterations(); modelPtr_->setLogLevel(save); } if (saveSolveType==2) { enableSimplexInterface(doingPrimal); } if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } modelPtr_->setNumberIterations(totalIterations); handler_->setLogLevel(saveMessageLevel2); if (modelPtr_->problemStatus_==3&&lastAlgorithm_==2) modelPtr_->computeObjectiveValue(); // mark so we can pick up objective value quickly modelPtr_->upperIn_=0.0; time1 = CoinCpuTime()-time1; totalTime += time1; assert (!modelPtr_->disasterHandler()); if (lastAlgorithm_<1||lastAlgorithm_>2) lastAlgorithm_=1; if (abortSearch) { lastAlgorithm_=-911; modelPtr_->setProblemStatus(4); } modelPtr_->whatsChanged_ |= 0x30000; #if 0 // delete scaled matrix and rowcopy for safety delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; delete modelPtr_->rowCopy_; modelPtr_->rowCopy_=NULL; #endif //std::cout<-1.0e12); } n = getNumRows(); lower = getRowLower() ; upper = getRowUpper() ; for (i=0;i-1.0e12); } } #endif if ((stuff_.solverOptions_&65536)!=0) { modelPtr_->fastDual2(&stuff_); return; } if ((specialOptions_&2097152)!=0||(specialOptions_&4194304)!=0) { bool takeHint; OsiHintStrength strength; int algorithm = 0; getHintParam(OsiDoDualInResolve,takeHint,strength); if (strength!=OsiHintIgnore) algorithm = takeHint ? -1 : 1; if (algorithm>0||(specialOptions_&4194304)!=0) { // Gub resolveGub((9*modelPtr_->numberRows())/10); return; } } //void pclp(char *); //pclp("res"); bool takeHint; OsiHintStrength strength; bool gotHint = (getHintParam(OsiDoInBranchAndCut,takeHint,strength)); assert (gotHint); // mark so we can pick up objective value quickly modelPtr_->upperIn_=0.0; if ((specialOptions_&4096)!=0) { // Quick check to see if optimal modelPtr_->checkSolutionInternal(); if (modelPtr_->problemStatus()==0) { modelPtr_->setNumberIterations(0); return; } } int totalIterations=0; bool abortSearch=false; ClpObjective * savedObjective=NULL; double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit]; if (fakeObjective_) { modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128)); // See if all with costs fixed int numberColumns = modelPtr_->numberColumns_; const double * obj = modelPtr_->objective(); const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); int i; for (i=0;iobjective_; modelPtr_->objective_=fakeObjective_; modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX; } else { modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128); } } } // If using Clp initialSolve and primal - just do here gotHint = (getHintParam(OsiDoDualInResolve,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&!takeHint&&solveOptions_.getSpecialOption(6)) { ClpSolve options=solveOptions_; // presolve getHintParam(OsiDoPresolveInResolve,takeHint,strength); if (strength!=OsiHintIgnore&&!takeHint) options.setPresolveType(ClpSolve::presolveOff); int saveOptions = modelPtr_->specialOptions(); getHintParam(OsiDoInBranchAndCut,takeHint,strength); if (takeHint) { modelPtr_->setSpecialOptions(modelPtr_->specialOptions()|1024); } setBasis(basis_,modelPtr_); modelPtr_->initialSolve(options); lastAlgorithm_ = 1; // say primal // If scaled feasible but unscaled infeasible take action if (!modelPtr_->status()&&cleanupScaling_) { modelPtr_->cleanup(cleanupScaling_); } modelPtr_->setSpecialOptions(saveOptions); // restore basis_ = getBasis(modelPtr_); } int saveSolveType=modelPtr_->solveType(); bool doingPrimal = modelPtr_->algorithm()>0; if (saveSolveType==2) { disableSimplexInterface(); } int saveOptions = modelPtr_->specialOptions(); int startFinishOptions=0; if (specialOptions_!=0x80000000) { if((specialOptions_&1)==0) { startFinishOptions=0; modelPtr_->setSpecialOptions(saveOptions|(64|1024|32768)); } else { startFinishOptions=1+4; if ((specialOptions_&8)!=0) startFinishOptions +=2; // allow re-use of factorization if((specialOptions_&4)==0||!takeHint) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096|32768)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096|32768)); } } else { modelPtr_->setSpecialOptions(saveOptions|64|32768); } //printf("options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); //modelPtr_->setSolveType(1); // Set message handler to have same levels etc int saveMessageLevel=modelPtr_->logLevel(); int messageLevel=messageHandler()->logLevel(); bool oldDefault; CoinMessageHandler * saveHandler = NULL; if (!defaultHandler_) saveHandler = modelPtr_->pushMessageHandler(handler_,oldDefault); //printf("basis before dual\n"); //basis_.print(); setBasis(basis_,modelPtr_); #ifdef SAVE_MODEL resolveTry++; #if SAVE_MODEL > 1 if (resolveTry>=loResolveTry&& resolveTry<=hiResolveTry) { char fileName[20]; sprintf(fileName,"save%d.mod",resolveTry); modelPtr_->saveModel(fileName); } #endif #endif // set reasonable defaults // Switch off printing if asked to gotHint = (getHintParam(OsiDoReducePrint,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { if (messageLevel>0) messageLevel--; } if (messageLevelmessageHandler()->logLevel()) modelPtr_->messageHandler()->setLogLevel(messageLevel); // See if user set factorization frequency int userFactorizationFrequency = modelPtr_->factorization()->maximumPivots(); // scaling if (modelPtr_->solveType()==1) { gotHint = (getHintParam(OsiDoScale,takeHint,strength)); assert (gotHint); if (strength==OsiHintIgnore||takeHint) { if (!modelPtr_->scalingFlag()) modelPtr_->scaling(3); } else { modelPtr_->scaling(0); } } else { modelPtr_->scaling(0); } // sort out hints; // algorithm -1 force dual, +1 force primal int algorithm = -1; gotHint = (getHintParam(OsiDoDualInResolve,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore) algorithm = takeHint ? -1 : 1; //modelPtr_->saveModel("save.bad"); // presolve gotHint = (getHintParam(OsiDoPresolveInResolve,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { #ifdef KEEP_SMALL if (smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; delete smallModel_; smallModel_=NULL; } #endif ClpPresolve pinfo; if ((specialOptions_&128)!=0) { specialOptions_ &= ~128; } if ((modelPtr_->specialOptions()&1024)!=0) { pinfo.setDoDual(false); pinfo.setDoTripleton(false); pinfo.setDoDupcol(false); pinfo.setDoDuprow(false); pinfo.setDoSingletonColumn(false); } ClpSimplex * model2 = pinfo.presolvedModel(*modelPtr_,1.0e-8); if (!model2) { // problem found to be infeasible - whats best? model2 = modelPtr_; } // return number of rows int * stats = reinterpret_cast (getApplicationData()); if (stats) { stats[0]=model2->numberRows(); stats[1]=model2->numberColumns(); } //printf("rows %d -> %d, columns %d -> %d\n", // modelPtr_->numberRows(),model2->numberRows(), // modelPtr_->numberColumns(),model2->numberColumns()); // change from 200 if (modelPtr_->factorization()->maximumPivots()==200) model2->factorization()->maximumPivots(100+model2->numberRows()/50); else model2->factorization()->maximumPivots(userFactorizationFrequency); if (algorithm<0) { model2->dual(); totalIterations += model2->numberIterations(); // check if clp thought it was in a loop if (model2->status()==3&&!model2->hitMaximumIterations()) { // switch algorithm model2->primal(); totalIterations += model2->numberIterations(); } } else { model2->primal(1); totalIterations += model2->numberIterations(); // check if clp thought it was in a loop if (model2->status()==3&&!model2->hitMaximumIterations()) { // switch algorithm model2->dual(); totalIterations += model2->numberIterations(); } } if (model2!=modelPtr_) { int finalStatus=model2->status(); pinfo.postsolve(true); delete model2; // later try without (1) and check duals before solve if (finalStatus!=3&&(finalStatus||modelPtr_->status()==-1)) { modelPtr_->primal(1); totalIterations += modelPtr_->numberIterations(); lastAlgorithm_=1; // primal //if (modelPtr_->numberIterations()) //printf("****** iterated %d\n",modelPtr_->numberIterations()); } } } else { //modelPtr_->setLogLevel(63); //modelPtr_->setDualTolerance(1.0e-7); if (false&&modelPtr_->scalingFlag_>0&&!modelPtr_->rowScale_&& !modelPtr_->rowCopy_&&matrixByRow_) { assert (matrixByRow_->getNumElements()==modelPtr_->clpMatrix()->getNumElements()); modelPtr_->setNewRowCopy(new ClpPackedMatrix(*matrixByRow_)); } if (algorithm<0) { //writeMps("try1"); int savePerturbation = modelPtr_->perturbation(); if ((specialOptions_&2)!=0) modelPtr_->setPerturbation(100); //modelPtr_->messageHandler()->setLogLevel(1); //writeMpsNative("bad",NULL,NULL,2,1,1.0); disasterHandler_->setOsiModel(this); bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0; #if 0 // See how many integers fixed bool skipCrunch=true; const char * integerInformation = modelPtr_->integerType_; if (integerInformation) { int numberColumns = modelPtr_->numberColumns_; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); int target=CoinMax(1,numberColumns/10000); for (int i=0;isetWhereFrom(0); // dual if (inCbcOrOther) modelPtr_->setDisasterHandler(disasterHandler_); bool specialScale; if ((specialOptions_&131072)!=0&&!modelPtr_->rowScale_) { modelPtr_->rowScale_ = rowScale_.array(); modelPtr_->columnScale_ = columnScale_.array(); specialScale=true; } else { specialScale=false; } #ifdef KEEP_SMALL if (smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; delete smallModel_; smallModel_=NULL; } #endif #ifdef CBC_STATISTICS osi_dual++; #endif modelPtr_->dual(0,startFinishOptions); totalIterations += modelPtr_->numberIterations(); if (specialScale) { modelPtr_->rowScale_ = NULL; modelPtr_->columnScale_ = NULL; } } else { #ifdef CBC_STATISTICS osi_crunch++; #endif crunch(); totalIterations += modelPtr_->numberIterations(); if (modelPtr_->problemStatus()==4) goto disaster; // should have already been fixed if problems inCbcOrOther=false; } if (inCbcOrOther) { if(disasterHandler_->inTrouble()) { if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try just going back in disasterHandler_->setPhase(1); modelPtr_->dual(); totalIterations += modelPtr_->numberIterations(); if (disasterHandler_->inTrouble()) { if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal with original basis disasterHandler_->setPhase(2); setBasis(basis_,modelPtr_); modelPtr_->primal(); totalIterations += modelPtr_->numberIterations(); } if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } modelPtr_->setProblemStatus(1); } } // reset modelPtr_->setDisasterHandler(NULL); } if (modelPtr_->problemStatus()==4) { // bad bounds? modelPtr_->setProblemStatus(1); } if (!modelPtr_->problemStatus()&&0) { int numberColumns = modelPtr_->numberColumns(); const double * columnLower = modelPtr_->columnLower(); const double * columnUpper = modelPtr_->columnUpper(); int nBad=0; for (int i=0;igetColumnStatus(i)==ClpSimplex::basic) { nBad++; modelPtr_->setColumnStatus(i,ClpSimplex::isFixed); } } if (nBad) { modelPtr_->primal(1); totalIterations += modelPtr_->numberIterations(); printf("%d fixed basic - %d iterations\n",nBad,modelPtr_->numberIterations()); } } assert (modelPtr_->objectiveValue()<1.0e100); modelPtr_->setPerturbation(savePerturbation); lastAlgorithm_=2; // dual // check if clp thought it was in a loop if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) { modelPtr_->setSpecialOptions(saveOptions); // switch algorithm //modelPtr_->messageHandler()->setLogLevel(63); // Allow for catastrophe int saveMax = modelPtr_->maximumIterations(); int numberIterations = modelPtr_->numberIterations(); int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); if (modelPtr_->maximumIterations()>100000+numberIterations) modelPtr_->setMaximumIterations(numberIterations + 1000 + 2*numberRows+numberColumns); modelPtr_->primal(0,startFinishOptions); totalIterations += modelPtr_->numberIterations(); modelPtr_->setMaximumIterations(saveMax); lastAlgorithm_=1; // primal if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) { #ifdef COIN_DEVELOP printf("in trouble - try all slack\n"); #endif CoinWarmStartBasis allSlack; setBasis(allSlack,modelPtr_); modelPtr_->dual(); totalIterations += modelPtr_->numberIterations(); if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) { if (modelPtr_->numberPrimalInfeasibilities()) { #ifdef COIN_DEVELOP printf("Real real trouble - treat as infeasible\n"); #endif modelPtr_->setProblemStatus(1); } else { #ifdef COIN_DEVELOP printf("Real real trouble - treat as optimal\n"); #endif modelPtr_->setProblemStatus(0); } } } } assert (modelPtr_->objectiveValue()<1.0e100); } else { #ifdef KEEP_SMALL if (smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; delete smallModel_; smallModel_=NULL; } #endif //printf("doing primal\n"); #ifdef CBC_STATISTICS osi_primal++; #endif modelPtr_->primal(1,startFinishOptions); totalIterations += modelPtr_->numberIterations(); lastAlgorithm_=1; // primal // check if clp thought it was in a loop if (modelPtr_->status()==3&&!modelPtr_->hitMaximumIterations()) { // switch algorithm modelPtr_->dual(); totalIterations += modelPtr_->numberIterations(); lastAlgorithm_=2; // dual } } } // If scaled feasible but unscaled infeasible take action //if (!modelPtr_->status()&&cleanupScaling_) { if (cleanupScaling_) { modelPtr_->cleanup(cleanupScaling_); } basis_ = getBasis(modelPtr_); disaster: //printf("basis after dual\n"); //basis_.print(); if (!defaultHandler_) modelPtr_->popMessageHandler(saveHandler,oldDefault); modelPtr_->messageHandler()->setLogLevel(saveMessageLevel); if (saveSolveType==2) { int saveStatus = modelPtr_->problemStatus_; enableSimplexInterface(doingPrimal); modelPtr_->problemStatus_=saveStatus; } #ifdef COIN_DEVELOP_x extern bool doingDoneBranch; if (doingDoneBranch) { if (modelPtr_->numberIterations()) printf("***** done %d iterations after general\n",modelPtr_->numberIterations()); doingDoneBranch=false; } #endif modelPtr_->setNumberIterations(totalIterations); //modelPtr_->setSolveType(saveSolveType); if (abortSearch) { lastAlgorithm_=-911; modelPtr_->setProblemStatus(4); } if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } modelPtr_->setSpecialOptions(saveOptions); // restore if (modelPtr_->problemStatus_==3&&lastAlgorithm_==2) modelPtr_->computeObjectiveValue(); if (lastAlgorithm_<1||lastAlgorithm_>2) lastAlgorithm_=1; #ifdef SAVE_MODEL if (resolveTry>=loResolveTry&& resolveTry<=hiResolveTry) { printf("resolve %d took %d iterations - algorithm %d\n",resolveTry,modelPtr_->numberIterations(),lastAlgorithm_); } #endif // Make sure whatsChanged not out of sync if (!modelPtr_->columnUpperWork_) modelPtr_->whatsChanged_ &= ~0xffff; modelPtr_->whatsChanged_ |= 0x30000; } #include "ClpSimplexOther.hpp" // Resolve an LP relaxation after problem modification (try GUB) void OsiClpSolverInterface::resolveGub(int needed) { bool takeHint; OsiHintStrength strength; // Switch off printing if asked to getHintParam(OsiDoReducePrint,takeHint,strength); int saveMessageLevel=modelPtr_->logLevel(); if (strength!=OsiHintIgnore&&takeHint) { int messageLevel=messageHandler()->logLevel(); if (messageLevel>0) modelPtr_->messageHandler()->setLogLevel(messageLevel-1); else modelPtr_->messageHandler()->setLogLevel(0); } //modelPtr_->messageHandler()->setLogLevel(1); setBasis(basis_,modelPtr_); // find gub int numberRows = modelPtr_->numberRows(); int * which = new int[numberRows]; int numberColumns = modelPtr_->numberColumns(); int * whichC = new int[numberColumns+numberRows]; ClpSimplex * model2 = static_cast (modelPtr_)->gubVersion(which,whichC, needed,100); if (model2) { // move in solution static_cast (model2)->setGubBasis(*modelPtr_, which,whichC); model2->setLogLevel(CoinMin(1,model2->logLevel())); ClpPrimalColumnSteepest steepest(5); model2->setPrimalColumnPivotAlgorithm(steepest); //double time1 = CoinCpuTime(); model2->primal(); //printf("Primal took %g seconds\n",CoinCpuTime()-time1); static_cast (model2)->getGubBasis(*modelPtr_, which,whichC); int totalIterations = model2->numberIterations(); delete model2; //modelPtr_->setLogLevel(63); modelPtr_->primal(1); modelPtr_->setNumberIterations(totalIterations+modelPtr_->numberIterations()); } else { modelPtr_->dual(); } delete [] which; delete [] whichC; basis_ = getBasis(modelPtr_); modelPtr_->messageHandler()->setLogLevel(saveMessageLevel); } // Sort of lexicographic resolve void OsiClpSolverInterface::lexSolve() { #if 1 abort(); #else ((ClpSimplexPrimal *) modelPtr_)->lexSolve(); printf("itA %d\n",modelPtr_->numberIterations()); modelPtr_->primal(); printf("itB %d\n",modelPtr_->numberIterations()); basis_ = getBasis(modelPtr_); #endif } /* Sets up solver for repeated use by Osi interface. The normal usage does things like keeping factorization around so can be used. Will also do things like keep scaling and row copy of matrix if matrix does not change. adventure: 0 - safe stuff as above 1 - will take more risks - if it does not work then bug which will be fixed 2 - don't bother doing most extreme termination checks e.g. don't bother re-factorizing if less than 20 iterations. 3 - Actually safer than 1 (mainly just keeps factorization) printOut - -1 always skip round common messages instead of doing some work 0 skip if normal defaults 1 leaves */ void OsiClpSolverInterface::setupForRepeatedUse(int senseOfAdventure, int printOut) { // First try switch (senseOfAdventure) { case 0: specialOptions_=8; break; case 1: specialOptions_=1+2+8; break; case 2: specialOptions_=1+2+4+8; break; case 3: specialOptions_=1+8; break; } bool stopPrinting=false; if (printOut<0) { stopPrinting=true; } else if (!printOut) { bool takeHint; OsiHintStrength strength; getHintParam(OsiDoReducePrint,takeHint,strength); int messageLevel=messageHandler()->logLevel(); if (strength!=OsiHintIgnore&&takeHint) messageLevel--; stopPrinting = (messageLevel<=0); } #ifndef COIN_DEVELOP if (stopPrinting) { CoinMessages * messagesPointer = modelPtr_->messagesPointer(); // won't even build messages messagesPointer->setDetailMessages(100,10000,reinterpret_cast (NULL)); } #endif } #ifndef NDEBUG // For errors to make sure print to screen // only called in debug mode static void indexError(int index, std::string methodName) { std::cerr<<"Illegal index "<setIntParam(static_cast (key), value); } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::setDblParam(OsiDblParam key, double value) { if (key != OsiLastDblParam ) { if (key==OsiDualObjectiveLimit||key==OsiPrimalObjectiveLimit) value *= modelPtr_->optimizationDirection(); return modelPtr_->setDblParam(static_cast (key), value); } else { return false; } } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::setStrParam(OsiStrParam key, const std::string & value) { assert (key!=OsiSolverName); if (key != OsiLastStrParam ) { return modelPtr_->setStrParam(static_cast (key), value); } else { return false; } } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::getIntParam(OsiIntParam key, int& value) const { return modelPtr_->getIntParam(static_cast (key), value); } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::getDblParam(OsiDblParam key, double& value) const { if (key != OsiLastDblParam ) { bool condition = modelPtr_->getDblParam(static_cast (key), value); if (key==OsiDualObjectiveLimit||key==OsiPrimalObjectiveLimit) value *= modelPtr_->optimizationDirection(); return condition; } else { return false; } } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::getStrParam(OsiStrParam key, std::string & value) const { if ( key==OsiSolverName ) { value = "clp"; return true; } if (key != OsiLastStrParam ) { return modelPtr_->getStrParam(static_cast (key), value); } else { return false; } } //############################################################################# // Methods returning info on how the solution process terminated //############################################################################# bool OsiClpSolverInterface::isAbandoned() const { // not sure about -1 (should not happen) return (modelPtr_->status()==4||modelPtr_->status()==-1|| (modelPtr_->status()==1&&modelPtr_->secondaryStatus()==8)); } bool OsiClpSolverInterface::isProvenOptimal() const { const int stat = modelPtr_->status(); return (stat == 0); } bool OsiClpSolverInterface::isProvenPrimalInfeasible() const { const int stat = modelPtr_->status(); if (stat != 1) return false; return true; } bool OsiClpSolverInterface::isProvenDualInfeasible() const { const int stat = modelPtr_->status(); return stat == 2; } /* NOTE - Coding if limit > 1.0e30 says that 1.0e29 is loose bound so all maximization tests are changed */ bool OsiClpSolverInterface::isPrimalObjectiveLimitReached() const { double limit = 0.0; modelPtr_->getDblParam(ClpPrimalObjectiveLimit, limit); if (fabs(limit) > 1e30) { // was not ever set return false; } const double obj = modelPtr_->objectiveValue(); int maxmin = static_cast (modelPtr_->optimizationDirection()); switch (lastAlgorithm_) { case 0: // no simplex was needed return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/; case 2: // dual simplex if (modelPtr_->status() == 0) // optimal return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/; return false; case 1: // primal simplex return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/; } return false; // fake return } bool OsiClpSolverInterface::isDualObjectiveLimitReached() const { const int stat = modelPtr_->status(); if (stat == 1) return true; double limit = 0.0; modelPtr_->getDblParam(ClpDualObjectiveLimit, limit); if (fabs(limit) > 1e30) { // was not ever set return false; } const double obj = modelPtr_->objectiveValue(); int maxmin = static_cast (modelPtr_->optimizationDirection()); switch (lastAlgorithm_) { case 0: // no simplex was needed return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/; case 1: // primal simplex if (stat == 0) // optimal return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/; return false; case 2: // dual simplex if (stat != 0 && stat != 3) // over dual limit return true; return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/; } return false; // fake return } bool OsiClpSolverInterface::isIterationLimitReached() const { const int status = modelPtr_->status(); const int secondaryStatus = modelPtr_->secondaryStatus(); return (status == 3 && secondaryStatus != 9); } //############################################################################# // WarmStart related methods //############################################################################# CoinWarmStart *OsiClpSolverInterface::getEmptyWarmStart () const { return (static_cast(new CoinWarmStartBasis())) ; } CoinWarmStart* OsiClpSolverInterface::getWarmStart() const { return new CoinWarmStartBasis(basis_); } /* Get warm start information. Return warm start information for the current state of the solver interface. If there is no valid warm start information, an empty warm start object wil be returned. This does not necessarily create an object - may just point to one. must Delete set true if user should delete returned object. OsiClp version always returns pointer and false. */ CoinWarmStart* OsiClpSolverInterface::getPointerToWarmStart(bool & mustDelete) { mustDelete = false; return &basis_; } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::setWarmStart(const CoinWarmStart* warmstart) { modelPtr_->whatsChanged_ &= 0xffff; const CoinWarmStartBasis* ws = dynamic_cast(warmstart); if (ws) { basis_ = CoinWarmStartBasis(*ws); return true; } else if (!warmstart) { // create from current basis basis_ = getBasis(modelPtr_); return true; } else { return false; } } //############################################################################# // Hotstart related methods (primarily used in strong branching) //############################################################################# void OsiClpSolverInterface::markHotStart() { #ifdef CBC_STATISTICS osi_hot++; #endif //printf("HotStart options %x changed %x, small %x spare %x\n", // specialOptions_,modelPtr_->whatsChanged_, // smallModel_,spareArrays_); modelPtr_->setProblemStatus(0); saveData_.perturbation_=0; saveData_.specialOptions_ = modelPtr_->specialOptions_; modelPtr_->specialOptions_ |= 0x1000000; modelPtr_->specialOptions_ = saveData_.specialOptions_; ClpObjective * savedObjective=NULL; double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit]; if (fakeObjective_) { modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~128)); // See if all with costs fixed int numberColumns = modelPtr_->numberColumns_; const double * obj = modelPtr_->objective(); const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); int i; for (i=0;iobjective_; modelPtr_->objective_=fakeObjective_; modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX; saveData_.perturbation_=1; } else { modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()|128); } } } #define CLEAN_HOT_START #ifdef CLEAN_HOT_START if ((specialOptions_&65536)!=0) { //specialOptions_ |= 65536; saveData_.scalingFlag_=modelPtr_->logLevel(); if (modelPtr_->logLevel()<2) modelPtr_->setLogLevel(0); assert ((specialOptions_&128)==0); // space for save arrays int numberColumns = modelPtr_->numberColumns(); int numberRows = modelPtr_->numberRows(); // Get space for strong branching int size = static_cast((1+4*(numberRows+numberColumns))*sizeof(double)); // and for save of original column bounds size += static_cast(2*numberColumns*sizeof(double)); size += static_cast((1+4*numberRows+2*numberColumns)*sizeof(int)); size += numberRows+numberColumns; assert (spareArrays_==NULL); spareArrays_ = new char[size]; //memset(spareArrays_,0x20,size); // Setup for strong branching assert (factorization_==NULL); if ((specialOptions_&131072)!=0) { assert (lastNumberRows_>=0); if (modelPtr_->rowScale_!=rowScale_.array()) { assert(modelPtr_->columnScale_!=columnScale_.array()); delete [] modelPtr_->rowScale_; modelPtr_->rowScale_=NULL; delete [] modelPtr_->columnScale_; modelPtr_->columnScale_=NULL; if (lastNumberRows_==modelPtr_->numberRows()) { // use scaling modelPtr_->rowScale_ = rowScale_.array(); modelPtr_->columnScale_ = columnScale_.array(); } else { specialOptions_ &= ~131072; } } lastNumberRows_ = -1 -lastNumberRows_; } factorization_ = static_cast(modelPtr_)->setupForStrongBranching(spareArrays_,numberRows, numberColumns,true); double * arrayD = reinterpret_cast (spareArrays_); arrayD[0]=modelPtr_->objectiveValue()* modelPtr_->optimizationDirection(); double * saveSolution = arrayD+1; double * saveLower = saveSolution + (numberRows+numberColumns); double * saveUpper = saveLower + (numberRows+numberColumns); double * saveObjective = saveUpper + (numberRows+numberColumns); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; CoinMemcpyN( modelPtr_->columnLower(),numberColumns, saveLowerOriginal); CoinMemcpyN( modelPtr_->columnUpper(),numberColumns, saveUpperOriginal); #if 0 if (whichRange_&&whichRange_[0]) { // get ranging information int numberToDo = whichRange_[0]; int * which = new int [numberToDo]; // Convert column numbers int * backColumn = whichColumn+numberColumns; for (int i=0;igutsOfSolution(NULL,NULL,false); // Tell code we can increase costs in some cases modelPtr_->setCurrentDualTolerance(0.0); ((ClpSimplexOther *) modelPtr_)->dualRanging(numberToDo,which, upRange, whichUp, downRange, whichDown); delete [] whichDown; delete [] whichUp; delete [] which; rowActivity_=upRange; columnActivity_=downRange; } #endif if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } return; } #endif if ((specialOptions_&8192)==0&&false) { // ||(specialOptions_&65536)!=0) { delete ws_; ws_ = dynamic_cast(getWarmStart()); int numberRows = modelPtr_->numberRows(); rowActivity_= new double[numberRows]; CoinMemcpyN(modelPtr_->primalRowSolution(),numberRows,rowActivity_); int numberColumns = modelPtr_->numberColumns(); columnActivity_= new double[numberColumns]; CoinMemcpyN(modelPtr_->primalColumnSolution(),numberColumns,columnActivity_); } else { #if 0 int saveLevel = modelPtr_->logLevel(); modelPtr_->setLogLevel(0); //modelPtr_->dual(); OsiClpSolverInterface::resolve(); if (modelPtr_->numberIterations()>0) printf("**** iterated large %d\n",modelPtr_->numberIterations()); //else //printf("no iterations\n"); modelPtr_->setLogLevel(saveLevel); #endif // called from CbcNode int numberColumns = modelPtr_->numberColumns(); int numberRows = modelPtr_->numberRows(); // Get space for crunch and strong branching (too much) int size = static_cast((1+4*(numberRows+numberColumns))*sizeof(double)); // and for save of original column bounds size += static_cast(2*numberColumns*sizeof(double)); size += static_cast((1+4*numberRows+2*numberColumns)*sizeof(int)); size += numberRows+numberColumns; #ifdef KEEP_SMALL if(smallModel_&&(modelPtr_->whatsChanged_&0x30000)!=0x30000) { //printf("Bounds changed ? %x\n",modelPtr_->whatsChanged_); delete smallModel_; smallModel_=NULL; } if (!smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; } #endif if (spareArrays_==NULL) { //if (smallModel_) //printf("small model %x\n",smallModel_); delete smallModel_; smallModel_=NULL; spareArrays_ = new char[size]; //memset(spareArrays_,0x20,size); } else { double * arrayD = reinterpret_cast (spareArrays_); double * saveSolution = arrayD+1; double * saveLower = saveSolution + (numberRows+numberColumns); double * saveUpper = saveLower + (numberRows+numberColumns); double * saveObjective = saveUpper + (numberRows+numberColumns); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; double * lowerOriginal = modelPtr_->columnLower(); double * upperOriginal = modelPtr_->columnUpper(); arrayD = saveUpperOriginal + numberColumns; int * savePivot = reinterpret_cast (arrayD); int * whichRow = savePivot+numberRows; int * whichColumn = whichRow + 3*numberRows; int nSame=0; int nSub=0; for (int i=0;i1.0e-30); double up = upperOriginal[i]; double upOld = saveUpperOriginal[i]; if (lo>=loOld&&up<=upOld) { if (lo==loOld&&up==upOld) { nSame++; } else { nSub++; //if (!isInteger(i)) //nSub+=10; } } } //printf("Mark Hot %d bounds same, %d interior, %d bad\n", // nSame,nSub,numberColumns-nSame-nSub); if (nSamecolumnLower(); double * upperSmall = smallModel_->columnUpper(); int numberColumns2 = smallModel_->numberColumns(); for (int i=0;i (spareArrays_); arrayD[0]=modelPtr_->objectiveValue()* modelPtr_->optimizationDirection(); double * saveSolution = arrayD+1; double * saveLower = saveSolution + (numberRows+numberColumns); double * saveUpper = saveLower + (numberRows+numberColumns); double * saveObjective = saveUpper + (numberRows+numberColumns); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; arrayD = saveUpperOriginal + numberColumns; int * savePivot = reinterpret_cast (arrayD); int * whichRow = savePivot+numberRows; int * whichColumn = whichRow + 3*numberRows; int * arrayI = whichColumn + 2*numberColumns; //unsigned char * saveStatus = (unsigned char *) (arrayI+1); // Use dual region double * rhs = modelPtr_->dualRowSolution(); int nBound=0; ClpSimplex * small; #ifndef KEEP_SMALL assert (!smallModel_); small = static_cast (modelPtr_)->crunch(rhs,whichRow,whichColumn,nBound,true); bool needSolveInSetupHotStart=true; #else bool needSolveInSetupHotStart=true; if (!smallModel_) { #ifndef NDEBUG CoinFillN(whichRow,3*numberRows+2*numberColumns,-1); #endif small = static_cast (modelPtr_)->crunch(rhs,whichRow,whichColumn,nBound,true); #ifndef NDEBUG int nCopy = 3*numberRows+2*numberColumns; for (int i=0;i=-CoinMax(numberRows,numberColumns)&&whichRow[i]intParam_[ClpMaxNumIterationHotStart]; //if (5*small->factorization_->maximumPivots()> // 4*hotIts) //small->factorization_->maximumPivots(hotIts+1); } else { assert((modelPtr_->whatsChanged_&0x30000)==0x30000); //delete [] spareArrays_; //spareArrays_ = NULL; assert (spareArrays_); int nCopy = 3*numberRows+2*numberColumns; nBound = whichRow[nCopy]; #ifndef NDEBUG for (int i=0;i=-CoinMax(numberRows,numberColumns)&&whichRow[i]specialOptions_ |= 262144; small->specialOptions_ &= ~65536; } if (small&&(specialOptions_&131072)!=0) { assert (lastNumberRows_>=0); int numberRows2 = small->numberRows(); int numberColumns2 = small->numberColumns(); double * rowScale2 = new double [2*numberRows2]; const double * rowScale = rowScale_.array(); double * inverseScale2 = rowScale2+numberRows2; const double * inverseScale = rowScale+modelPtr_->numberRows_; int i; for (i=0;isetRowScale(rowScale2); double * columnScale2 = new double [2*numberColumns2]; const double * columnScale = columnScale_.array(); inverseScale2 = columnScale2+numberColumns2; inverseScale = columnScale+modelPtr_->numberColumns_; for (i=0;isetColumnScale(columnScale2); } if (!small) { // should never be infeasible .... but delete [] spareArrays_; spareArrays_=NULL; delete ws_; ws_ = dynamic_cast(getWarmStart()); int numberRows = modelPtr_->numberRows(); rowActivity_= new double[numberRows]; CoinMemcpyN(modelPtr_->primalRowSolution(),numberRows,rowActivity_); int numberColumns = modelPtr_->numberColumns(); columnActivity_= new double[numberColumns]; CoinMemcpyN(modelPtr_->primalColumnSolution(),numberColumns,columnActivity_); modelPtr_->setProblemStatus(1); if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; } return; } int clpOptions = modelPtr_->specialOptions(); clpOptions &= ~65536; if((specialOptions_&1)==0) { small->setSpecialOptions(clpOptions|(64|1024)); } else { if((specialOptions_&4)==0) small->setSpecialOptions(clpOptions|(64|128|512|1024|4096)); else small->setSpecialOptions(clpOptions|(64|128|512|1024|2048|4096)); } arrayI[0]=nBound; assert (smallModel_==NULL||small==smallModel_); if ((specialOptions_&256)!=0||1) { // only need to do this on second pass in CbcNode if (modelPtr_->logLevel()<2) small->setLogLevel(0); small->specialOptions_ |= 262144; small->moreSpecialOptions_ = modelPtr_->moreSpecialOptions_; #define SETUP_HOT #ifndef SETUP_HOT small->dual(); #else assert (factorization_==NULL); //needSolveInSetupHotStart=true; ClpFactorization * factorization = static_cast(small)->setupForStrongBranching(spareArrays_, numberRows,numberColumns, needSolveInSetupHotStart); #endif if (small->numberIterations()>0&&small->logLevel()>2) printf("**** iterated small %d\n",small->numberIterations()); //small->setLogLevel(0); // Could be infeasible if forced one way (and other way stopped on iterations) // could also be stopped on iterations if (small->status()) { #ifndef KEEP_SMALL if (small!=modelPtr_) delete small; //delete smallModel_; //smallModel_=NULL; assert (!smallModel_); #else assert (small==smallModel_); if (smallModel_!=modelPtr_) { delete smallModel_; } smallModel_=NULL; #endif delete [] spareArrays_; spareArrays_=NULL; delete ws_; ws_ = dynamic_cast(getWarmStart()); int numberRows = modelPtr_->numberRows(); rowActivity_= new double[numberRows]; CoinMemcpyN(modelPtr_->primalRowSolution(), numberRows,rowActivity_); int numberColumns = modelPtr_->numberColumns(); columnActivity_= new double[numberColumns]; CoinMemcpyN(modelPtr_->primalColumnSolution(), numberColumns,columnActivity_); modelPtr_->setProblemStatus(1); if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; } return; } else { // update model static_cast (modelPtr_)->afterCrunch(*small,whichRow,whichColumn,nBound); } #ifndef SETUP_HOT assert (factorization_==NULL); factorization_ = static_cast(small)->setupForStrongBranching(spareArrays_,numberRows, numberColumns,false); #else assert (factorization!=NULL || small->problemStatus_ ); factorization_ = factorization; #endif } else { assert (factorization_==NULL); factorization_ = static_cast(small)->setupForStrongBranching(spareArrays_,numberRows, numberColumns,false); } smallModel_=small; if (modelPtr_->logLevel()<2) smallModel_->setLogLevel(0); // Setup for strong branching int numberColumns2 = smallModel_->numberColumns(); CoinMemcpyN( modelPtr_->columnLower(),numberColumns, saveLowerOriginal); CoinMemcpyN( modelPtr_->columnUpper(),numberColumns, saveUpperOriginal); const double * smallLower = smallModel_->columnLower(); const double * smallUpper = smallModel_->columnUpper(); // But modify if bounds changed in small for (int i=0;isetFactorization(*factorization_); smallModel_->gutsOfSolution(NULL,NULL,false); // Tell code we can increase costs in some cases smallModel_->setCurrentDualTolerance(0.0); static_cast (smallModel_)->dualRanging(numberToDo,which, upRange, whichUp, downRange, whichDown); delete [] whichDown; delete [] whichUp; delete [] which; rowActivity_=upRange; columnActivity_=downRange; } } if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } } void OsiClpSolverInterface::solveFromHotStart() { #ifdef KEEP_SMALL if (!spareArrays_) { assert (!smallModel_); assert (modelPtr_->problemStatus_==1); return; } #endif ClpObjective * savedObjective=NULL; double savedDualLimit=modelPtr_->dblParam_[ClpDualObjectiveLimit]; if (saveData_.perturbation_) { // Set fake savedObjective=modelPtr_->objective_; modelPtr_->objective_=fakeObjective_; modelPtr_->dblParam_[ClpDualObjectiveLimit]=COIN_DBL_MAX; } int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); modelPtr_->getIntParam(ClpMaxNumIteration,itlimOrig_); int itlim; modelPtr_->getIntParam(ClpMaxNumIterationHotStart, itlim); // Is there an extra copy of scaled bounds int extraCopy = (modelPtr_->maximumRows_>0) ? modelPtr_->maximumRows_+modelPtr_->maximumColumns_ : 0; #ifdef CLEAN_HOT_START if ((specialOptions_&65536)!=0) { double * arrayD = reinterpret_cast (spareArrays_); double saveObjectiveValue = arrayD[0]; double * saveSolution = arrayD+1; int number = numberRows+numberColumns; CoinMemcpyN(saveSolution,number,modelPtr_->solutionRegion()); double * saveLower = saveSolution + (numberRows+numberColumns); CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion()); double * saveUpper = saveLower + (numberRows+numberColumns); CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion()); double * saveObjective = saveUpper + (numberRows+numberColumns); CoinMemcpyN(saveObjective,number,modelPtr_->costRegion()); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; arrayD = saveUpperOriginal + numberColumns; int * savePivot = reinterpret_cast (arrayD); CoinMemcpyN(savePivot,numberRows,modelPtr_->pivotVariable()); int * whichRow = savePivot+numberRows; int * whichColumn = whichRow + 3*numberRows; int * arrayI = whichColumn + 2*numberColumns; unsigned char * saveStatus = reinterpret_cast (arrayI+1); CoinMemcpyN(saveStatus,number,modelPtr_->statusArray()); modelPtr_->setFactorization(*factorization_); double * columnLower = modelPtr_->columnLower(); double * columnUpper = modelPtr_->columnUpper(); // make sure whatsChanged_ has 1 set modelPtr_->setWhatsChanged(511); double * lowerInternal = modelPtr_->lowerRegion(); double * upperInternal = modelPtr_->upperRegion(); double rhsScale = modelPtr_->rhsScale(); const double * columnScale = NULL; if (modelPtr_->scalingFlag()>0) columnScale = modelPtr_->columnScale() ; // and do bounds in case dual needs them int iColumn; for (iColumn=0;iColumnsaveLowerOriginal[iColumn]) { double value = columnLower[iColumn]; value *= rhsScale; if (columnScale) value /= columnScale[iColumn]; lowerInternal[iColumn]=value; if (extraCopy) lowerInternal[iColumn+extraCopy]=value; } if (columnUpper[iColumn]setLogLevel(1); modelPtr_->setIntParam(ClpMaxNumIteration,itlim); int saveNumberFake = (static_cast(modelPtr_))->numberFake_; int status = (static_cast(modelPtr_))->fastDual(alwaysFinish); (static_cast(modelPtr_))->numberFake_ = saveNumberFake; int problemStatus = modelPtr_->problemStatus(); double objectiveValue =modelPtr_->objectiveValue() * modelPtr_->optimizationDirection(); CoinAssert (modelPtr_->problemStatus()||modelPtr_->objectiveValue()<1.0e50); // make sure plausible double obj = CoinMax(objectiveValue,saveObjectiveValue); if (problemStatus==10||problemStatus<0) { // was trying to clean up or something odd if (problemStatus==10) lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode) status=1; } if (status) { // not finished - might be optimal modelPtr_->checkPrimalSolution(modelPtr_->solutionRegion(0), modelPtr_->solutionRegion(1)); //modelPtr_->gutsOfSolution(NULL,NULL,0); //if (problemStatus==3) //modelPtr_->computeObjectiveValue(); objectiveValue =modelPtr_->objectiveValue() * modelPtr_->optimizationDirection(); obj = CoinMax(objectiveValue,saveObjectiveValue); if (!modelPtr_->numberDualInfeasibilities()) { double limit = 0.0; modelPtr_->getDblParam(ClpDualObjectiveLimit, limit); if (modelPtr_->secondaryStatus()==1&&!problemStatus&&objnumberPrimalInfeasibilities()&&objnumberPrimalInfeasibilities()) { problemStatus=1; // infeasible } } else { // can't say much //if (problemStatus==3) //modelPtr_->computeObjectiveValue(); lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode) problemStatus=3; } } else if (!problemStatus) { if (modelPtr_->isDualObjectiveLimitReached()) problemStatus=1; // infeasible } if (status&&!problemStatus) { problemStatus=3; // can't be sure lastAlgorithm_=1; } if (problemStatus<0) problemStatus=3; modelPtr_->setProblemStatus(problemStatus); modelPtr_->setObjectiveValue(obj*modelPtr_->optimizationDirection()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = modelPtr_->solutionRegion(); // could just do changed bounds - also try double size scale so can use * not / if (!columnScale) { for (iColumn=0;iColumncomputeObjectiveValue(); if (status&&!problemStatus) { memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double)); modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution()); modelPtr_->checkSolutionInternal(); //modelPtr_->setLogLevel(1); //modelPtr_->allSlackBasis(); //modelPtr_->primal(1); //memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double)); //modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution()); //modelPtr_->checkSolutionInternal(); assert (!modelPtr_->problemStatus()); } #endif // and back bounds CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion()); CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion()); if (extraCopy) { CoinMemcpyN(saveLower,number,modelPtr_->lowerRegion()+extraCopy); CoinMemcpyN(saveUpper,number,modelPtr_->upperRegion()+extraCopy); } modelPtr_->setIntParam(ClpMaxNumIteration,itlimOrig_); if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } return; } #endif if (smallModel_==NULL) { setWarmStart(ws_); CoinMemcpyN( rowActivity_,numberRows,modelPtr_->primalRowSolution()); CoinMemcpyN(columnActivity_,numberColumns,modelPtr_->primalColumnSolution()); modelPtr_->setIntParam(ClpMaxNumIteration,CoinMin(itlim,9999)); resolve(); } else { assert (spareArrays_); double * arrayD = reinterpret_cast (spareArrays_); double saveObjectiveValue = arrayD[0]; double * saveSolution = arrayD+1; // double check arrays exist (? for nonlinear) //if (!smallModel_->solutionRegion()) //smallModel_->createRim(63); int numberRows2 = smallModel_->numberRows(); int numberColumns2 = smallModel_->numberColumns(); int number = numberRows2+numberColumns2; CoinMemcpyN(saveSolution,number,smallModel_->solutionRegion()); double * saveLower = saveSolution + (numberRows+numberColumns); CoinMemcpyN(saveLower,number,smallModel_->lowerRegion()); double * saveUpper = saveLower + (numberRows+numberColumns); CoinMemcpyN(saveUpper,number,smallModel_->upperRegion()); double * saveObjective = saveUpper + (numberRows+numberColumns); CoinMemcpyN(saveObjective,number,smallModel_->costRegion()); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; arrayD = saveUpperOriginal + numberColumns; int * savePivot = reinterpret_cast (arrayD); CoinMemcpyN(savePivot,numberRows2,smallModel_->pivotVariable()); int * whichRow = savePivot+numberRows; int * whichColumn = whichRow + 3*numberRows; int * arrayI = whichColumn + 2*numberColumns; unsigned char * saveStatus = reinterpret_cast (arrayI+1); CoinMemcpyN(saveStatus,number,smallModel_->statusArray()); /* If factorization_ NULL then infeasible not really sure how could have slipped through. But this can't make situation worse */ if (factorization_) smallModel_->setFactorization(*factorization_); //int * backColumn = whichColumn+numberColumns; const double * lowerBig = modelPtr_->columnLower(); const double * upperBig = modelPtr_->columnUpper(); // make sure whatsChanged_ has 1 set smallModel_->setWhatsChanged(511); double * lowerSmall = smallModel_->lowerRegion(); double * upperSmall = smallModel_->upperRegion(); double * lowerSmallReal = smallModel_->columnLower(); double * upperSmallReal = smallModel_->columnUpper(); int i; double rhsScale = smallModel_->rhsScale(); const double * columnScale = NULL; if (smallModel_->scalingFlag()>0) { columnScale = smallModel_->columnScale(); } // and do bounds in case dual needs them // may be infeasible for (i=0;isaveLowerOriginal[iColumn]) { double value = lowerBig[iColumn]; lowerSmallReal[i]=value; value *= rhsScale; if (columnScale) value /= columnScale[i]; lowerSmall[i]=value; } if (upperBig[iColumn]setLogLevel(1); smallModel_->setIntParam(ClpMaxNumIteration,itlim); int saveNumberFake = (static_cast(smallModel_))->numberFake_; int status; if (!infeasible) { status = static_cast(smallModel_)->fastDual(alwaysFinish); } else { status=0; smallModel_->setProblemStatus(1); } (static_cast(smallModel_))->numberFake_ = saveNumberFake; if (smallModel_->numberIterations()==-98) { printf("rrrrrrrrrrrr\n"); smallModel_->checkPrimalSolution(smallModel_->solutionRegion(0), smallModel_->solutionRegion(1)); //smallModel_->gutsOfSolution(NULL,NULL,0); //if (problemStatus==3) //smallModel_->computeObjectiveValue(); printf("robj %g\n",smallModel_->objectiveValue() * modelPtr_->optimizationDirection()); writeMps("rr.mps"); smallModel_->writeMps("rr_small.mps"); ClpSimplex temp = *smallModel_; printf("small\n"); temp.setLogLevel(63); temp.dual(); double limit = 0.0; modelPtr_->getDblParam(ClpDualObjectiveLimit, limit); if (temp.problemStatus()==0&&temp.objectiveValue()objectiveValue(), temp.objectiveValue(), smallModel_->objectiveOffset(),temp.objectiveOffset()); } printf("big\n"); temp = *modelPtr_; temp.dual(); if (temp.problemStatus()==0&&temp.objectiveValue()objectiveValue(), temp.objectiveValue(), smallModel_->objectiveOffset(),temp.objectiveOffset()); } } int problemStatus = smallModel_->problemStatus(); double objectiveValue =smallModel_->objectiveValue() * modelPtr_->optimizationDirection(); CoinAssert (smallModel_->problemStatus()||smallModel_->objectiveValue()<1.0e50); // make sure plausible double obj = CoinMax(objectiveValue,saveObjectiveValue); if (problemStatus==10||problemStatus<0) { // was trying to clean up or something odd if (problemStatus==10) lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode) status=1; } if (status) { // not finished - might be optimal smallModel_->checkPrimalSolution(smallModel_->solutionRegion(0), smallModel_->solutionRegion(1)); //smallModel_->gutsOfSolution(NULL,NULL,0); //if (problemStatus==3) //smallModel_->computeObjectiveValue(); objectiveValue =smallModel_->objectiveValue() * modelPtr_->optimizationDirection(); if (problemStatus!=10) obj = CoinMax(objectiveValue,saveObjectiveValue); if (!smallModel_->numberDualInfeasibilities()) { double limit = 0.0; modelPtr_->getDblParam(ClpDualObjectiveLimit, limit); if (smallModel_->secondaryStatus()==1&&!problemStatus&&objobjectiveValue(), temp.objectiveValue(), smallModel_->objectiveOffset(),temp.objectiveOffset()); } lastAlgorithm_=1; obj=limit; problemStatus=10; #else obj=limit; problemStatus=3; #endif } if (!smallModel_->numberPrimalInfeasibilities()&&objnumberPrimalInfeasibilities()) { problemStatus=1; // infeasible } } else { // can't say much //if (problemStatus==3) //smallModel_->computeObjectiveValue(); lastAlgorithm_=1; // so won't fail on cutoff (in CbcNode) problemStatus=3; } } else if (!problemStatus) { if (smallModel_->isDualObjectiveLimitReached()) problemStatus=1; // infeasible } if (status&&!problemStatus) { problemStatus=3; // can't be sure lastAlgorithm_=1; } if (problemStatus<0) problemStatus=3; modelPtr_->setProblemStatus(problemStatus); modelPtr_->setObjectiveValue(obj*modelPtr_->optimizationDirection()); modelPtr_->setSumDualInfeasibilities(smallModel_->sumDualInfeasibilities()); modelPtr_->setNumberDualInfeasibilities(smallModel_->numberDualInfeasibilities()); modelPtr_->setSumPrimalInfeasibilities(smallModel_->sumPrimalInfeasibilities()); modelPtr_->setNumberPrimalInfeasibilities(smallModel_->numberPrimalInfeasibilities()); double * solution = modelPtr_->primalColumnSolution(); const double * solution2 = smallModel_->solutionRegion(); if (!columnScale) { for (i=0;icomputeObjectiveValue(); #if 1 if (status&&!problemStatus) { memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double)); modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution()); modelPtr_->checkSolutionInternal(); //modelPtr_->setLogLevel(1); //modelPtr_->allSlackBasis(); //modelPtr_->primal(1); //memset(modelPtr_->primalRowSolution(),0,numberRows*sizeof(double)); //modelPtr_->clpMatrix()->times(1.0,solution,modelPtr_->primalRowSolution()); //modelPtr_->checkSolutionInternal(); assert (!modelPtr_->problemStatus()); } #endif modelPtr_->setNumberIterations(smallModel_->numberIterations()); // and back bounds CoinMemcpyN(saveLower,number,smallModel_->lowerRegion()); CoinMemcpyN(saveUpper,number,smallModel_->upperRegion()); } if (savedObjective) { // fix up modelPtr_->dblParam_[ClpDualObjectiveLimit]=savedDualLimit; //modelPtr_->setMoreSpecialOptions(modelPtr_->moreSpecialOptions()&(~32)); modelPtr_->objective_=savedObjective; if (!modelPtr_->problemStatus_) { CoinZeroN(modelPtr_->dual_,modelPtr_->numberRows_); CoinZeroN(modelPtr_->reducedCost_,modelPtr_->numberColumns_); if (modelPtr_->dj_&&(modelPtr_->whatsChanged_&1)!=0) CoinZeroN(modelPtr_->dj_,modelPtr_->numberColumns_+modelPtr_->numberRows_); modelPtr_->computeObjectiveValue(); } } modelPtr_->setIntParam(ClpMaxNumIteration,itlimOrig_); } void OsiClpSolverInterface::unmarkHotStart() { #ifdef CLEAN_HOT_START if ((specialOptions_&65536)!=0) { modelPtr_->setLogLevel(saveData_.scalingFlag_); modelPtr_->deleteRim(0); if (lastNumberRows_<0) { specialOptions_ |= 131072; lastNumberRows_ = -1 -lastNumberRows_; if (modelPtr_->rowScale_) { if (modelPtr_->rowScale_!=rowScale_.array()) { delete [] modelPtr_->rowScale_; delete [] modelPtr_->columnScale_; } modelPtr_->rowScale_=NULL; modelPtr_->columnScale_=NULL; } } delete factorization_; delete [] spareArrays_; smallModel_=NULL; spareArrays_=NULL; factorization_=NULL; delete [] rowActivity_; delete [] columnActivity_; rowActivity_=NULL; columnActivity_=NULL; return; } #endif if (smallModel_==NULL) { setWarmStart(ws_); int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); CoinMemcpyN( rowActivity_,numberRows,modelPtr_->primalRowSolution()); CoinMemcpyN(columnActivity_,numberColumns,modelPtr_->primalColumnSolution()); delete ws_; ws_ = NULL; } else { #ifndef KEEP_SMALL if (smallModel_!=modelPtr_) delete smallModel_; smallModel_=NULL; #else if (smallModel_==modelPtr_) { smallModel_=NULL; } else if (smallModel_) { if(!spareArrays_) { delete smallModel_; smallModel_=NULL; delete factorization_; factorization_=NULL; } else { static_cast (smallModel_)->cleanupAfterStrongBranching( factorization_); if ((smallModel_->specialOptions_&4096)==0) { delete factorization_; } } } #endif //delete [] spareArrays_; //spareArrays_=NULL; factorization_=NULL; } delete [] rowActivity_; delete [] columnActivity_; rowActivity_=NULL; columnActivity_=NULL; // Make sure whatsChanged not out of sync if (!modelPtr_->columnUpperWork_) modelPtr_->whatsChanged_ &= ~0xffff; modelPtr_->specialOptions_ = saveData_.specialOptions_; } //############################################################################# // Problem information methods (original data) //############################################################################# //------------------------------------------------------------------ const char * OsiClpSolverInterface::getRowSense() const { extractSenseRhsRange(); return rowsense_; } //------------------------------------------------------------------ const double * OsiClpSolverInterface::getRightHandSide() const { extractSenseRhsRange(); return rhs_; } //------------------------------------------------------------------ const double * OsiClpSolverInterface::getRowRange() const { extractSenseRhsRange(); return rowrange_; } //------------------------------------------------------------------ // Return information on integrality //------------------------------------------------------------------ bool OsiClpSolverInterface::isContinuous(int colNumber) const { if ( integerInformation_==NULL ) return true; #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isContinuous"); } #endif if ( integerInformation_[colNumber]==0 ) return true; return false; } bool OsiClpSolverInterface::isBinary(int colNumber) const { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isBinary"); } #endif if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) { return false; } else { const double * cu = getColUpper(); const double * cl = getColLower(); if ((cu[colNumber]== 1 || cu[colNumber]== 0) && (cl[colNumber]== 0 || cl[colNumber]==1)) return true; else return false; } } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::isInteger(int colNumber) const { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isInteger"); } #endif if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) return false; else return true; } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::isIntegerNonBinary(int colNumber) const { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isIntegerNonBinary"); } #endif if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) { return false; } else { return !isBinary(colNumber); } } //----------------------------------------------------------------------------- bool OsiClpSolverInterface::isFreeBinary(int colNumber) const { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isFreeBinary"); } #endif if ( integerInformation_==NULL || integerInformation_[colNumber]==0 ) { return false; } else { const double * cu = getColUpper(); const double * cl = getColLower(); if ((cu[colNumber]== 1) && (cl[colNumber]== 0)) return true; else return false; } } /* Return array of column length 0 - continuous 1 - binary (may get fixed later) 2 - general integer (may get fixed later) */ const char * OsiClpSolverInterface::getColType(bool refresh) const { if (!columnType_||refresh) { const int numCols = getNumCols() ; if (!columnType_) columnType_ = new char [numCols]; if ( integerInformation_==NULL ) { memset(columnType_,0,numCols); } else { const double * cu = getColUpper(); const double * cl = getColLower(); for (int i = 0 ; i < numCols ; ++i) { if (integerInformation_[i]) { if ((cu[i]== 1 || cu[i]== 0) && (cl[i]== 0 || cl[i]==1)) columnType_[i]=1; else columnType_[i]=2; } else { columnType_[i]=0; } } } } return columnType_; } /* Return true if column is integer but does not have to be declared as such. Note: This function returns true if the the column is binary or a general integer. */ bool OsiClpSolverInterface::isOptionalInteger(int colNumber) const { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (colNumber<0||colNumber>=n) { indexError(colNumber,"isInteger"); } #endif if ( integerInformation_==NULL || integerInformation_[colNumber]!=2 ) return false; else return true; } /* Set the index-th variable to be an optional integer variable */ void OsiClpSolverInterface::setOptionalInteger(int index) { if (!integerInformation_) { integerInformation_ = new char[modelPtr_->numberColumns()]; CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast (0)); } #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (index<0||index>=n) { indexError(index,"setInteger"); } #endif integerInformation_[index]=2; modelPtr_->setInteger(index); } //------------------------------------------------------------------ // Row and column copies of the matrix ... //------------------------------------------------------------------ const CoinPackedMatrix * OsiClpSolverInterface::getMatrixByRow() const { if ( matrixByRow_ == NULL || matrixByRow_->getNumElements() != modelPtr_->clpMatrix()->getNumElements() ) { delete matrixByRow_; matrixByRow_ = new CoinPackedMatrix(); matrixByRow_->setExtraGap(0.0); matrixByRow_->setExtraMajor(0.0); matrixByRow_->reverseOrderedCopyOf(*modelPtr_->matrix()); //matrixByRow_->removeGaps(); #if 0 CoinPackedMatrix back; std::cout<<"start check"<matrix()->isEquivalent2(back); std::cout<<"stop check"<getNumElements()==modelPtr_->clpMatrix()->getNumElements()); return matrixByRow_; } const CoinPackedMatrix * OsiClpSolverInterface::getMatrixByCol() const { return modelPtr_->matrix(); } // Get pointer to mutable column-wise copy of matrix (returns NULL if not meaningful) CoinPackedMatrix * OsiClpSolverInterface::getMutableMatrixByCol() const { ClpPackedMatrix * matrix = dynamic_cast(modelPtr_->matrix_) ; if (matrix) return matrix->getPackedMatrix(); else return NULL; } //------------------------------------------------------------------ std::vector OsiClpSolverInterface::getDualRays(int /*maxNumRays*/, bool fullRay) const { return std::vector(1, modelPtr_->infeasibilityRay(fullRay)); } //------------------------------------------------------------------ std::vector OsiClpSolverInterface::getPrimalRays(int /*maxNumRays*/) const { return std::vector(1, modelPtr_->unboundedRay()); } //############################################################################# void OsiClpSolverInterface::setContinuous(int index) { if (integerInformation_) { #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (index<0||index>=n) { indexError(index,"setContinuous"); } #endif integerInformation_[index]=0; } modelPtr_->setContinuous(index); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setInteger(int index) { if (!integerInformation_) { integerInformation_ = new char[modelPtr_->numberColumns()]; CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast (0)); } #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (index<0||index>=n) { indexError(index,"setInteger"); } #endif integerInformation_[index]=1; modelPtr_->setInteger(index); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setContinuous(const int* indices, int len) { if (integerInformation_) { #ifndef NDEBUG int n = modelPtr_->numberColumns(); #endif int i; for (i=0; i=n) { indexError(colNumber,"setContinuous"); } #endif integerInformation_[colNumber]=0; modelPtr_->setContinuous(colNumber); } } } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setInteger(const int* indices, int len) { if (!integerInformation_) { integerInformation_ = new char[modelPtr_->numberColumns()]; CoinFillN ( integerInformation_, modelPtr_->numberColumns(),static_cast (0)); } #ifndef NDEBUG int n = modelPtr_->numberColumns(); #endif int i; for (i=0; i=n) { indexError(colNumber,"setInteger"); } #endif integerInformation_[colNumber]=1; modelPtr_->setInteger(colNumber); } } /* Set the objective coefficients for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ void OsiClpSolverInterface::setObjective(const double * array) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; modelPtr_->whatsChanged_ &= (0xffff&~64); int n = modelPtr_->numberColumns() ; if (fakeMinInSimplex_) { std::transform(array,array+n, modelPtr_->objective(),std::negate()) ; } else { CoinMemcpyN(array,n,modelPtr_->objective()); } } /* Set the lower bounds for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ void OsiClpSolverInterface::setColLower(const double * array) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; modelPtr_->whatsChanged_ &= (0x1ffff&128); CoinMemcpyN(array,modelPtr_->numberColumns(), modelPtr_->columnLower()); } /* Set the upper bounds for all columns array [getNumCols()] is an array of values for the objective. This defaults to a series of set operations and is here for speed. */ void OsiClpSolverInterface::setColUpper(const double * array) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; modelPtr_->whatsChanged_ &= (0x1ffff&256); CoinMemcpyN(array,modelPtr_->numberColumns(), modelPtr_->columnUpper()); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setColSolution(const double * cs) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; CoinDisjointCopyN(cs,modelPtr_->numberColumns(), modelPtr_->primalColumnSolution()); if (modelPtr_->solveType()==2) { // directly into code as well CoinDisjointCopyN(cs,modelPtr_->numberColumns(), modelPtr_->solutionRegion(1)); } // compute row activity memset(modelPtr_->primalRowSolution(),0,modelPtr_->numberRows()*sizeof(double)); modelPtr_->times(1.0,modelPtr_->primalColumnSolution(),modelPtr_->primalRowSolution()); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setRowPrice(const double * rs) { CoinDisjointCopyN(rs,modelPtr_->numberRows(), modelPtr_->dualRowSolution()); if (modelPtr_->solveType()==2) { // directly into code as well (? sign ) CoinDisjointCopyN(rs,modelPtr_->numberRows(), modelPtr_->djRegion(0)); } // compute reduced costs memcpy(modelPtr_->dualColumnSolution(),modelPtr_->objective(), modelPtr_->numberColumns()*sizeof(double)); modelPtr_->transposeTimes(-1.0,modelPtr_->dualRowSolution(),modelPtr_->dualColumnSolution()); } //############################################################################# // Problem modifying methods (matrix) //############################################################################# void OsiClpSolverInterface::addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj) { int numberColumns = modelPtr_->numberColumns(); modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256)); modelPtr_->resize(modelPtr_->numberRows(),numberColumns+1); linearObjective_ = modelPtr_->objective(); basis_.resize(modelPtr_->numberRows(),numberColumns+1); setColBounds(numberColumns,collb,colub); setObjCoeff(numberColumns,obj); if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendCol(vec); if (integerInformation_) { char * temp = new char[numberColumns+1]; CoinMemcpyN(integerInformation_,numberColumns,temp); delete [] integerInformation_; integerInformation_ = temp; integerInformation_[numberColumns]=0; } freeCachedResults(); } //----------------------------------------------------------------------------- /* Add a column (primal variable) to the problem. */ void OsiClpSolverInterface::addCol(int numberElements, const int * rows, const double * elements, const double collb, const double colub, const double obj) { CoinPackedVector column(numberElements, rows, elements); addCol(column,collb,colub,obj); } // Add a named column (primal variable) to the problem. void OsiClpSolverInterface::addCol(const CoinPackedVectorBase& vec, const double collb, const double colub, const double obj, std::string name) { int ndx = getNumCols() ; addCol(vec,collb,colub,obj) ; setColName(ndx,name) ; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addCols(const int numcols, const CoinPackedVectorBase * const * cols, const double* collb, const double* colub, const double* obj) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256)); int numberColumns = modelPtr_->numberColumns(); modelPtr_->resize(modelPtr_->numberRows(),numberColumns+numcols); linearObjective_ = modelPtr_->objective(); basis_.resize(modelPtr_->numberRows(),numberColumns+numcols); double * lower = modelPtr_->columnLower()+numberColumns; double * upper = modelPtr_->columnUpper()+numberColumns; double * objective = modelPtr_->objective()+numberColumns; int iCol; if (collb) { for (iCol = 0; iCol < numcols; iCol++) { lower[iCol]= forceIntoRange(collb[iCol], -OsiClpInfinity, OsiClpInfinity); if (lower[iCol]<-1.0e27) lower[iCol]=-COIN_DBL_MAX; } } else { CoinFillN ( lower, numcols,0.0); } if (colub) { for (iCol = 0; iCol < numcols; iCol++) { upper[iCol]= forceIntoRange(colub[iCol], -OsiClpInfinity, OsiClpInfinity); if (upper[iCol]>1.0e27) upper[iCol]=COIN_DBL_MAX; } } else { CoinFillN ( upper, numcols,COIN_DBL_MAX); } if (obj) { for (iCol = 0; iCol < numcols; iCol++) { objective[iCol] = obj[iCol]; } } else { CoinFillN ( objective, numcols,0.0); } if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendCols(numcols,cols); if (integerInformation_) { char * temp = new char[numberColumns+numcols]; CoinMemcpyN(integerInformation_,numberColumns,temp); delete [] integerInformation_; integerInformation_ = temp; for (iCol = 0; iCol < numcols; iCol++) integerInformation_[numberColumns+iCol]=0; } freeCachedResults(); } void OsiClpSolverInterface::addCols(const int numcols, const int * columnStarts, const int * rows, const double * elements, const double* collb, const double* colub, const double* obj) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256)); int numberColumns = modelPtr_->numberColumns(); modelPtr_->resize(modelPtr_->numberRows(),numberColumns+numcols); linearObjective_ = modelPtr_->objective(); basis_.resize(modelPtr_->numberRows(),numberColumns+numcols); double * lower = modelPtr_->columnLower()+numberColumns; double * upper = modelPtr_->columnUpper()+numberColumns; double * objective = modelPtr_->objective()+numberColumns; int iCol; if (collb) { for (iCol = 0; iCol < numcols; iCol++) { lower[iCol]= forceIntoRange(collb[iCol], -OsiClpInfinity, OsiClpInfinity); if (lower[iCol]<-1.0e27) lower[iCol]=-COIN_DBL_MAX; } } else { CoinFillN ( lower, numcols,0.0); } if (colub) { for (iCol = 0; iCol < numcols; iCol++) { upper[iCol]= forceIntoRange(colub[iCol], -OsiClpInfinity, OsiClpInfinity); if (upper[iCol]>1.0e27) upper[iCol]=COIN_DBL_MAX; } } else { CoinFillN ( upper, numcols,COIN_DBL_MAX); } if (obj) { for (iCol = 0; iCol < numcols; iCol++) { objective[iCol] = obj[iCol]; } } else { CoinFillN ( objective, numcols,0.0); } if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendCols(numcols,columnStarts,rows,elements); if (integerInformation_) { char * temp = new char[numberColumns+numcols]; CoinMemcpyN(integerInformation_,numberColumns,temp); delete [] integerInformation_; integerInformation_ = temp; for (iCol = 0; iCol < numcols; iCol++) integerInformation_[numberColumns+iCol]=0; } freeCachedResults(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::deleteCols(const int num, const int * columnIndices) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|8|64|128|256)); findIntegers(false); deleteBranchingInfo(num,columnIndices); modelPtr_->deleteColumns(num,columnIndices); int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; if (num&&nameDiscipline) { // Very clumsy (and inefficient) - need to sort and then go backwards in ? chunks int * indices = CoinCopyOfArray(columnIndices,num); std::sort(indices,indices+num); int num2=num; while(num2) { int next = indices[num2-1]; int firstDelete = num2-1; int i; for (i=num2-2;i>=0;i--) { if (indices[i]+1==next) { next --; firstDelete=i; } else { break; } } OsiSolverInterface::deleteColNames(indices[firstDelete],num2-firstDelete); num2 = firstDelete; assert (num2>=0); } delete [] indices; } // synchronize integers (again) if (integerInformation_) { int numberColumns = modelPtr_->numberColumns(); for (int i=0;iisInteger(i)) integerInformation_[i]=1; else integerInformation_[i]=0; } } basis_.deleteColumns(num,columnIndices); linearObjective_ = modelPtr_->objective(); freeCachedResults(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+1,modelPtr_->numberColumns()); basis_.resize(numberRows+1,modelPtr_->numberColumns()); setRowBounds(numberRows,rowlb,rowub); if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRow(vec); freeCachedResults1(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec, const double rowlb, const double rowub, std::string name) { int ndx = getNumRows() ; addRow(vec,rowlb,rowub) ; setRowName(ndx,name) ; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+1,modelPtr_->numberColumns()); basis_.resize(numberRows+1,modelPtr_->numberColumns()); double rowlb = 0, rowub = 0; convertSenseToBound(rowsen, rowrhs, rowrng, rowlb, rowub); setRowBounds(numberRows,rowlb,rowub); if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRow(vec); freeCachedResults1(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRow(int numberElements, const int * columns, const double * elements, const double rowlb, const double rowub) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+1,modelPtr_->numberColumns()); basis_.resize(numberRows+1,modelPtr_->numberColumns()); setRowBounds(numberRows,rowlb,rowub); if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRow(numberElements, columns, elements); CoinBigIndex starts[2]; starts[0]=0; starts[1]=numberElements; redoScaleFactors( 1,starts, columns, elements); freeCachedResults1(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns()); basis_.resize(numberRows+numrows,modelPtr_->numberColumns()); double * lower = modelPtr_->rowLower()+numberRows; double * upper = modelPtr_->rowUpper()+numberRows; int iRow; for (iRow = 0; iRow < numrows; iRow++) { if (rowlb) lower[iRow]= forceIntoRange(rowlb[iRow], -OsiClpInfinity, OsiClpInfinity); else lower[iRow]=-OsiClpInfinity; if (rowub) upper[iRow]= forceIntoRange(rowub[iRow], -OsiClpInfinity, OsiClpInfinity); else upper[iRow]=OsiClpInfinity; if (lower[iRow]<-1.0e27) lower[iRow]=-COIN_DBL_MAX; if (upper[iRow]>1.0e27) upper[iRow]=COIN_DBL_MAX; } if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRows(numrows,rows); freeCachedResults1(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const char* rowsen, const double* rowrhs, const double* rowrng) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns()); basis_.resize(numberRows+numrows,modelPtr_->numberColumns()); double * lower = modelPtr_->rowLower()+numberRows; double * upper = modelPtr_->rowUpper()+numberRows; int iRow; for (iRow = 0; iRow < numrows; iRow++) { double rowlb = 0, rowub = 0; convertSenseToBound(rowsen[iRow], rowrhs[iRow], rowrng[iRow], rowlb, rowub); lower[iRow]= forceIntoRange(rowlb, -OsiClpInfinity, OsiClpInfinity); upper[iRow]= forceIntoRange(rowub, -OsiClpInfinity, OsiClpInfinity); if (lower[iRow]<-1.0e27) lower[iRow]=-COIN_DBL_MAX; if (upper[iRow]>1.0e27) upper[iRow]=COIN_DBL_MAX; } if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRows(numrows,rows); freeCachedResults1(); } void OsiClpSolverInterface::addRows(const int numrows, const int * rowStarts, const int * columns, const double * element, const double* rowlb, const double* rowub) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); freeCachedResults0(); int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+numrows,modelPtr_->numberColumns()); basis_.resize(numberRows+numrows,modelPtr_->numberColumns()); double * lower = modelPtr_->rowLower()+numberRows; double * upper = modelPtr_->rowUpper()+numberRows; int iRow; for (iRow = 0; iRow < numrows; iRow++) { if (rowlb) lower[iRow]= forceIntoRange(rowlb[iRow], -OsiClpInfinity, OsiClpInfinity); else lower[iRow]=-OsiClpInfinity; if (rowub) upper[iRow]= forceIntoRange(rowub[iRow], -OsiClpInfinity, OsiClpInfinity); else upper[iRow]=OsiClpInfinity; if (lower[iRow]<-1.0e27) lower[iRow]=-COIN_DBL_MAX; if (upper[iRow]>1.0e27) upper[iRow]=COIN_DBL_MAX; } if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); modelPtr_->matrix()->appendRows(numrows,rowStarts,columns,element); redoScaleFactors( numrows,rowStarts, columns, element); freeCachedResults1(); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::deleteRows(const int num, const int * rowIndices) { modelPtr_->whatsChanged_ &= (0xffff&~(1|2|4|16|32)); // will still be optimal if all rows basic bool allBasic=true; int numBasis = basis_.getNumArtificial(); for (int i=0;ideleteRows(num,rowIndices); int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; if (num&&nameDiscipline) { // Very clumsy (and inefficient) - need to sort and then go backwards in ? chunks int * indices = CoinCopyOfArray(rowIndices,num); std::sort(indices,indices+num); int num2=num; while(num2) { int next = indices[num2-1]; int firstDelete = num2-1; int i; for (i=num2-2;i>=0;i--) { if (indices[i]+1==next) { next --; firstDelete=i; } else { break; } } OsiSolverInterface::deleteRowNames(indices[firstDelete],num2-firstDelete); num2 = firstDelete; assert (num2>=0); } delete [] indices; } basis_.deleteRows(num,rowIndices); CoinPackedMatrix * saveRowCopy = matrixByRow_; matrixByRow_=NULL; freeCachedResults(); modelPtr_->setNewRowCopy(NULL); delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; if (saveRowCopy) { matrixByRow_=saveRowCopy; matrixByRow_->deleteRows(num,rowIndices); if (matrixByRow_->getNumElements()!=modelPtr_->clpMatrix()->getNumElements()) { delete matrixByRow_; // odd type matrix matrixByRow_=NULL; } } lastAlgorithm_ = saveAlgorithm; if ((specialOptions_&131072)!=0) lastNumberRows_=modelPtr_->numberRows(); } //############################################################################# // Methods to input a problem //############################################################################# void OsiClpSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { modelPtr_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) delete [] integerInformation_; integerInformation_=NULL; modelPtr_->loadProblem(matrix, collb, colub, obj, rowlb, rowub); linearObjective_ = modelPtr_->objective(); freeCachedResults(); basis_=CoinWarmStartBasis(); if (ws_) { delete ws_; ws_ = 0; } } //----------------------------------------------------------------------------- /* Expose the method that takes ClpMatrixBase. User request. Can't hurt, given the number of non-OSI methods already here. */ void OsiClpSolverInterface::loadProblem (const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub) { modelPtr_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) delete [] integerInformation_; integerInformation_=NULL; modelPtr_->loadProblem(matrix,collb,colub,obj,rowlb,rowub); linearObjective_ = modelPtr_->objective(); freeCachedResults(); basis_=CoinWarmStartBasis(); if (ws_) { delete ws_; ws_ = 0; } } //----------------------------------------------------------------------------- void OsiClpSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, double*& rowlb, double*& rowub) { modelPtr_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) loadProblem(*matrix, collb, colub, obj, rowlb, rowub); delete matrix; matrix = NULL; delete[] collb; collb = NULL; delete[] colub; colub = NULL; delete[] obj; obj = NULL; delete[] rowlb; rowlb = NULL; delete[] rowub; rowub = NULL; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::loadProblem(const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const char* rowsen, const double* rowrhs, const double* rowrng) { modelPtr_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) // assert( rowsen != NULL ); // assert( rowrhs != NULL ); // If any of Rhs NULLs then create arrays int numrows = matrix.getNumRows(); const char * rowsenUse = rowsen; if (!rowsen) { char * rowsen = new char [numrows]; for (int i=0;i= 0; --i) { convertSenseToBound(rowsenUse[i],rowrhsUse[i],rowrngUse[i],rowlb[i],rowub[i]); } if (rowsen!=rowsenUse) delete [] rowsenUse; if (rowrhs!=rowrhsUse) delete [] rowrhsUse; if (rowrng!=rowrngUse) delete [] rowrngUse; loadProblem(matrix, collb, colub, obj, rowlb, rowub); delete [] rowlb; delete [] rowub; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::assignProblem(CoinPackedMatrix*& matrix, double*& collb, double*& colub, double*& obj, char*& rowsen, double*& rowrhs, double*& rowrng) { modelPtr_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) loadProblem(*matrix, collb, colub, obj, rowsen, rowrhs, rowrng); delete matrix; matrix = NULL; delete[] collb; collb = NULL; delete[] colub; colub = NULL; delete[] obj; obj = NULL; delete[] rowsen; rowsen = NULL; delete[] rowrhs; rowrhs = NULL; delete[] rowrng; rowrng = NULL; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::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_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) delete [] integerInformation_; integerInformation_=NULL; modelPtr_->loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); linearObjective_ = modelPtr_->objective(); freeCachedResults(); basis_=CoinWarmStartBasis(); if (ws_) { delete ws_; ws_ = 0; } } //----------------------------------------------------------------------------- void OsiClpSolverInterface::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_->whatsChanged_ = 0; // Get rid of integer information (modelPtr will get rid of its copy) // If any of Rhs NULLs then create arrays const char * rowsenUse = rowsen; if (!rowsen) { char * rowsen = new char [numrows]; for (int i=0;i= 0; --i) { convertSenseToBound(rowsenUse[i],rowrhsUse[i],rowrngUse[i],rowlb[i],rowub[i]); } if (rowsen!=rowsenUse) delete [] rowsenUse; if (rowrhs!=rowrhsUse) delete [] rowrhsUse; if (rowrng!=rowrngUse) delete [] rowrngUse; loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub); delete[] rowlb; delete[] rowub; } // This loads a model from a coinModel object - returns number of errors int OsiClpSolverInterface::loadFromCoinModel ( CoinModel & modelObject, bool keepSolution) { modelPtr_->whatsChanged_ = 0; int numberErrors = 0; // Set arrays for normal use double * rowLower = modelObject.rowLowerArray(); double * rowUpper = modelObject.rowUpperArray(); double * columnLower = modelObject.columnLowerArray(); double * columnUpper = modelObject.columnUpperArray(); double * objective = modelObject.objectiveArray(); int * integerType = modelObject.integerTypeArray(); double * associated = modelObject.associatedArray(); // If strings then do copies if (modelObject.stringsExist()) { numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper, objective, integerType,associated); } CoinPackedMatrix matrix; modelObject.createPackedMatrix(matrix,associated); int numberRows = modelObject.numberRows(); int numberColumns = modelObject.numberColumns(); CoinWarmStart * ws = getWarmStart(); bool restoreBasis = keepSolution && numberRows&&numberRows==getNumRows()&& numberColumns==getNumCols(); loadProblem(matrix, columnLower, columnUpper, objective, rowLower, rowUpper); if (restoreBasis) setWarmStart(ws); delete ws; // Do names if wanted int numberItems; numberItems = modelObject.rowNames()->numberItems(); if (numberItems) { const char *const * rowNames=modelObject.rowNames()->names(); modelPtr_->copyRowNames(rowNames,0,numberItems); } numberItems = modelObject.columnNames()->numberItems(); if (numberItems) { const char *const * columnNames=modelObject.columnNames()->names(); modelPtr_->copyColumnNames(columnNames,0,numberItems); } // Do integers if wanted assert(integerType); for (int iColumn=0;iColumnmessage(CLP_BAD_STRING_VALUES,messages_) // <optimizationDirection_ = modelObject.optimizationDirection(); return numberErrors; } //----------------------------------------------------------------------------- // Write mps files //----------------------------------------------------------------------------- void OsiClpSolverInterface::writeMps(const char * filename, const char * extension, double objSense) const { std::string f(filename); std::string e(extension); std::string fullname; if (e!="") { fullname = f + "." + e; } else { // no extension so no trailing period fullname = f; } // get names const char * const * const rowNames = modelPtr_->rowNamesAsChar(); const char * const * const columnNames = modelPtr_->columnNamesAsChar(); // Fall back on Osi version - possibly with names OsiSolverInterface::writeMpsNative(fullname.c_str(), const_cast(rowNames), const_cast(columnNames),0,2,objSense, numberSOS_,setInfo_); if (rowNames) { modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1); modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_); } } int OsiClpSolverInterface::writeMpsNative(const char *filename, const char ** rowNames, const char ** columnNames, int formatType,int numberAcross,double objSense) const { return OsiSolverInterface::writeMpsNative(filename, rowNames, columnNames, formatType, numberAcross,objSense, numberSOS_,setInfo_); } //############################################################################# // CLP specific public interfaces //############################################################################# ClpSimplex * OsiClpSolverInterface::getModelPtr() const { int saveAlgorithm = lastAlgorithm_; //freeCachedResults(); lastAlgorithm_ = saveAlgorithm; //bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0; return modelPtr_; } //------------------------------------------------------------------- //############################################################################# // Constructors, destructors clone and assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiClpSolverInterface::OsiClpSolverInterface () : OsiSolverInterface(), rowsense_(NULL), rhs_(NULL), rowrange_(NULL), ws_(NULL), rowActivity_(NULL), columnActivity_(NULL), numberSOS_(0), setInfo_(NULL), smallModel_(NULL), factorization_(NULL), smallestElementInCut_(1.0e-15), smallestChangeInCut_(1.0e-10), largestAway_(-1.0), spareArrays_(NULL), matrixByRow_(NULL), matrixByRowAtContinuous_(NULL), integerInformation_(NULL), whichRange_(NULL), fakeMinInSimplex_(false), linearObjective_(NULL), cleanupScaling_(0), specialOptions_(0x80000000), baseModel_(NULL), lastNumberRows_(0), continuousModel_(NULL), fakeObjective_(NULL) { //printf("in default %x\n",this); modelPtr_=NULL; notOwned_=false; disasterHandler_ = new OsiClpDisasterHandler(); reset(); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- OsiSolverInterface * OsiClpSolverInterface::clone(bool CopyData) const { //printf("in clone %x\n",this); OsiClpSolverInterface * newSolver; if (CopyData) { newSolver = new OsiClpSolverInterface(*this); } else { newSolver = new OsiClpSolverInterface(); } #if 0 const double * obj = newSolver->getObjCoefficients(); const double * oldObj = getObjCoefficients(); if(newSolver->getNumCols()>3787) printf("%x - obj %x (from %x) val %g\n",newSolver,obj,oldObj,obj[3787]); #endif return newSolver; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiClpSolverInterface::OsiClpSolverInterface ( const OsiClpSolverInterface & rhs) : OsiSolverInterface(rhs), rowsense_(NULL), rhs_(NULL), rowrange_(NULL), ws_(NULL), rowActivity_(NULL), columnActivity_(NULL), stuff_(rhs.stuff_), numberSOS_(rhs.numberSOS_), setInfo_(NULL), smallModel_(NULL), factorization_(NULL), smallestElementInCut_(rhs.smallestElementInCut_), smallestChangeInCut_(rhs.smallestChangeInCut_), largestAway_(-1.0), spareArrays_(NULL), basis_(), itlimOrig_(9999999), lastAlgorithm_(0), notOwned_(false), matrixByRow_(NULL), matrixByRowAtContinuous_(NULL), integerInformation_(NULL), whichRange_(NULL), fakeMinInSimplex_(rhs.fakeMinInSimplex_) { //printf("in copy %x - > %x\n",&rhs,this); if ( rhs.modelPtr_ ) modelPtr_ = new ClpSimplex(*rhs.modelPtr_); else modelPtr_ = new ClpSimplex(); if ( rhs.baseModel_ ) baseModel_ = new ClpSimplex(*rhs.baseModel_); else baseModel_ = NULL; if ( rhs.continuousModel_ ) continuousModel_ = new ClpSimplex(*rhs.continuousModel_); else continuousModel_ = NULL; if (rhs.matrixByRowAtContinuous_) matrixByRowAtContinuous_ = new CoinPackedMatrix(*rhs.matrixByRowAtContinuous_); if ( rhs.disasterHandler_ ) disasterHandler_ = dynamic_cast(rhs.disasterHandler_->clone()); else disasterHandler_ = NULL; if (rhs.fakeObjective_) fakeObjective_ = new ClpLinearObjective(*rhs.fakeObjective_); else fakeObjective_ = NULL; linearObjective_ = modelPtr_->objective(); if ( rhs.ws_ ) ws_ = new CoinWarmStartBasis(*rhs.ws_); basis_ = rhs.basis_; if (rhs.integerInformation_) { int numberColumns = modelPtr_->numberColumns(); integerInformation_ = new char[numberColumns]; CoinMemcpyN(rhs.integerInformation_, numberColumns,integerInformation_); } saveData_ = rhs.saveData_; solveOptions_ = rhs.solveOptions_; cleanupScaling_ = rhs.cleanupScaling_; specialOptions_ = rhs.specialOptions_; lastNumberRows_ = rhs.lastNumberRows_; rowScale_ = rhs.rowScale_; columnScale_ = rhs.columnScale_; fillParamMaps(); messageHandler()->setLogLevel(rhs.messageHandler()->logLevel()); if (numberSOS_) { setInfo_ = new CoinSet[numberSOS_]; for (int i=0;i %x\n",&rhs,this); modelPtr_ = rhs; basis_.resize(modelPtr_->numberRows(),modelPtr_->numberColumns()); linearObjective_ = modelPtr_->objective(); if (rhs) { notOwned_=!reallyOwn; if (rhs->integerInformation()) { int numberColumns = modelPtr_->numberColumns(); integerInformation_ = new char[numberColumns]; CoinMemcpyN(rhs->integerInformation(), numberColumns,integerInformation_); } } fillParamMaps(); } // Releases so won't error void OsiClpSolverInterface::releaseClp() { modelPtr_=NULL; notOwned_=false; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiClpSolverInterface::~OsiClpSolverInterface () { //printf("in destructor %x\n",this); freeCachedResults(); if (!notOwned_) delete modelPtr_; delete baseModel_; delete continuousModel_; delete disasterHandler_; delete fakeObjective_; delete ws_; delete [] rowActivity_; delete [] columnActivity_; delete [] setInfo_; #ifdef KEEP_SMALL if (smallModel_) { delete [] spareArrays_; spareArrays_ = NULL; delete smallModel_; smallModel_=NULL; } #endif assert(smallModel_==NULL); assert(factorization_==NULL); assert(spareArrays_==NULL); delete [] integerInformation_; delete matrixByRowAtContinuous_; delete matrixByRow_; } //------------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiClpSolverInterface & OsiClpSolverInterface::operator=(const OsiClpSolverInterface& rhs) { if (this != &rhs) { //printf("in = %x - > %x\n",&rhs,this); OsiSolverInterface::operator=(rhs); freeCachedResults(); if (!notOwned_) delete modelPtr_; delete ws_; if ( rhs.modelPtr_ ) modelPtr_ = new ClpSimplex(*rhs.modelPtr_); delete baseModel_; if ( rhs.baseModel_ ) baseModel_ = new ClpSimplex(*rhs.baseModel_); else baseModel_ = NULL; delete continuousModel_; if ( rhs.continuousModel_ ) continuousModel_ = new ClpSimplex(*rhs.continuousModel_); else continuousModel_ = NULL; delete matrixByRowAtContinuous_; delete matrixByRow_; matrixByRow_=NULL; if (rhs.matrixByRowAtContinuous_) matrixByRowAtContinuous_ = new CoinPackedMatrix(*rhs.matrixByRowAtContinuous_); else matrixByRowAtContinuous_=NULL; delete disasterHandler_; if ( rhs.disasterHandler_ ) disasterHandler_ = dynamic_cast(rhs.disasterHandler_->clone()); else disasterHandler_ = NULL; delete fakeObjective_; if (rhs.fakeObjective_) fakeObjective_ = new ClpLinearObjective(*rhs.fakeObjective_); else fakeObjective_ = NULL; notOwned_=false; linearObjective_ = modelPtr_->objective(); saveData_ = rhs.saveData_; solveOptions_ = rhs.solveOptions_; cleanupScaling_ = rhs.cleanupScaling_; specialOptions_ = rhs.specialOptions_; lastNumberRows_ = rhs.lastNumberRows_; rowScale_ = rhs.rowScale_; columnScale_ = rhs.columnScale_; basis_ = rhs.basis_; stuff_ = rhs.stuff_; if (rhs.integerInformation_) { int numberColumns = modelPtr_->numberColumns(); integerInformation_ = new char[numberColumns]; CoinMemcpyN(rhs.integerInformation_, numberColumns,integerInformation_); } if ( rhs.ws_ ) ws_ = new CoinWarmStartBasis(*rhs.ws_); else ws_=NULL; delete [] rowActivity_; delete [] columnActivity_; rowActivity_=NULL; columnActivity_=NULL; delete [] setInfo_; numberSOS_ = rhs.numberSOS_; setInfo_=NULL; if (numberSOS_) { setInfo_ = new CoinSet[numberSOS_]; for (int i=0;isetLogLevel(rhs.messageHandler()->logLevel()); } return *this; } //############################################################################# // Applying cuts //############################################################################# void OsiClpSolverInterface::applyRowCut( const OsiRowCut & rowCut ) { 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 OsiClpSolverInterface::applyRowCuts(int numberCuts, const OsiRowCut * cuts) { if (numberCuts) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; // Thanks to js const OsiRowCut * * cutsp = new const OsiRowCut * [numberCuts]; for (int i=0;iwhatsChanged_ &= (0xffff&~(1|2|4|16|32)); CoinPackedMatrix * saveRowCopy = matrixByRow_; matrixByRow_=NULL; #if 0 // was #ifndef NDEBUG int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; assert (!nameDiscipline); #endif freeCachedResults0(); // Say can't gurantee optimal basis etc lastAlgorithm_=999; int numberRows = modelPtr_->numberRows(); modelPtr_->resize(numberRows+numberCuts,modelPtr_->numberColumns()); basis_.resize(numberRows+numberCuts,modelPtr_->numberColumns()); // redo as relaxed - use modelPtr_-> addRows with starts etc int size = 0; for (i=0;irow().getNumElements(); CoinBigIndex * starts = new CoinBigIndex [numberCuts+1]; int * indices = new int[size]; double * elements = new double[size]; double * lower = modelPtr_->rowLower()+numberRows; double * upper = modelPtr_->rowUpper()+numberRows; const double * columnLower = modelPtr_->columnLower(); const double * columnUpper = modelPtr_->columnUpper(); size=0; for (i=0;ilb(); double rowUb = cuts[i]->ub(); int n=cuts[i]->row().getNumElements(); const int * index = cuts[i]->row().getIndices(); const double * elem = cuts[i]->row().getElements(); starts[i]=size; for (int j=0;j=smallestChangeInCut_) { // always take indices[size]=column; elements[size++]=value; } else if (fabs(value)>=smallestElementInCut_) { double lowerValue = columnLower[column]; double upperValue = columnUpper[column]; double difference = upperValue-lowerValue; if (difference<1.0e20&&difference*fabs(value)1.0e20)) { // Take out and adjust to relax //printf("small el %g adjusted\n",value); if (rowLb>-1.0e20) { // just lower bound on row if (value>0.0) { // pretend at upper rowLb -= value*upperValue; } else { // pretend at lower rowLb -= value*lowerValue; } } else { // just upper bound on row if (value>0.0) { // pretend at lower rowUb -= value*lowerValue; } else { // pretend at upper rowUb -= value*upperValue; } } } else { // take (unwillingly) indices[size]=column; elements[size++]=value; } } else { //printf("small el %g ignored\n",value); } } lower[i]= forceIntoRange(rowLb, -OsiClpInfinity, OsiClpInfinity); upper[i]= forceIntoRange(rowUb, -OsiClpInfinity, OsiClpInfinity); if (lower[i]<-1.0e27) lower[i]=-COIN_DBL_MAX; if (upper[i]>1.0e27) upper[i]=COIN_DBL_MAX; } starts[numberCuts]=size; if (!modelPtr_->clpMatrix()) modelPtr_->createEmptyMatrix(); //modelPtr_->matrix()->appendRows(numberCuts,rows); modelPtr_->clpMatrix()->appendMatrix(numberCuts,0,starts,indices,elements); modelPtr_->setNewRowCopy(NULL); modelPtr_->setClpScaledMatrix(NULL); freeCachedResults1(); redoScaleFactors( numberCuts,starts, indices, elements); if (saveRowCopy) { #if 1 matrixByRow_=saveRowCopy; matrixByRow_->appendRows(numberCuts,starts,indices,elements,0); if (matrixByRow_->getNumElements()!=modelPtr_->clpMatrix()->getNumElements()) { delete matrixByRow_; // odd type matrix matrixByRow_=NULL; } #else delete saveRowCopy; #endif } delete [] starts; delete [] indices; delete [] elements; } //############################################################################# // Apply Cuts //############################################################################# OsiSolverInterface::ApplyCutsReturnCode OsiClpSolverInterface::applyCuts( const OsiCuts & cs, double effectivenessLb ) { OsiSolverInterface::ApplyCutsReturnCode retVal; int i; // Loop once for each column cut for ( i=0; inumberRows()-numberAdd; assert (lastNumberRows_==numberRows); // ??? int iRow; int newNumberRows = numberRows + numberAdd; rowScale_.extend(static_cast(2*newNumberRows*sizeof(double))); double * rowScale = rowScale_.array(); double * oldInverseScale = rowScale + lastNumberRows_; double * inverseRowScale = rowScale + newNumberRows; for (iRow=lastNumberRows_-1;iRow>=0;iRow--) inverseRowScale[iRow] = oldInverseScale[iRow] ; //int numberColumns = baseModel_->numberColumns(); const double * columnScale = columnScale_.array(); //const double * inverseColumnScale = columnScale + numberColumns; // Geometric mean on row scales // adjust arrays rowScale += lastNumberRows_; inverseRowScale += lastNumberRows_; for (iRow=0;iRow1.0e-20) { value *= columnScale[iColumn]; largest = CoinMax(largest,value); smallest = CoinMin(smallest,value); } } double scale=sqrt(smallest*largest); scale=CoinMax(1.0e-10,CoinMin(1.0e10,scale)); inverseRowScale[iRow]=scale; rowScale[iRow]=1.0/scale; } lastNumberRows_=newNumberRows; } } // Delete all scale factor stuff and reset option void OsiClpSolverInterface::deleteScaleFactors() { delete baseModel_; baseModel_=NULL; lastNumberRows_=0; specialOptions_ &= ~131072; } //----------------------------------------------------------------------------- void OsiClpSolverInterface::applyColCut( const OsiColCut & cc ) { modelPtr_->whatsChanged_ &= (0x1ffff&~(128|256)); // Say can't gurantee optimal basis etc lastAlgorithm_=999; double * lower = modelPtr_->columnLower(); double * upper = modelPtr_->columnUpper(); const CoinPackedVector & lbs = cc.lbs(); const CoinPackedVector & ubs = cc.ubs(); int i; for ( i=0; i lower[iCol] ) lower[iCol]= value; } for ( i=0; iscaledMatrix_) { delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; } //delete ws_; rowsense_=NULL; rhs_=NULL; rowrange_=NULL; matrixByRow_=NULL; //ws_ = NULL; if (modelPtr_&&modelPtr_->clpMatrix()) { modelPtr_->clpMatrix()->refresh(modelPtr_); // make sure all clean #ifndef NDEBUG ClpPackedMatrix * clpMatrix = dynamic_cast (modelPtr_->clpMatrix()); if (clpMatrix) { if (clpMatrix->getNumCols()) assert (clpMatrix->getNumRows()==modelPtr_->getNumRows()); if (clpMatrix->getNumRows()) assert (clpMatrix->getNumCols()==modelPtr_->getNumCols()); } #endif } } //------------------------------------------------------------------- void OsiClpSolverInterface::freeCachedResults0() const { delete [] rowsense_; delete [] rhs_; delete [] rowrange_; rowsense_=NULL; rhs_=NULL; rowrange_=NULL; } //------------------------------------------------------------------- void OsiClpSolverInterface::freeCachedResults1() const { // Say can't gurantee optimal basis etc lastAlgorithm_=999; delete matrixByRow_; matrixByRow_=NULL; //ws_ = NULL; if (modelPtr_&&modelPtr_->clpMatrix()) { delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; modelPtr_->clpMatrix()->refresh(modelPtr_); // make sure all clean #ifndef NDEBUG ClpPackedMatrix * clpMatrix = dynamic_cast (modelPtr_->clpMatrix()); if (clpMatrix) { assert (clpMatrix->getNumRows()==modelPtr_->getNumRows()); assert (clpMatrix->getNumCols()==modelPtr_->getNumCols()); } #endif } } //------------------------------------------------------------------ void OsiClpSolverInterface::extractSenseRhsRange() const { if (rowsense_ == NULL) { // all three must be NULL assert ((rhs_ == NULL) && (rowrange_ == NULL)); int nr=modelPtr_->numberRows(); if ( nr!=0 ) { rowsense_ = new char[nr]; rhs_ = new double[nr]; rowrange_ = new double[nr]; std::fill(rowrange_,rowrange_+nr,0.0); const double * lb = modelPtr_->rowLower(); const double * ub = modelPtr_->rowUpper(); int i; for ( i=0; inewLanguage(language); OsiSolverInterface::newLanguage(language); } //############################################################################# void OsiClpSolverInterface::fillParamMaps() { assert (static_cast (OsiMaxNumIteration)== static_cast(ClpMaxNumIteration)); assert (static_cast (OsiMaxNumIterationHotStart)==static_cast(ClpMaxNumIterationHotStart)); //assert (static_cast (OsiLastIntParam)== static_cast(ClpLastIntParam)); assert (static_cast (OsiDualObjectiveLimit)== static_cast(ClpDualObjectiveLimit)); assert (static_cast (OsiPrimalObjectiveLimit)==static_cast(ClpPrimalObjectiveLimit)); assert (static_cast (OsiDualTolerance)== static_cast(ClpDualTolerance)); assert (static_cast (OsiPrimalTolerance)== static_cast(ClpPrimalTolerance)); assert (static_cast (OsiObjOffset)== static_cast(ClpObjOffset)); //assert (static_cast (OsiLastDblParam)== static_cast(ClpLastDblParam)); assert (static_cast (OsiProbName)== static_cast (ClpProbName)); //strParamMap_[OsiLastStrParam] = ClpLastStrParam; } // Sets up basis void OsiClpSolverInterface::setBasis ( const CoinWarmStartBasis & basis) { setBasis(basis,modelPtr_); setWarmStart(&basis); } // Warm start CoinWarmStartBasis OsiClpSolverInterface::getBasis(ClpSimplex * model) const { int iRow,iColumn; int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); CoinWarmStartBasis basis; basis.setSize(numberColumns,numberRows); if (model->statusExists()) { // Flip slacks int lookupA[]={0,1,3,2,0,2}; for (iRow=0;iRowgetRowStatus(iRow); iStatus = lookupA[iStatus]; basis.setArtifStatus(iRow,static_cast (iStatus)); } int lookupS[]={0,1,2,3,0,3}; for (iColumn=0;iColumngetColumnStatus(iColumn); iStatus = lookupS[iStatus]; basis.setStructStatus(iColumn,static_cast (iStatus)); } } //basis.print(); return basis; } // Warm start from statusArray CoinWarmStartBasis * OsiClpSolverInterface::getBasis(const unsigned char * statusArray) const { int iRow,iColumn; int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); CoinWarmStartBasis * basis = new CoinWarmStartBasis(); basis->setSize(numberColumns,numberRows); // Flip slacks int lookupA[]={0,1,3,2,0,2}; for (iRow=0;iRowsetArtifStatus(iRow,static_cast (iStatus)); } int lookupS[]={0,1,2,3,0,3}; for (iColumn=0;iColumnsetStructStatus(iColumn,static_cast (iStatus)); } //basis->print(); return basis; } // Sets up basis void OsiClpSolverInterface::setBasis ( const CoinWarmStartBasis & basis, ClpSimplex * model) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; // transform basis to status arrays int iRow,iColumn; int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); if (!model->statusExists()) { /* get status arrays ClpBasis would seem to have overheads and we will need extra bits anyway. */ model->createStatus(); } if (basis.getNumArtificial()!=numberRows|| basis.getNumStructural()!=numberColumns) { CoinWarmStartBasis basis2 = basis; // resize basis2.resize(numberRows,numberColumns); // move status model->createStatus(); // For rows lower and upper are flipped for (iRow=0;iRow1) stat = 5 - stat; // so 2->3 and 3->2 model->setRowStatus(iRow, static_cast (stat)); } for (iColumn=0;iColumnsetColumnStatus(iColumn, static_cast (basis2.getStructStatus(iColumn))); } } else { // move status model->createStatus(); // For rows lower and upper are flipped for (iRow=0;iRow1) stat = 5 - stat; // so 2->3 and 3->2 model->setRowStatus(iRow, static_cast (stat)); } for (iColumn=0;iColumnsetColumnStatus(iColumn, static_cast (basis.getStructStatus(iColumn))); } } } // Warm start difference from basis_ to statusArray CoinWarmStartDiff * OsiClpSolverInterface::getBasisDiff(const unsigned char * statusArray) const { int iRow,iColumn; int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); CoinWarmStartBasis basis; basis.setSize(numberColumns,numberRows); assert (modelPtr_->statusExists()); int lookupS[]={0,1,2,3,0,3}; for (iColumn=0;iColumn (iStatus)); } statusArray += numberColumns; // Flip slacks int lookupA[]={0,1,3,2,0,2}; for (iRow=0;iRow (iStatus)); } // Now basis is what we want while basis_ is old CoinWarmStartDiff * difference = basis.generateDiff(&basis_); return difference; } /* Read an mps file from the given filename - returns number of errors (see CoinMpsIO class) */ int OsiClpSolverInterface::readMps(const char *filename, const char *extension ) { // Get rid of integer stuff delete [] integerInformation_; integerInformation_=NULL; freeCachedResults(); CoinMpsIO m; m.setInfinity(getInfinity()); m.passInMessageHandler(modelPtr_->messageHandler()); *m.messagesPointer()=modelPtr_->coinMessages(); delete [] setInfo_; setInfo_=NULL; numberSOS_=0; CoinSet ** sets=NULL; // Temporarily reduce log level to get CoinMpsIO to shut up. int saveLogLevel = modelPtr_->messageHandler()->logLevel() ; modelPtr_->messageHandler()->setLogLevel(0) ; int numberErrors = m.readMps(filename,extension,numberSOS_,sets); modelPtr_->messageHandler()->setLogLevel(saveLogLevel) ; if (numberSOS_) { setInfo_ = new CoinSet[numberSOS_]; for (int i=0;imessage(COIN_SOLVER_MPS,messages_) <copyInIntegerInformation(integer); } // set objective name setObjName(m.getObjectiveName()); // Always keep names int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; int iRow; std::vector rowNames = std::vector (); std::vector columnNames = std::vector (); rowNames.reserve(nRows); for (iRow=0;iRowcopyNames(rowNames,columnNames); } return numberErrors; } int OsiClpSolverInterface::readMps(const char *filename, const char*extension, int & numberSets, CoinSet ** & sets) { int numberErrors = readMps(filename,extension); numberSets= numberSOS_; sets = &setInfo_; return numberErrors; } /* Read an mps file from the given filename returns number of errors (see OsiMpsReader class) */ int OsiClpSolverInterface::readMps(const char *filename,bool keepNames,bool allowErrors) { // Get rid of integer stuff delete [] integerInformation_; integerInformation_=NULL; freeCachedResults(); CoinMpsIO m; m.setInfinity(getInfinity()); m.passInMessageHandler(modelPtr_->messageHandler()); *m.messagesPointer()=modelPtr_->coinMessages(); m.setSmallElementValue(CoinMax(modelPtr_->getSmallElementValue(), m.getSmallElementValue())); delete [] setInfo_; setInfo_=NULL; numberSOS_=0; CoinSet ** sets=NULL; int numberErrors = m.readMps(filename,"",numberSOS_,sets); if (numberSOS_) { setInfo_ = new CoinSet[numberSOS_]; for (int i=0;imessage(COIN_SOLVER_MPS,messages_) <0&&numberErrors<100000)&&allowErrors)) { // set objective function offest setDblParam(OsiObjOffset,m.objectiveOffset()); // set problem name setStrParam(OsiProbName,m.getProblemName()); // set objective name setObjName(m.getObjectiveName()); // no errors loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(),m.getRowSense(),m.getRightHandSide(), m.getRowRange()); int nCols=m.getNumCols(); // get quadratic part if (m.reader()->whichSection ( ) == COIN_QUAD_SECTION ) { int * start=NULL; int * column = NULL; double * element = NULL; int status=m.readQuadraticMps(NULL,start,column,element,2); if (!status) modelPtr_->loadQuadraticObjective(nCols,start,column,element); delete [] start; delete [] column; delete [] element; } const char * integer = m.integerColumns(); int nRows=m.getNumRows(); if (integer) { int i,n=0; int * index = new int [nCols]; for (i=0;icopyInIntegerInformation(integer); } if (keepNames) { // keep names int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; int iRow; std::vector rowNames = std::vector (); std::vector columnNames = std::vector (); rowNames.reserve(nRows); for (iRow=0;iRowcopyNames(rowNames,columnNames); } } return numberErrors; } // Read file in LP format (with names) int OsiClpSolverInterface::readLp(const char *filename, const double epsilon ) { CoinLpIO m; m.passInMessageHandler(modelPtr_->messageHandler()); *m.messagesPointer()=modelPtr_->coinMessages(); m.readLp(filename, epsilon); freeCachedResults(); // set objective function offest setDblParam(OsiObjOffset, 0); // set problem name setStrParam(OsiProbName, m.getProblemName()); // set objective name setObjName(m.getObjName()); // no errors loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); const char *integer = m.integerColumns(); int nCols = m.getNumCols(); int nRows = m.getNumRows(); if (integer) { int i, n = 0; int *index = new int [nCols]; for (i=0; i rowNames = std::vector (); std::vector columnNames = std::vector (); rowNames.reserve(nRows); for (iRow=0;iRowcopyNames(rowNames,columnNames); return(0); } /* Write the problem into an Lp 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. This version calls writeLpNative with names */ void OsiClpSolverInterface::writeLp(const char *filename, const char *extension , double epsilon , int numberAcross , int decimals , double objSense , bool changeNameOnRange) const { std::string f(filename); std::string e(extension); std::string fullname; if (e!="") { fullname = f + "." + e; } else { // no extension so no trailing period fullname = f; } // get names const char * const * const rowNames = modelPtr_->rowNamesAsChar(); const char * const * const columnNames = modelPtr_->columnNamesAsChar(); // Fall back on Osi version - possibly with names OsiSolverInterface::writeLpNative(fullname.c_str(), rowNames,columnNames, epsilon, numberAcross, decimals, objSense,changeNameOnRange); if (rowNames) { modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1); modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_); } } void OsiClpSolverInterface::writeLp(FILE * fp, double epsilon , int numberAcross , int decimals , double objSense , bool changeNameOnRange) const { // get names const char * const * const rowNames = modelPtr_->rowNamesAsChar(); const char * const * const columnNames = modelPtr_->columnNamesAsChar(); // Fall back on Osi version - possibly with names OsiSolverInterface::writeLpNative(fp, rowNames,columnNames, epsilon, numberAcross, decimals, objSense,changeNameOnRange); if (rowNames) { modelPtr_->deleteNamesAsChar(rowNames, modelPtr_->numberRows_+1); modelPtr_->deleteNamesAsChar(columnNames, modelPtr_->numberColumns_); } } /* I (JJF) am getting incredibly annoyed because I can't just replace a matrix. The default behavior of this is do nothing so only use where that would not matter e.g. strengthening a matrix for MIP */ void OsiClpSolverInterface::replaceMatrixOptional(const CoinPackedMatrix & matrix) { modelPtr_->whatsChanged_ &= (0xffff&~(2|4|8)); replaceMatrix(matrix); } // And if it does matter (not used at present) void OsiClpSolverInterface::replaceMatrix(const CoinPackedMatrix & matrix) { modelPtr_->whatsChanged_ &= (0xffff&~(2|4|8)); delete modelPtr_->matrix_; delete modelPtr_->rowCopy_; modelPtr_->rowCopy_=NULL; if (matrix.isColOrdered()) { modelPtr_->matrix_=new ClpPackedMatrix(matrix); } else { CoinPackedMatrix matrix2; matrix2.setExtraGap(0.0); matrix2.setExtraMajor(0.0); matrix2.reverseOrderedCopyOf(matrix); modelPtr_->matrix_=new ClpPackedMatrix(matrix2); } modelPtr_->matrix_->setDimensions(modelPtr_->numberRows_,modelPtr_->numberColumns_); freeCachedResults(); } // Get pointer to array[getNumCols()] of primal solution vector const double * OsiClpSolverInterface::getColSolution() const { if (modelPtr_->solveType()!=2) { return modelPtr_->primalColumnSolution(); } else { // simplex interface return modelPtr_->solutionRegion(1); } } // Get pointer to array[getNumRows()] of dual prices const double * OsiClpSolverInterface::getRowPrice() const { if (modelPtr_->solveType()!=2) { return modelPtr_->dualRowSolution(); } else { // simplex interface //return modelPtr_->djRegion(0); return modelPtr_->dualRowSolution(); } } // Get a pointer to array[getNumCols()] of reduced costs const double * OsiClpSolverInterface::getReducedCost() const { if (modelPtr_->solveType()!=2) { return modelPtr_->dualColumnSolution(); } else { // simplex interface return modelPtr_->djRegion(1); } } /* Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector */ const double * OsiClpSolverInterface::getRowActivity() const { if (modelPtr_->solveType()!=2) { return modelPtr_->primalRowSolution(); } else { // simplex interface return modelPtr_->solutionRegion(0); } } double OsiClpSolverInterface::getObjValue() const { if (modelPtr_->numberIterations()||modelPtr_->upperIn_!=-COIN_DBL_MAX) { // This does not pass unitTest when getObjValue is called before solve. //printf("obj a %g %g\n",modelPtr_->objectiveValue(), // OsiSolverInterface::getObjValue()); if (fakeMinInSimplex_) return -modelPtr_->objectiveValue() ; else return modelPtr_->objectiveValue(); } else { return OsiSolverInterface::getObjValue(); } } /* Set an objective function coefficient */ void OsiClpSolverInterface::setObjCoeff( int elementIndex, double elementValue ) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (elementIndex<0||elementIndex>=n) { indexError(elementIndex,"setObjCoeff"); } #endif modelPtr_->setObjectiveCoefficient(elementIndex, ((fakeMinInSimplex_)?-elementValue:elementValue)); } /* Set a single column lower bound
Use -DBL_MAX for -infinity. */ void OsiClpSolverInterface::setColLower( int index, double elementValue ) { modelPtr_->whatsChanged_ &= 0x1ffff; #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (index<0||index>=n) { indexError(index,"setColLower"); } #endif double currentValue = modelPtr_->columnActivity_[index]; bool changed=(currentValueprimalTolerance()|| index>=basis_.getNumStructural()|| basis_.getStructStatus(index)==CoinWarmStartBasis::atLowerBound); // Say can't gurantee optimal basis etc if (changed) lastAlgorithm_=999; if (!modelPtr_->lower_) modelPtr_->whatsChanged_ &= ~0xffff; // switch off modelPtr_->setColumnLower(index,elementValue); } /* Set a single column upper bound
Use DBL_MAX for infinity. */ void OsiClpSolverInterface::setColUpper( int index, double elementValue ) { modelPtr_->whatsChanged_ &= 0x1ffff; #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (index<0||index>=n) { indexError(index,"setColUpper"); } #endif double currentValue = modelPtr_->columnActivity_[index]; bool changed=(currentValue>elementValue+modelPtr_->primalTolerance()|| index>=basis_.getNumStructural()|| basis_.getStructStatus(index)==CoinWarmStartBasis::atUpperBound); // Say can't gurantee optimal basis etc if (changed) lastAlgorithm_=999; if (!modelPtr_->upper_) modelPtr_->whatsChanged_ &= ~0xffff; // switch off modelPtr_->setColumnUpper(index,elementValue); } /* Set a single column lower and upper bound */ void OsiClpSolverInterface::setColBounds( int elementIndex, double lower, double upper ) { modelPtr_->whatsChanged_ &= 0x1ffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberColumns(); if (elementIndex<0||elementIndex>=n) { indexError(elementIndex,"setColBounds"); } #endif if (!modelPtr_->lower_) modelPtr_->whatsChanged_ &= ~0xffff; // switch off modelPtr_->setColumnBounds(elementIndex,lower,upper); } void OsiClpSolverInterface::setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { modelPtr_->whatsChanged_ &= 0x1ffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberColumns(); const int * indexFirst2=indexFirst; while (indexFirst2 != indexLast) { const int iColumn=*indexFirst2++; if (iColumn<0||iColumn>=n) { indexError(iColumn,"setColSetBounds"); } } #endif modelPtr_->setColSetBounds(indexFirst,indexLast,boundList); } //------------------------------------------------------------------ /* Set a single row lower bound
Use -DBL_MAX for -infinity. */ void OsiClpSolverInterface::setRowLower( int elementIndex, double elementValue ) { // Say can't gurantee optimal basis etc lastAlgorithm_=999; modelPtr_->whatsChanged_ &= 0xffff; #ifndef NDEBUG int n = modelPtr_->numberRows(); if (elementIndex<0||elementIndex>=n) { indexError(elementIndex,"setRowLower"); } #endif modelPtr_->setRowLower(elementIndex , elementValue); if (rowsense_!=NULL) { assert ((rhs_ != NULL) && (rowrange_ != NULL)); convertBoundToSense(modelPtr_->rowLower_[elementIndex], modelPtr_->rowUpper_[elementIndex], rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]); } } /* Set a single row upper bound
Use DBL_MAX for infinity. */ void OsiClpSolverInterface::setRowUpper( int elementIndex, double elementValue ) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't guarantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberRows(); if (elementIndex<0||elementIndex>=n) { indexError(elementIndex,"setRowUpper"); } #endif modelPtr_->setRowUpper(elementIndex , elementValue); if (rowsense_!=NULL) { assert ((rhs_ != NULL) && (rowrange_ != NULL)); convertBoundToSense(modelPtr_->rowLower_[elementIndex], modelPtr_->rowUpper_[elementIndex], rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]); } } /* Set a single row lower and upper bound */ void OsiClpSolverInterface::setRowBounds( int elementIndex, double lower, double upper ) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberRows(); if (elementIndex<0||elementIndex>=n) { indexError(elementIndex,"setRowBounds"); } #endif modelPtr_->setRowBounds(elementIndex,lower,upper); if (rowsense_!=NULL) { assert ((rhs_ != NULL) && (rowrange_ != NULL)); convertBoundToSense(modelPtr_->rowLower_[elementIndex], modelPtr_->rowUpper_[elementIndex], rowsense_[elementIndex], rhs_[elementIndex], rowrange_[elementIndex]); } } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setRowType(int i, char sense, double rightHandSide, double range) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberRows(); if (i<0||i>=n) { indexError(i,"setRowType"); } #endif double lower = 0, upper = 0; convertSenseToBound(sense, rightHandSide, range, lower, upper); setRowBounds(i, lower, upper); // If user is using sense then set if (rowsense_) { rowsense_[i] = sense; rhs_[i] = rightHandSide; rowrange_[i] = range; } } // Set name of row void //OsiClpSolverInterface::setRowName(int rowIndex, std::string & name) OsiClpSolverInterface::setRowName(int rowIndex, std::string name) { if (rowIndex>=0&&rowIndexnumberRows()) { int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; if (nameDiscipline) { modelPtr_->setRowName(rowIndex,name); OsiSolverInterface::setRowName(rowIndex,name) ; } } } // Return name of row if one exists or Rnnnnnnn // we ignore maxLen std::string OsiClpSolverInterface::getRowName(int rowIndex, unsigned int /*maxLen*/) const { if (rowIndex == getNumRows()) return getObjName(); int useNames; getIntParam (OsiNameDiscipline,useNames); if (useNames) return modelPtr_->getRowName(rowIndex); else return dfltRowColName('r',rowIndex); } // Set name of col void //OsiClpSolverInterface::setColName(int colIndex, std::string & name) OsiClpSolverInterface::setColName(int colIndex, std::string name) { if (colIndex>=0&&colIndexnumberColumns()) { int nameDiscipline; getIntParam(OsiNameDiscipline,nameDiscipline) ; if (nameDiscipline) { modelPtr_->setColumnName(colIndex,name); OsiSolverInterface::setColName(colIndex,name) ; } } } // Return name of col if one exists or Rnnnnnnn std::string OsiClpSolverInterface::getColName(int colIndex, unsigned int /*maxLen*/) const { int useNames; getIntParam (OsiNameDiscipline,useNames); if (useNames) return modelPtr_->getColumnName(colIndex); else return dfltRowColName('c',colIndex); } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberRows(); const int * indexFirst2=indexFirst; while (indexFirst2 != indexLast) { const int iColumn=*indexFirst2++; if (iColumn<0||iColumn>=n) { indexError(iColumn,"setColumnSetBounds"); } } #endif modelPtr_->setRowSetBounds(indexFirst,indexLast,boundList); if (rowsense_ != NULL) { assert ((rhs_ != NULL) && (rowrange_ != NULL)); double * lower = modelPtr_->rowLower(); double * upper = modelPtr_->rowUpper(); while (indexFirst != indexLast) { const int iRow=*indexFirst++; convertBoundToSense(lower[iRow], upper[iRow], rowsense_[iRow], rhs_[iRow], rowrange_[iRow]); } } } //----------------------------------------------------------------------------- void OsiClpSolverInterface::setRowSetTypes(const int* indexFirst, const int* indexLast, const char* senseList, const double* rhsList, const double* rangeList) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; #ifndef NDEBUG int n = modelPtr_->numberRows(); #endif const int len = static_cast(indexLast - indexFirst); while (indexFirst != indexLast) { const int iRow= *indexFirst++; #ifndef NDEBUG if (iRow<0||iRow>=n) { indexError(iRow,"isContinuous"); } #endif double lowerValue = 0; double upperValue = 0; if (rangeList){ convertSenseToBound(*senseList++, *rhsList++, *rangeList++, lowerValue, upperValue); } else { convertSenseToBound(*senseList++, *rhsList++, 0, lowerValue, upperValue); } modelPtr_->setRowBounds(iRow,lowerValue,upperValue); } if (rowsense_ != NULL) { assert ((rhs_ != NULL) && (rowrange_ != NULL)); indexFirst -= len; senseList -= len; rhsList -= len; if (rangeList) rangeList -= len; while (indexFirst != indexLast) { const int iRow=*indexFirst++; rowsense_[iRow] = *senseList++; rhs_[iRow] = *rhsList++; if (rangeList) rowrange_[iRow] = *rangeList++; } } } /* Clp's copy-in/copy-out design paradigm is a challenge for the simplex modes. Normal operation goes like this: * startup() loads clp's work arrays, performing scaling for numerical stability and compensating for max. * clp solves the problem * finish() unloads the work arrays into answer arrays, undoing scaling and max compensation. There are two solutions: undo scaling and max on demand, or make them into noops. The various getBInv* methods undo scaling on demand (but see special option 512) and do not need to worry about max. Other get solution methods are not coded to do this, so the second approach is used. For simplex modes, turn off scaling (necessary for both primal and dual solutions) and temporarily convert max to min (necessary for dual solution). This makes the unscaling in getBInv* superfluous, but don't remove it. Arguably the better solution here would be to go through and add unscaling and max compensation to the get solution methods. Look for fakeMinInSimplex to see the places this propagates to. TODO: setRowPrice never has worked properly, and I didn't try to fix it in this go-round. As of 100907, change applied to [enable|disable]Factorization (mode 1). Limitation of [enable|disable]SimplexInterface (mode 2) noted in documentation. -- lh, 100907 -- */ /* Enables normal operation of subsequent functions. This method is supposed to ensure that all typical things (like reduced costs, etc.) are updated when individual pivots are executed and can be queried by other methods */ void OsiClpSolverInterface::enableSimplexInterface(bool doingPrimal) { modelPtr_->whatsChanged_ &= 0xffff; if (modelPtr_->solveType()==2) return; assert (modelPtr_->solveType()==1); int saveIts = modelPtr_->numberIterations_; modelPtr_->setSolveType(2); if (doingPrimal) modelPtr_->setAlgorithm(1); else modelPtr_->setAlgorithm(-1); // Do initialization saveData_ = modelPtr_->saveData(); saveData_.scalingFlag_=modelPtr_->scalingFlag(); modelPtr_->scaling(0); specialOptions_ = 0x80000000; // set infeasibility cost up modelPtr_->setInfeasibilityCost(1.0e12); ClpDualRowDantzig dantzig; modelPtr_->setDualRowPivotAlgorithm(dantzig); ClpPrimalColumnDantzig dantzigP; dantzigP.saveWeights(modelPtr_,0); // set modelPtr modelPtr_->setPrimalColumnPivotAlgorithm(dantzigP); int saveOptions = modelPtr_->specialOptions_; modelPtr_->specialOptions_ &= ~262144; delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; // make sure using standard factorization modelPtr_->factorization()->forceOtherFactorization(4); #ifdef NDEBUG modelPtr_->startup(0); #else int returnCode=modelPtr_->startup(0); assert (!returnCode||returnCode==2); #endif modelPtr_->specialOptions_=saveOptions; modelPtr_->numberIterations_=saveIts; } //Undo whatever setting changes the above method had to make void OsiClpSolverInterface::disableSimplexInterface() { modelPtr_->whatsChanged_ &= 0xffff; assert (modelPtr_->solveType()==2); // declare optimality anyway (for message handler) modelPtr_->setProblemStatus(0); modelPtr_->setSolveType(1); // message will not appear anyway int saveMessageLevel=modelPtr_->messageHandler()->logLevel(); modelPtr_->messageHandler()->setLogLevel(0); modelPtr_->finish(); modelPtr_->messageHandler()->setLogLevel(saveMessageLevel); modelPtr_->restoreData(saveData_); modelPtr_->scaling(saveData_.scalingFlag_); ClpDualRowSteepest steepest; modelPtr_->setDualRowPivotAlgorithm(steepest); ClpPrimalColumnSteepest steepestP; modelPtr_->setPrimalColumnPivotAlgorithm(steepestP); basis_ = getBasis(modelPtr_); modelPtr_->setSolveType(1); } /* Force scaling off. If the client thinks we're maximising, arrange it so that clp sees minimisation while the client still sees maximisation. In keeping with the spirit of the getBInv methods, special option 512 will leave all work to the client. */ void OsiClpSolverInterface::enableFactorization() const { saveData_.specialOptions_=specialOptions_; // Try to preserve work regions, reuse factorization if ((specialOptions_&(1+8))!=1+8) setSpecialOptionsMutable((1+8)|specialOptions_); // Are we allowed to make the output sensible to mere mortals? if ((specialOptions_&512)==0) { // Force scaling to off saveData_.scalingFlag_ = modelPtr_->scalingFlag() ; modelPtr_->scaling(0) ; // Temporarily force to min but keep a copy of original objective. if (getObjSense() < 0.0) { fakeMinInSimplex_ = true ; modelPtr_->setOptimizationDirection(1.0) ; double *c = modelPtr_->objective() ; int n = getNumCols() ; linearObjective_ = new double[n] ; CoinMemcpyN(c,n,linearObjective_) ; std::transform(c,c+n,c,std::negate()) ; } } int saveStatus = modelPtr_->problemStatus_; #ifdef NDEBUG modelPtr_->startup(0); #else int returnCode=modelPtr_->startup(0); assert (!returnCode||returnCode==2); #endif modelPtr_->problemStatus_=saveStatus; } /* Undo enableFactorization. Retrieve the special options and scaling and remove the temporary objective used to fake minimisation in clp. */ void OsiClpSolverInterface::disableFactorization() const { specialOptions_=saveData_.specialOptions_; // declare optimality anyway (for message handler) modelPtr_->setProblemStatus(0); // message will not appear anyway int saveMessageLevel=modelPtr_->messageHandler()->logLevel(); modelPtr_->messageHandler()->setLogLevel(0); modelPtr_->finish(); modelPtr_->messageHandler()->setLogLevel(saveMessageLevel); // Client asked for transforms on the way in, so back out. if ((specialOptions_&512)==0) { modelPtr_->scaling(saveData_.scalingFlag_) ; if (fakeMinInSimplex_ == true) { fakeMinInSimplex_ = false ; modelPtr_->setOptimizationDirection(-1.0) ; double *c = modelPtr_->objective() ; int n = getNumCols() ; std::transform(c,c+n,c,std::negate()) ; delete[] linearObjective_ ; } } } /* The following two methods may be replaced by the methods of OsiSolverInterface using OsiWarmStartBasis if: 1. OsiWarmStartBasis resize operation is implemented more efficiently and 2. It is ensured that effects on the solver are the same Returns a basis status of the structural/artificial variables */ void OsiClpSolverInterface::getBasisStatus(int* cstat, int* rstat) const { int iRow,iColumn; int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const double * pi = modelPtr_->dualRowSolution(); const double * dj = modelPtr_->dualColumnSolution(); double multiplier = modelPtr_->optimizationDirection(); // Flip slacks int lookupA[]={0,1,3,2,0,3}; for (iRow=0;iRowgetRowStatus(iRow); if (iStatus==5) { // Fixed - look at reduced cost if (pi[iRow]*multiplier>1.0e-7) iStatus = 3; } iStatus = lookupA[iStatus]; rstat[iRow]=iStatus; } int lookupS[]={0,1,2,3,0,3}; for (iColumn=0;iColumngetColumnStatus(iColumn); if (iStatus==5) { // Fixed - look at reduced cost if (dj[iColumn]*multiplier<-1.0e-7) iStatus = 2; } iStatus = lookupS[iStatus]; cstat[iColumn]=iStatus; } } //Set the status of structural/artificial variables //Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ... int OsiClpSolverInterface::setBasisStatus(const int* cstat, const int* rstat) { modelPtr_->whatsChanged_ &= 0xffff; // Say can't gurantee optimal basis etc lastAlgorithm_=999; modelPtr_->createStatus(); int i, n; double * lower, * upper, * solution; n=modelPtr_->numberRows(); lower = modelPtr_->rowLower(); upper = modelPtr_->rowUpper(); solution = modelPtr_->primalRowSolution(); // For rows lower and upper are flipped int lookupA[]={0,1,3,2}; for (i=0;i3) status = 3; if (lower[i]<-1.0e50&&upper[i]>1.0e50&&status!=1) status = 0; // set free if should be else if (lower[i]<-1.0e50&&status==3) status = 2; // can't be at lower bound else if (upper[i]>1.0e50&&status==2) status = 3; // can't be at upper bound switch (status) { // free or superbasic case 0: if (lower[i]<-1.0e50&&upper[i]>1.0e50) { modelPtr_->setRowStatus(i,ClpSimplex::isFree); if (fabs(solution[i])>1.0e20) solution[i]=0.0; } else { modelPtr_->setRowStatus(i,ClpSimplex::superBasic); if (fabs(solution[i])>1.0e20) solution[i]=0.0; } break; case 1: // basic modelPtr_->setRowStatus(i,ClpSimplex::basic); break; case 2: // at upper bound solution[i]=upper[i]; if (upper[i]>lower[i]) modelPtr_->setRowStatus(i,ClpSimplex::atUpperBound); else modelPtr_->setRowStatus(i,ClpSimplex::isFixed); break; case 3: // at lower bound solution[i]=lower[i]; if (upper[i]>lower[i]) modelPtr_->setRowStatus(i,ClpSimplex::atLowerBound); else modelPtr_->setRowStatus(i,ClpSimplex::isFixed); break; } } n=modelPtr_->numberColumns(); lower = modelPtr_->columnLower(); upper = modelPtr_->columnUpper(); solution = modelPtr_->primalColumnSolution(); for (i=0;i3) status = 3; if (lower[i]<-1.0e50&&upper[i]>1.0e50&&status!=1) status = 0; // set free if should be else if (lower[i]<-1.0e50&&status==3) status = 2; // can't be at lower bound else if (upper[i]>1.0e50&&status==2) status = 3; // can't be at upper bound switch (status) { // free or superbasic case 0: if (lower[i]<-1.0e50&&upper[i]>1.0e50) { modelPtr_->setColumnStatus(i,ClpSimplex::isFree); if (fabs(solution[i])>1.0e20) solution[i]=0.0; } else { modelPtr_->setColumnStatus(i,ClpSimplex::superBasic); if (fabs(solution[i])>1.0e20) solution[i]=0.0; } break; case 1: // basic modelPtr_->setColumnStatus(i,ClpSimplex::basic); break; case 2: // at upper bound solution[i]=upper[i]; if (upper[i]>lower[i]) modelPtr_->setColumnStatus(i,ClpSimplex::atUpperBound); else modelPtr_->setColumnStatus(i,ClpSimplex::isFixed); break; case 3: // at lower bound solution[i]=lower[i]; if (upper[i]>lower[i]) modelPtr_->setColumnStatus(i,ClpSimplex::atLowerBound); else modelPtr_->setColumnStatus(i,ClpSimplex::isFixed); break; } } // say first time modelPtr_->statusOfProblem(true); // May be bad model if (modelPtr_->status()==4) return 1; // Save basis_ = getBasis(modelPtr_); return 0; } /* Perform a pivot by substituting a colIn for colOut in the basis. The status of the leaving variable is given in statOut. Where 1 is to upper bound, -1 to lower bound Return code is 0 for okay, 1 if inaccuracy forced re-factorization (should be okay) and -1 for singular factorization */ int OsiClpSolverInterface::pivot(int colIn, int colOut, int outStatus) { assert (modelPtr_->solveType()==2); // convert to Clp style (what about flips?) if (colIn<0) colIn = modelPtr_->numberColumns()+(-1-colIn); if (colOut<0) colOut = modelPtr_->numberColumns()+(-1-colOut); // in clp direction of out is reversed outStatus = - outStatus; // set in clp modelPtr_->setDirectionOut(outStatus); modelPtr_->setSequenceIn(colIn); modelPtr_->setSequenceOut(colOut); // do pivot return modelPtr_->pivot(); } /* Obtain a result of the primal pivot Outputs: colOut -- leaving column, outStatus -- its status, t -- step size, and, if dx!=NULL, *dx -- primal ray direction. Inputs: colIn -- entering column, sign -- direction of its change (+/-1). Both for colIn and colOut, artificial variables are index by the negative of the row index minus 1. Return code (for now): 0 -- leaving variable found, -1 -- everything else? Clearly, more informative set of return values is required Primal and dual solutions are updated */ int OsiClpSolverInterface::primalPivotResult(int colIn, int sign, int& colOut, int& outStatus, double& t, CoinPackedVector* dx) { assert (modelPtr_->solveType()==2); // convert to Clp style if (colIn<0) colIn = modelPtr_->numberColumns()+(-1-colIn); // set in clp modelPtr_->setDirectionIn(sign); modelPtr_->setSequenceIn(colIn); modelPtr_->setSequenceOut(-1); int returnCode = modelPtr_->primalPivotResult(); t = modelPtr_->theta(); int numberColumns = modelPtr_->numberColumns(); if (dx) { double * ray = modelPtr_->unboundedRay(); if (ray) dx->setFullNonZero(numberColumns,ray); else printf("No ray?\n"); delete [] ray; } outStatus = - modelPtr_->directionOut(); colOut = modelPtr_->sequenceOut(); if (colOut>= numberColumns) colOut = -1-(colOut - numberColumns); return returnCode; } /* Obtain a result of the dual pivot (similar to the previous method) Differences: entering variable and a sign of its change are now the outputs, the leaving variable and its statuts -- the inputs If dx!=NULL, then *dx contains dual ray Return code: same */ int OsiClpSolverInterface::dualPivotResult(int& /*colIn*/, int& /*sign*/, int /*colOut*/, int /*outStatus*/, double& /*t*/, CoinPackedVector* /*dx*/) { assert (modelPtr_->solveType()==2); abort(); return 0; } /* This method should not leave a permanent change in the solver. For this reason, save a copy of the cost region and replace it after we've calculated the duals and reduced costs. On the good side, if we're maximising, we should negate the objective on the way in and negate the duals on the way out. Since clp won't be doing anything more with c, we can exploit (-1)(-1) = 1 and do nothing. */ void OsiClpSolverInterface::getReducedGradient( double* columnReducedCosts, double * duals, const double * c) const { //assert (modelPtr_->solveType()==2); // could do this faster with coding inside Clp // save current costs int numberColumns = modelPtr_->numberColumns(); double * save = new double [numberColumns]; double * obj = modelPtr_->costRegion(); CoinMemcpyN(obj,numberColumns,save); // Compute new duals and reduced costs. const double * columnScale = modelPtr_->columnScale(); if (!columnScale) { CoinMemcpyN(c,numberColumns,obj) ; } else { // need to scale for (int i=0;icomputeDuals(NULL); // Restore previous cost vector CoinMemcpyN(save,numberColumns,obj); delete [] save; // Transfer results to parameters int numberRows = modelPtr_->numberRows(); const double * dualScaled = modelPtr_->dualRowSolution(); const double * djScaled = modelPtr_->djRegion(1); if (!columnScale) { CoinMemcpyN(dualScaled,numberRows,duals) ; CoinMemcpyN(djScaled,numberColumns,columnReducedCosts) ; } else { // need to scale const double * rowScale = modelPtr_->rowScale(); for (int i=0;iwhatsChanged_ &= (0xffff&~(64)); assert (modelPtr_->solveType()==2); int numberColumns = modelPtr_->numberColumns(); CoinMemcpyN(c,numberColumns,modelPtr_->objective()); if (modelPtr_->nonLinearCost()) { modelPtr_->nonLinearCost()->refreshCosts(c); } CoinMemcpyN(c,numberColumns,modelPtr_->costRegion()); modelPtr_->computeDuals(NULL); } #endif //Get a row of the tableau (slack part in slack if not NULL) void OsiClpSolverInterface::getBInvARow(int row, double* z, double * slack) const { #ifndef NDEBUG int n = modelPtr_->numberRows(); if (row<0||row>=n) { indexError(row,"getBInvARow"); } #endif //assert (modelPtr_->solveType()==2||(specialOptions_&1)); CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1); CoinIndexedVector * columnArray0 = modelPtr_->columnArray(0); CoinIndexedVector * columnArray1 = modelPtr_->columnArray(1); rowArray0->clear(); rowArray1->clear(); columnArray0->clear(); columnArray1->clear(); int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); // put +1 in row // But swap if pivot variable was slack as clp stores slack as -1.0 const int * pivotVariable = modelPtr_->pivotVariable(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); int pivot = pivotVariable[row]; double value; // And if scaled then adjust if (!rowScale) { if (pivotinsert(row,value); modelPtr_->factorization()->updateColumnTranspose(rowArray0,rowArray1); // put row of tableau in rowArray1 and columnArray0 modelPtr_->clpMatrix()->transposeTimes(modelPtr_,1.0, rowArray1,columnArray1,columnArray0); // If user is sophisticated then let her/him do work if ((specialOptions_&512)==0) { // otherwise copy and clear if (!rowScale) { CoinMemcpyN(columnArray0->denseVector(),numberColumns,z); } else { double * array = columnArray0->denseVector(); for (int i=0;idenseVector(),numberRows,slack); } else { double * array = rowArray1->denseVector(); for (int i=0;iclear(); rowArray1->clear(); } // don't need to clear everything always, but doesn't cost rowArray0->clear(); columnArray1->clear(); } //Get a row of the tableau (slack part in slack if not NULL) void OsiClpSolverInterface::getBInvARow(int row, CoinIndexedVector * columnArray0, CoinIndexedVector * slack, bool keepScaled) const { #ifndef NDEBUG int nx = modelPtr_->numberRows(); if (row<0||row>=nx) { indexError(row,"getBInvARow"); } #endif //assert (modelPtr_->solveType()==2||(specialOptions_&1)); CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); CoinIndexedVector * rowArray1 = slack ? slack : modelPtr_->rowArray(1); CoinIndexedVector * columnArray1 = modelPtr_->columnArray(1); rowArray0->clear(); rowArray1->clear(); columnArray0->clear(); columnArray1->clear(); //int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); // put +1 in row // But swap if pivot variable was slack as clp stores slack as -1.0 const int * pivotVariable = modelPtr_->pivotVariable(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); int pivot = pivotVariable[row]; double value; // And if scaled then adjust if (!rowScale) { if (pivotinsert(row,value); modelPtr_->factorization()->updateColumnTranspose(rowArray0,rowArray1); // put row of tableau in rowArray1 and columnArray0 modelPtr_->clpMatrix()->transposeTimes(modelPtr_,1.0, rowArray1,columnArray1,columnArray0); int n; const int * which; double * array; // deal with scaling etc if (rowScale&&!keepScaled) { int j; // First columns n = columnArray0->getNumElements(); which = columnArray0->getIndices(); array = columnArray0->denseVector(); for (j=0; j < n; j++) { int k=which[j]; array[k] /= columnScale[k]; } if (slack) { n = slack->getNumElements(); which = slack->getIndices(); array = slack->denseVector(); for(j=0; j < n; j++) { int k=which[j]; array[k] *= rowScale[k]; } } } if (!slack) rowArray1->clear(); } //Get a row of the basis inverse void OsiClpSolverInterface::getBInvRow(int row, double* z) const { #ifndef NDEBUG int n = modelPtr_->numberRows(); if (row<0||row>=n) { indexError(row,"getBInvRow"); } #endif //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0); ClpFactorization * factorization = modelPtr_->factorization(); CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1); rowArray0->clear(); rowArray1->clear(); // put +1 in row // But swap if pivot variable was slack as clp stores slack as -1.0 double value = (modelPtr_->pivotVariable()[row]numberColumns()) ? 1.0 : -1.0; int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); const int * pivotVariable = modelPtr_->pivotVariable(); // but scale if (rowScale) { int pivot = pivotVariable[row]; if (pivotinsert(row,value); factorization->updateColumnTranspose(rowArray0,rowArray1); // If user is sophisticated then let her/him do work if ((specialOptions_&512)==0) { // otherwise copy and clear if (!rowScale) { CoinMemcpyN(rowArray1->denseVector(),modelPtr_->numberRows(),z); } else { double * array = rowArray1->denseVector(); for (int i=0;iclear(); } } //Get a column of the tableau void OsiClpSolverInterface::getBInvACol(int col, double* vec) const { //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0); CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1); rowArray0->clear(); rowArray1->clear(); // get column of matrix #ifndef NDEBUG int n = modelPtr_->numberColumns()+modelPtr_->numberRows(); if (col<0||col>=n) { indexError(col,"getBInvACol"); } #endif int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const int * pivotVariable = modelPtr_->pivotVariable(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); if (!rowScale) { if (colunpack(rowArray1,col); } else { rowArray1->insert(col-numberColumns,1.0); } } else { if (colunpack(rowArray1,col); double multiplier = 1.0/columnScale[col]; int number = rowArray1->getNumElements(); int * index = rowArray1->getIndices(); double * array = rowArray1->denseVector(); for (int i=0;iinsert(col-numberColumns,rowScale[col-numberColumns]); } } modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false); // If user is sophisticated then let her/him do work if ((specialOptions_&512)==0) { // otherwise copy and clear // But swap if pivot variable was slack as clp stores slack as -1.0 double * array = rowArray1->denseVector(); if (!rowScale) { for (int i=0;iclear(); } } //Get a column of the tableau void OsiClpSolverInterface::getBInvACol(int col, CoinIndexedVector * rowArray1) const { CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); rowArray0->clear(); rowArray1->clear(); // get column of matrix #ifndef NDEBUG int nx = modelPtr_->numberColumns()+modelPtr_->numberRows(); if (col<0||col>=nx) { indexError(col,"getBInvACol"); } #endif //int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const int * pivotVariable = modelPtr_->pivotVariable(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); if (!rowScale) { if (colunpack(rowArray1,col); } else { rowArray1->insert(col-numberColumns,1.0); } } else { if (colunpack(rowArray1,col); double multiplier = 1.0/columnScale[col]; int number = rowArray1->getNumElements(); int * index = rowArray1->getIndices(); double * array = rowArray1->denseVector(); for (int i=0;iinsert(col-numberColumns,rowScale[col-numberColumns]); } } modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false); // Deal with stuff int n = rowArray1->getNumElements(); const int * which = rowArray1->getIndices(); double * array = rowArray1->denseVector(); for(int j=0; j < n; j++){ int k=which[j]; // need to know pivot variable for +1/-1 (slack) and row/column scaling int pivot = pivotVariable[k]; if (pivotrowArray(0); rowArray0->clear(); // get column of matrix //int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const int * pivotVariable = modelPtr_->pivotVariable(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); // rowArray1 is not a column - so column scale can't be applied before modelPtr_->factorization()->updateColumn(rowArray0,rowArray1,false); // Deal with stuff int n = rowArray1->getNumElements(); const int * which = rowArray1->getIndices(); double * array = rowArray1->denseVector(); for(int j=0; j < n; j++){ int k=which[j]; // need to know pivot variable for +1/-1 (slack) and row/column scaling int pivot = pivotVariable[k]; if (pivotsolveType()==2||(specialOptions_&1)!=0); ClpFactorization * factorization = modelPtr_->factorization(); CoinIndexedVector * rowArray0 = modelPtr_->rowArray(0); CoinIndexedVector * rowArray1 = modelPtr_->rowArray(1); rowArray0->clear(); rowArray1->clear(); #ifndef NDEBUG int n = modelPtr_->numberRows(); if (col<0||col>=n) { indexError(col,"getBInvCol"); } #endif // put +1 in row int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); const double * rowScale = modelPtr_->rowScale(); const double * columnScale = modelPtr_->columnScale(); const int * pivotVariable = modelPtr_->pivotVariable(); // but scale double value; if (!rowScale) { value=1.0; } else { value = rowScale[col]; } rowArray1->insert(col,value); factorization->updateColumn(rowArray0,rowArray1,false); // If user is sophisticated then let her/him do work if ((specialOptions_&512)==0) { // otherwise copy and clear // But swap if pivot variable was slack as clp stores slack as -1.0 double * array = rowArray1->denseVector(); if (!rowScale) { for (int i=0;iclear(); } } /* Get basic indices (order of indices corresponds to the order of elements in a vector returned by getBInvACol() and getBInvCol()). */ void OsiClpSolverInterface::getBasics(int* index) const { //assert (modelPtr_->solveType()==2||(specialOptions_&1)!=0); assert (index); if (modelPtr_->pivotVariable()) { CoinMemcpyN(modelPtr_->pivotVariable(),modelPtr_->numberRows(),index); } else { std::cerr<<"getBasics is only available with enableSimplexInterface." <problemStatus_); } // Resets as if default constructor void OsiClpSolverInterface::reset() { setInitialData(); // clear base class freeCachedResults(); if (!notOwned_) delete modelPtr_; delete ws_; ws_ = NULL; delete [] rowActivity_; delete [] columnActivity_; assert(smallModel_==NULL); assert(factorization_==NULL); smallestElementInCut_ = 1.0e-15; smallestChangeInCut_ = 1.0e-10; largestAway_ = -1.0; assert(spareArrays_==NULL); delete [] integerInformation_; rowActivity_ = NULL; columnActivity_ = NULL; integerInformation_ = NULL; basis_ = CoinWarmStartBasis(); itlimOrig_=9999999; lastAlgorithm_=0; notOwned_=false; modelPtr_ = new ClpSimplex(); linearObjective_ = NULL; fillParamMaps(); } // Set a hint parameter bool OsiClpSolverInterface::setHintParam(OsiHintParam key, bool yesNo, OsiHintStrength strength, void * otherInformation) { if ( OsiSolverInterface::setHintParam(key,yesNo,strength,otherInformation)) { // special coding for branch and cut if (yesNo&&strength == OsiHintDo&&key==OsiDoInBranchAndCut) { if ( specialOptions_==0x80000000) { setupForRepeatedUse(0,0); specialOptions_=0; } // set normal specialOptions_ &= (2047|3*8192|15*65536|2097152|4194304); if (otherInformation!=NULL) { int * array = static_cast (otherInformation); if (array[0]>=0||array[0]<=2) specialOptions_ |= array[0]<<10; } } // Printing if (key==OsiDoReducePrint) { handler_->setLogLevel(yesNo ? 0 : 1); } return true; } else { return false; } } // Crunch down model void OsiClpSolverInterface::crunch() { //if (modelPtr_->scalingFlag_>0&&!modelPtr_->rowScale_&& // modelPtr_->rowCopy_) { //printf("BBBB could crunch2\n"); //} int numberColumns = modelPtr_->numberColumns(); int numberRows = modelPtr_->numberRows(); int totalIterations=0; bool abortSearch=false; // Use dual region double * rhs = modelPtr_->dualRowSolution(); // Get space for strong branching int size = static_cast((1+4*(numberRows+numberColumns))*sizeof(double)); // and for save of original column bounds size += static_cast(2*numberColumns*sizeof(double)); size += static_cast((1+4*numberRows+2*numberColumns)*sizeof(int)); size += numberRows+numberColumns; #ifdef KEEP_SMALL char * spareArrays = NULL; if(!(modelPtr_->whatsChanged_&0x30000)) { delete smallModel_; smallModel_ = NULL; delete [] spareArrays_; spareArrays_ = NULL; } if (!spareArrays_) { spareArrays = new char[size]; //memset(spareArrays,0x20,size); } else { spareArrays = spareArrays_; } double * arrayD = reinterpret_cast (spareArrays); double * saveSolution = arrayD+1; double * saveLower = saveSolution + (numberRows+numberColumns); double * saveUpper = saveLower + (numberRows+numberColumns); double * saveObjective = saveUpper + (numberRows+numberColumns); double * saveLowerOriginal = saveObjective + (numberRows+numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; double * lowerOriginal = modelPtr_->columnLower(); double * upperOriginal = modelPtr_->columnUpper(); int * savePivot = reinterpret_cast (saveUpperOriginal + numberColumns); int * whichRow = savePivot+numberRows; int * whichColumn = whichRow + 3*numberRows; int * arrayI = whichColumn + 2*numberColumns; if (spareArrays_) { assert (smallModel_); int nSame=0; int nSub=0; for (int i=0;i1.0e-30); double up = upperOriginal[i]; double upOld = saveUpperOriginal[i]; if (lo>=loOld&&up<=upOld) { if (lo==loOld&&up==upOld) { nSame++; } else { nSub++; //if (!isInteger(i)) //nSub+=10; } } } //printf("%d bounds same, %d interior, %d bad\n", // nSame,nSub,numberColumns-nSame-nSub); if (nSame0) { delete smallModel_; smallModel_=NULL; } else { // we can fix up (but should we if large number fixed?) assert (smallModel_); double * lowerSmall = smallModel_->columnLower(); double * upperSmall = smallModel_->columnUpper(); int numberColumns2 = smallModel_->numberColumns(); for (int i=0;i (modelPtr_)->crunch(rhs,whichRow,whichColumn, nBound,moreBounds,tightenBounds); #ifndef NDEBUG int nCopy = 3*numberRows+2*numberColumns; for (int i=0;i=-CoinMax(numberRows,numberColumns)&&whichRow[i]whatsChanged_&0x30000)); //delete [] spareArrays_; //spareArrays_ = NULL; assert (spareArrays_); int nCopy = 3*numberRows+2*numberColumns; nBound = whichRow[nCopy]; #ifndef NDEBUG for (int i=0;i=-CoinMax(numberRows,numberColumns)&&whichRow[i]status_; int nr1=modelPtr_->numberRows_; int nc1=modelPtr_->numberColumns_; unsigned char * stat2=smallModel_->status_; int nr2=smallModel_->numberRows_; int nc2=smallModel_->numberColumns_; int n=0; for (int i=0;icolumnLower_; //const double * up1=modelPtr_->columnUpper_; //const double * lo2=smallModel_->columnLower_; //const double * up2=smallModel_->columnUpper_; int nBad=0; for (int i=0;i (modelPtr_)->crunch(rhs,whichRow,whichColumn, nBound,moreBounds,tightenBounds); #endif bool inCbcOrOther = (modelPtr_->specialOptions()&0x03000000)!=0; if (small) { small->specialOptions_ |= 262144; if ((specialOptions_&131072)!=0) { assert (lastNumberRows_>=0); int numberRows2 = small->numberRows(); int numberColumns2 = small->numberColumns(); double * rowScale2 = new double [2*numberRows2]; assert (rowScale_.getSize()>=2*numberRows); const double * rowScale = rowScale_.array(); double * inverseScale2 = rowScale2+numberRows2; const double * inverseScale = rowScale+modelPtr_->numberRows_; int i; for (i=0;i=0&&iRowsetRowScale(rowScale2); double * columnScale2 = new double [2*numberColumns2]; assert (columnScale_.getSize()>=2*numberColumns); const double * columnScale = columnScale_.array(); inverseScale2 = columnScale2+numberColumns2; inverseScale = columnScale+modelPtr_->numberColumns_; for (i=0;isetColumnScale(columnScale2); } disasterHandler_->setOsiModel(this); if (inCbcOrOther) { disasterHandler_->setSimplex(small); disasterHandler_->setWhereFrom(1); // crunch small->setDisasterHandler(disasterHandler_); } #if 0 const double * obj =small->objective(); int numberColumns2 = small->numberColumns(); int iColumn; for (iColumn=0;iColumndual(); else small->primal(); // No objective - use primal! #else small->moreSpecialOptions_ = modelPtr_->moreSpecialOptions_; small->dual(0,7); #endif modelPtr_->secondaryStatus_=0; totalIterations += small->numberIterations(); int problemStatus = small->problemStatus(); if (problemStatus>=0&&problemStatus<=2) { modelPtr_->setProblemStatus(problemStatus); if (!inCbcOrOther||!problemStatus) { // Scaling may have changed - if so pass across if (modelPtr_->scalingFlag()==4) modelPtr_->scaling(small->scalingFlag()); static_cast (modelPtr_)->afterCrunch(*small,whichRow,whichColumn,nBound); if ((specialOptions_&1048576)==0) { // get correct rays if (problemStatus==2) modelPtr_->primal(1); else if (problemStatus==1) modelPtr_->dual(); } else { delete [] modelPtr_->ray_; modelPtr_->ray_=NULL; if (problemStatus==1&&small->ray_) { // get ray to full problem int numberRows = modelPtr_->numberRows(); int numberRows2 = small->numberRows(); double * ray = new double [numberRows]; memset(ray,0,numberRows*sizeof(double)); for (int i = 0; i < numberRows2; i++) { int iRow = whichRow[i]; ray[iRow] = small->ray_[i]; } // Column copy of matrix const double * element = getMatrixByCol()->getElements(); const int * row = getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = getMatrixByCol()->getVectorStarts(); const int * columnLength = getMatrixByCol()->getVectorLengths(); // translate //pivotRow=whichRow[pivotRow]; //modelPtr_->spareIntArray_[3]=pivotRow; int pivotRow=-1; for (int jRow = nBound; jRow < 2 * numberRows; jRow++) { int iRow = whichRow[jRow]; int iColumn = whichRow[jRow+numberRows]; if (modelPtr_->getColumnStatus(iColumn) == ClpSimplex::basic) { double value = 0.0; double sum = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (iRow == row[j]) { value = element[j]; } else { sum += ray[row[j]]*element[j]; } } if (iRow!=pivotRow) { ray[iRow] = -sum / value; } else { printf("what now - direction %d wanted %g sum %g value %g\n", small->directionOut_,ray[iRow], sum,value); } } } for (int i=0;inumberColumns_;i++) { if (modelPtr_->getStatus(i)!=ClpSimplex::basic&& modelPtr_->columnLower_[i]==modelPtr_->columnUpper_[i]) modelPtr_->setStatus(i,ClpSimplex::isFixed); } modelPtr_->ray_=ray; modelPtr_->directionOut_=small->directionOut_; } } } #ifdef KEEP_SMALL //assert (!smallModel_); //smallModel_ = small; small=NULL; int nCopy = 3*numberRows+2*numberColumns; //int * copy = CoinCopyOfArrayPartial(whichRow,nCopy+1,nCopy); whichRow[nCopy]=nBound; assert (arrayI[0]==nBound); arrayI[0]=nBound; // same spareArrays_ = spareArrays; spareArrays=NULL; #endif } else if (problemStatus!=3) { modelPtr_->setProblemStatus(1); } else { if (problemStatus==3) { if (!inCbcOrOther) { // Calling code not Cbc - may want information from larger model static_cast (modelPtr_)->afterCrunch(*small,whichRow,whichColumn,nBound); // but may not be able to trust objective as lower bound if (small->algorithm_==1/*||small->sumDualInfeasibilities_>1.0e-5*/) modelPtr_->secondaryStatus_=10; } // may be problems if (inCbcOrOther&&disasterHandler_->inTrouble()) { if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // in case scaling bad small->setRowScale(NULL); small->setColumnScale(NULL); // try just going back in disasterHandler_->setPhase(1); small->dual(); totalIterations += small->numberIterations(); if (disasterHandler_->inTrouble()) { if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } // try primal on original model disasterHandler_->setPhase(2); disasterHandler_->setOsiModel(this); modelPtr_->setDisasterHandler(disasterHandler_); modelPtr_->primal(); totalIterations += modelPtr_->numberIterations(); if(disasterHandler_->inTrouble()) { #ifdef COIN_DEVELOP printf("disaster crunch - treat as infeasible\n"); #endif if (disasterHandler_->typeOfDisaster()) { // We want to abort abortSearch=true; goto disaster; } modelPtr_->setProblemStatus(1); } // give up for now modelPtr_->setDisasterHandler(NULL); } else { modelPtr_->setProblemStatus(small->problemStatus()); } } else { small->computeObjectiveValue(); modelPtr_->setObjectiveValue(small->objectiveValue()); modelPtr_->setProblemStatus(3); } } else { modelPtr_->setProblemStatus(3); } } disaster: delete small; #ifdef KEEP_SMALL if (small==smallModel_) { smallModel_ = NULL; delete [] spareArrays_; spareArrays_ = NULL; spareArrays = NULL; } #endif } else { modelPtr_->setProblemStatus(1); #ifdef KEEP_SMALL delete [] spareArrays_; spareArrays_ = NULL; spareArrays = NULL; #endif } modelPtr_->setNumberIterations(totalIterations); if (abortSearch) { lastAlgorithm_=-911; modelPtr_->setProblemStatus(4); } #ifdef KEEP_SMALL delete [] spareArrays; #else delete [] whichRow; #endif } // Synchronize model void OsiClpSolverInterface::synchronizeModel() { if ((specialOptions_ &128)!=0) { if (!modelPtr_->rowScale_&&(specialOptions_&131072)!=0) { assert (lastNumberRows_==modelPtr_->numberRows_); int numberRows = modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); double * rowScale = CoinCopyOfArray(rowScale_.array(),2*numberRows); modelPtr_->setRowScale(rowScale); double * columnScale = CoinCopyOfArray(columnScale_.array(),2*numberColumns); modelPtr_->setColumnScale(columnScale); modelPtr_->setRowScale(NULL); modelPtr_->setColumnScale(NULL); } } } // Returns true if has OsiSimplex methods /* Returns 1 if can just do getBInv etc 2 if has all OsiSimplex methods and 0 if it has none */ int OsiClpSolverInterface::canDoSimplexInterface() const { return 2; } // Pass in sos stuff from AMPl void OsiClpSolverInterface::setSOSData(int numberSOS,const char * type, const int * start,const int * indices, const double * weights) { delete [] setInfo_; setInfo_=NULL; numberSOS_=numberSOS; if (numberSOS_) { setInfo_ = new CoinSet[numberSOS_]; for (int i=0;i(oldObject[iObject]) ; if (obj) numberSOS++; } if (numberSOS_&&!numberSOS) { // make a large enough array for new objects nObjects = numberObjects_; numberObjects_=numberSOS_+nObjects; if (numberObjects_) object_ = new OsiObject * [numberObjects_]; else object_=NULL; // copy CoinMemcpyN(oldObject,nObjects,object_); // Delete old array (just array) delete [] oldObject; for (int i=0;inumberEntries(),set->which(),set->weights(), set->setType()); } } else if (!numberSOS_&&numberSOS) { // create Coin sets assert (!setInfo_); setInfo_ = new CoinSet[numberSOS]; for (iObject = 0;iObject(oldObject[iObject]) ; if (obj) setInfo_[numberSOS_++]=CoinSosSet(obj->numberMembers(),obj->members(),obj->weights(),obj->sosType()); } } else if (numberSOS!=numberSOS_) { printf("mismatch on SOS\n"); } return numberSOS_; } // below needed for pathetic branch and bound code #include #include // Trivial class for Branch and Bound class OsiNodeSimple { public: // Default Constructor OsiNodeSimple (); // Constructor from current state (and list of integers) // Also chooses branching variable (if none set to -1) OsiNodeSimple (OsiSolverInterface &model, int numberIntegers, int * integer, CoinWarmStart * basis); void gutsOfConstructor (OsiSolverInterface &model, int numberIntegers, int * integer, CoinWarmStart * basis); // Copy constructor OsiNodeSimple ( const OsiNodeSimple &); // Assignment operator OsiNodeSimple & operator=( const OsiNodeSimple& rhs); // Destructor ~OsiNodeSimple (); // Work of destructor void gutsOfDestructor(); // Extension - true if other extension of this bool extension(const OsiNodeSimple & other, const double * originalLower, const double * originalUpper) const; inline void incrementDescendants() { descendants_++;} // Public data // Basis (should use tree, but not as wasteful as bounds!) CoinWarmStart * basis_; // Objective value (COIN_DBL_MAX) if spare node double objectiveValue_; // Branching variable (0 is first integer) int variable_; // Way to branch - -1 down (first), 1 up, -2 down (second), 2 up (second) int way_; // Number of integers (for length of arrays) int numberIntegers_; // Current value double value_; // Number of descendant nodes (so 2 is in interior) int descendants_; // Parent int parent_; // Previous in chain int previous_; // Next in chain int next_; // Now I must use tree // Bounds stored in full (for integers) int * lower_; int * upper_; }; OsiNodeSimple::OsiNodeSimple() : basis_(NULL), objectiveValue_(COIN_DBL_MAX), variable_(-100), way_(-1), numberIntegers_(0), value_(0.5), descendants_(-1), parent_(-1), previous_(-1), next_(-1), lower_(NULL), upper_(NULL) { } OsiNodeSimple::OsiNodeSimple(OsiSolverInterface & model, int numberIntegers, int * integer,CoinWarmStart * basis) { gutsOfConstructor(model,numberIntegers,integer,basis); } void OsiNodeSimple::gutsOfConstructor(OsiSolverInterface & model, int numberIntegers, int * integer,CoinWarmStart * basis) { basis_ = basis; variable_=-1; way_=-1; numberIntegers_=numberIntegers; value_=0.0; descendants_ = 0; parent_ = -1; previous_ = -1; next_ = -1; if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) { objectiveValue_ = model.getObjSense()*model.getObjValue(); } else { objectiveValue_ = 1.0e100; lower_ = NULL; upper_ = NULL; return; // node cutoff } lower_ = new int [numberIntegers_]; upper_ = new int [numberIntegers_]; assert (upper_!=NULL); const double * lower = model.getColLower(); const double * upper = model.getColUpper(); const double * solution = model.getColSolution(); int i; // Hard coded integer tolerance #define INTEGER_TOLERANCE 1.0e-6 ///////// Start of Strong branching code - can be ignored // Number of strong branching candidates #define STRONG_BRANCHING 5 #ifdef STRONG_BRANCHING double upMovement[STRONG_BRANCHING]; double downMovement[STRONG_BRANCHING]; double solutionValue[STRONG_BRANCHING]; int chosen[STRONG_BRANCHING]; int iSmallest=0; // initialize distance from integer for (i=0;i(lower[iColumn]); upper_[i]=static_cast(upper[iColumn]); double value = solution[iColumn]; value = CoinMax(value,static_cast (lower_[i])); value = CoinMin(value,static_cast (upper_[i])); double nearest = floor(value+0.5); if (fabs(value-nearest)>INTEGER_TOLERANCE) numberAway++; if (fabs(value-nearest)>mostAway) { double away = fabs(value-nearest); if (away>upMovement[iSmallest]) { //add to list upMovement[iSmallest]=away; solutionValue[iSmallest]=value; chosen[iSmallest]=i; int j; iSmallest=-1; double smallest = 1.0; for (j=0;j=0) { numberStrong ++; variable_ = chosen[i]; } } // out strong branching if bit set OsiClpSolverInterface* clp = dynamic_cast(&model); if (clp&&(clp->specialOptions()&16)!=0&&numberStrong>1) { int j; int iBest=-1; double best = 0.0; for (j=0;jbest) { best=upMovement[j]; iBest=j; } } numberStrong=1; variable_=chosen[iBest]; } if (numberStrong==1) { // just one - makes it easy int iColumn = integer[variable_]; double value = solution[iColumn]; value = CoinMax(value,static_cast (lower_[variable_])); value = CoinMin(value,static_cast (upper_[variable_])); double nearest = floor(value+0.5); value_=value; if (value<=nearest) way_=1; // up else way_=-1; // down } else if (numberStrong) { // more than one - choose bool chooseOne=true; model.markHotStart(); for (i=0;i=0) { int iColumn = integer[iInt]; double value = solutionValue[i]; // value of variable in original double objectiveChange; value = CoinMax(value,static_cast (lower_[iInt])); value = CoinMin(value,static_cast (upper_[iInt])); // try down model.setColUpper(iColumn,floor(value)); model.solveFromHotStart(); model.setColUpper(iColumn,upper_[iInt]); if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) { objectiveChange = model.getObjSense()*model.getObjValue() - objectiveValue_; } else { objectiveChange = 1.0e100; } assert (objectiveChange>-1.0e-5); objectiveChange = CoinMax(objectiveChange,0.0); downMovement[i]=objectiveChange; // try up model.setColLower(iColumn,ceil(value)); model.solveFromHotStart(); model.setColLower(iColumn,lower_[iInt]); if (model.isProvenOptimal()&&!model.isDualObjectiveLimitReached()) { objectiveChange = model.getObjSense()*model.getObjValue() - objectiveValue_; } else { objectiveChange = 1.0e100; } assert (objectiveChange>-1.0e-5); objectiveChange = CoinMax(objectiveChange,0.0); upMovement[i]=objectiveChange; /* Possibilities are: Both sides feasible - store Neither side feasible - set objective high and exit One side feasible - change bounds and resolve */ bool solveAgain=false; if (upMovement[i]<1.0e100) { if(downMovement[i]<1.0e100) { // feasible - no action } else { // up feasible, down infeasible solveAgain = true; model.setColLower(iColumn,ceil(value)); } } else { if(downMovement[i]<1.0e100) { // down feasible, up infeasible solveAgain = true; model.setColUpper(iColumn,floor(value)); } else { // neither side feasible objectiveValue_=1.0e100; chooseOne=false; break; } } if (solveAgain) { // need to solve problem again - signal this variable_ = numberIntegers; chooseOne=false; break; } } } if (chooseOne) { // choose the one that makes most difference both ways double best = -1.0; double best2 = -1.0; for (i=0;i=0) { //std::cout<<"Strong branching on " // <best) { // smaller is better better=true; } else if (CoinMin(upMovement[i],downMovement[i])>best-1.0e-5) { if (CoinMax(upMovement[i],downMovement[i])>best2+1.0e-5) { // smaller is about same, but larger is better better=true; } } if (better) { best = CoinMin(upMovement[i],downMovement[i]); best2 = CoinMax(upMovement[i],downMovement[i]); variable_ = iInt; double value = solutionValue[i]; value = CoinMax(value,static_cast (lower_[variable_])); value = CoinMin(value,static_cast (upper_[variable_])); value_=value; if (upMovement[i]<=downMovement[i]) way_=1; // up else way_=-1; // down } } } } // Delete the snapshot model.unmarkHotStart(); } ////// End of Strong branching #else variable_=-1; // This has hard coded integer tolerance double mostAway=INTEGER_TOLERANCE; int numberAway=0; for (i=0;i(lower[iColumn]); upper_[i]=static_cast(upper[iColumn]); double value = solution[iColumn]; value = CoinMax(value,(double) lower_[i]); value = CoinMin(value,(double) upper_[i]); double nearest = floor(value+0.5); if (fabs(value-nearest)>INTEGER_TOLERANCE) numberAway++; if (fabs(value-nearest)>mostAway) { mostAway=fabs(value-nearest); variable_=i; value_=value; if (value<=nearest) way_=1; // up else way_=-1; // down } } #endif } OsiNodeSimple::OsiNodeSimple(const OsiNodeSimple & rhs) { if (rhs.basis_) basis_=rhs.basis_->clone(); else basis_ = NULL; objectiveValue_=rhs.objectiveValue_; variable_=rhs.variable_; way_=rhs.way_; numberIntegers_=rhs.numberIntegers_; value_=rhs.value_; descendants_ = rhs.descendants_; parent_ = rhs.parent_; previous_ = rhs.previous_; next_ = rhs.next_; lower_=NULL; upper_=NULL; if (rhs.lower_!=NULL) { lower_ = new int [numberIntegers_]; upper_ = new int [numberIntegers_]; assert (upper_!=NULL); CoinMemcpyN(rhs.lower_,numberIntegers_,lower_); CoinMemcpyN(rhs.upper_,numberIntegers_,upper_); } } OsiNodeSimple & OsiNodeSimple::operator=(const OsiNodeSimple & rhs) { if (this != &rhs) { gutsOfDestructor(); if (rhs.basis_) basis_=rhs.basis_->clone(); objectiveValue_=rhs.objectiveValue_; variable_=rhs.variable_; way_=rhs.way_; numberIntegers_=rhs.numberIntegers_; value_=rhs.value_; descendants_ = rhs.descendants_; parent_ = rhs.parent_; previous_ = rhs.previous_; next_ = rhs.next_; if (rhs.lower_!=NULL) { lower_ = new int [numberIntegers_]; upper_ = new int [numberIntegers_]; assert (upper_!=NULL); CoinMemcpyN(rhs.lower_,numberIntegers_,lower_); CoinMemcpyN(rhs.upper_,numberIntegers_,upper_); } } return *this; } OsiNodeSimple::~OsiNodeSimple () { gutsOfDestructor(); } // Work of destructor void OsiNodeSimple::gutsOfDestructor() { delete [] lower_; delete [] upper_; delete basis_; lower_ = NULL; upper_ = NULL; basis_ = NULL; objectiveValue_ = COIN_DBL_MAX; } // Extension - true if other extension of this bool OsiNodeSimple::extension(const OsiNodeSimple & other, const double * originalLower, const double * originalUpper) const { bool ok=true; for (int i=0;ioriginalLower[i]) { if (other.upper_[i]>upper_[i]|| other.lower_[i] #define FUNNY_BRANCHING 1 #define FUNNY_TREE #ifndef FUNNY_TREE // Vector of OsiNodeSimples typedef std::vector OsiVectorNode; #else // Must code up by hand class OsiVectorNode { public: // Default Constructor OsiVectorNode (); // Copy constructor OsiVectorNode ( const OsiVectorNode &); // Assignment operator OsiVectorNode & operator=( const OsiVectorNode& rhs); // Destructor ~OsiVectorNode (); // Size inline int size() const { return size_-sizeDeferred_;} // Push void push_back(const OsiNodeSimple & node); // Last one in (or other criterion) OsiNodeSimple back() const; // Get rid of last one void pop_back(); // Works out best one int best() const; // Public data // Maximum size int maximumSize_; // Current size int size_; // Number still hanging around int sizeDeferred_; // First spare int firstSpare_; // First int first_; // Last int last_; // Chosen one mutable int chosen_; // Nodes OsiNodeSimple * nodes_; }; OsiVectorNode::OsiVectorNode() : maximumSize_(10), size_(0), sizeDeferred_(0), firstSpare_(0), first_(-1), last_(-1) { nodes_ = new OsiNodeSimple[maximumSize_]; for (int i=0;i=0) { assert (nodes_[last_].next_==-1); nodes_[last_].next_=firstSpare_; } nodes_[firstSpare_].previous_=last_; nodes_[firstSpare_].next_=-1; if (last_==-1) { assert (first_==-1); first_ = firstSpare_; } last_=firstSpare_; if (next>=0&&next=0); } #endif } return chosen_; } // Last one in (or other criterion) OsiNodeSimple OsiVectorNode::back() const { assert (last_>=0); return nodes_[best()]; } // Get rid of last one void OsiVectorNode::pop_back() { // Temporary until more sophisticated //assert (last_==chosen_); if (nodes_[chosen_].descendants_==2) sizeDeferred_--; int previous = nodes_[chosen_].previous_; int next = nodes_[chosen_].next_; nodes_[chosen_].gutsOfDestructor(); if (previous>=0) { nodes_[previous].next_=next; } else { first_ = next; } if (next>=0) { nodes_[next].previous_ = previous; } else { last_ = previous; } nodes_[chosen_].previous_=-1; if (firstSpare_>=0) { nodes_[chosen_].next_ = firstSpare_; } else { nodes_[chosen_].next_ = -1; } firstSpare_ = chosen_; chosen_ = -1; assert (size_>0); size_--; } #endif // Invoke solver's built-in enumeration algorithm void OsiClpSolverInterface::branchAndBound() { double time1 = CoinCpuTime(); // solve LP initialSolve(); int funnyBranching=FUNNY_BRANCHING; if (isProvenOptimal()&&!isDualObjectiveLimitReached()) { // Continuous is feasible - find integers int numberIntegers=0; int numberColumns = getNumCols(); int iColumn; int i; for (iColumn=0;iColumn (lower[iColumn]); if (upper[iColumn]>1.0e9) { // This is not meant to be a bulletproof code setColUpper(iColumn,1.0e9); } originalUpper[numberIntegers]=static_cast (upper[iColumn]); which[numberIntegers++]=iColumn; } } } double direction = getObjSense(); // empty tree OsiVectorNode branchingTree; // Add continuous to it; OsiNodeSimple rootNode(*this,numberIntegers,which,getWarmStart()); // something extra may have been fixed by strong branching // if so go round again while (rootNode.variable_==numberIntegers) { resolve(); rootNode = OsiNodeSimple(*this,numberIntegers,which,getWarmStart()); } if (rootNode.objectiveValue_<1.0e100) { // push on stack branchingTree.push_back(rootNode); } // For printing totals int numberIterations=0; int numberNodes =0; int nRedundantUp=0; int nRedundantDown=0; int nRedundantUp2=0; int nRedundantDown2=0; OsiNodeSimple bestNode; ////// Start main while of branch and bound // while until nothing on stack while (branchingTree.size()) { // last node OsiNodeSimple node = branchingTree.back(); int kNode = branchingTree.chosen_; branchingTree.pop_back(); assert (node.descendants_<2); numberNodes++; if (node.variable_>=0) { // branch - do bounds for (i=0;i(ws); assert (wsb!=NULL); // make sure not volume numberIterations += getIterationCount(); // fix on reduced costs int nFixed0=0,nFixed1=0; double cutoff; getDblParam(OsiDualObjectiveLimit,cutoff); double gap=(cutoff-modelPtr_->objectiveValue())*direction+1.0e-4; if (gap<1.0e10&&isProvenOptimal()&&!isDualObjectiveLimitReached()) { const double * dj = getReducedCost(); const double * lower = getColLower(); const double * upper = getColUpper(); for (i=0;ilower[iColumn]) { double djValue = dj[iColumn]*direction; if (wsb->getStructStatus(iColumn)==CoinWarmStartBasis::atLowerBound&& djValue>gap) { nFixed0++; setColUpper(iColumn,lower[iColumn]); } else if (wsb->getStructStatus(iColumn)==CoinWarmStartBasis::atUpperBound&& -djValue>gap) { nFixed1++; setColLower(iColumn,upper[iColumn]); } } } //if (nFixed0+nFixed1) //printf("%d fixed to lower, %d fixed to upper\n",nFixed0,nFixed1); } if (!isIterationLimitReached()) { if (isProvenOptimal()&&!isDualObjectiveLimitReached()) { #if FUNNY_BRANCHING // See if branched variable off bounds const double * dj = getReducedCost(); const double * lower = getColLower(); const double * upper = getColUpper(); const double * solution = getColSolution(); // Better to use "natural" value - need flag to say fixed for (i=0;i1.0e-6) { // wants to go down if (lower[iColumn]>originalLower[i]) { // Lower bound active relaxedLower[i]=static_cast (lower[iColumn]); } if (upper[iColumn]originalLower[i]) { // Lower bound NOT active } if (upper[iColumn] (upper[iColumn]); } } } // See if can do anything { /* If kNode is on second branch then a) If other feasible could free up as well b) If other infeasible could do something clever. For now - we have to give up */ int jNode=branchingTree.nodes_[kNode].parent_; bool canDelete = (branchingTree.nodes_[kNode].descendants_<2); while (jNode>=0) { OsiNodeSimple & node = branchingTree.nodes_[jNode]; int next = node.parent_; if (node.descendants_<2) { int variable = node.variable_; iColumn=which[variable]; double value = node.value_; double djValue = dj[iColumn]*direction; assert (node.way_==2||node.way_==-2); // we don't know which branch it was - look at current bounds if (upper[iColumn]1.0e-3||solution[iColumn]=0) { OsiNodeSimple & node2 = branchingTree.nodes_[next]; newUpper = node2.upper_[variable]; } if (branchingTree.nodes_[jNode].parent_!=next) assert (newUpper>upper[iColumn]); setColUpper(iColumn,newUpper); int kNode2=next; int jNode2=branchingTree.nodes_[kNode].parent_; assert (newUpper>branchingTree.nodes_[kNode].upper_[variable]); branchingTree.nodes_[kNode].upper_[variable]= newUpper; while (jNode2!=kNode2) { OsiNodeSimple & node2 = branchingTree.nodes_[jNode2]; int next = node2.parent_; if (next!=kNode2) assert (newUpper>node2.upper_[variable]); node2.upper_[variable]= newUpper; jNode2=next; } } else { // can't delete but can add other way to jNode nRedundantDown2++; OsiNodeSimple & node2 = branchingTree.nodes_[kNode]; assert (node2.way_==2||node2.way_==-2); double value2 = node2.value_; int variable2 = node2.variable_; int iColumn2 = which[variable2]; if (variable != variable2) { if (node2.way_==2&&upper[iColumn2] (floor(value2)); assert (newUppervalue2) { // must have been up branch which was done - carry over int newLower = static_cast (ceil(value2)); assert (newLower>node.lower_[variable2]); node.lower_[variable2]=newLower; } if (node.lower_[variable2]>node.upper_[variable2]) { // infeasible node.descendants_=2; // ignore branchingTree.sizeDeferred_++; } } } break; } // we don't know which branch it was - look at current bounds } else if (lower[iColumn]>value&&node.upper_[variable]>lower[iColumn]) { // must have been up branch if (djValue<-1.0e-3||solution[iColumn]>lower[iColumn]+1.0e-5) { if (canDelete) { nRedundantUp++; #if 1 printf("%d redundant branch up with value %g current lower %g solution %g dj %g\n", variable,node.value_,lower[iColumn],solution[iColumn],djValue); #endif node.descendants_=2; // ignore branchingTree.sizeDeferred_++; int newLower = originalLower[variable]; if (next>=0) { OsiNodeSimple & node2 = branchingTree.nodes_[next]; newLower = node2.lower_[variable]; } if (branchingTree.nodes_[jNode].parent_!=next) assert (newLower (floor(value2)); assert (newUppervalue2) { // must have been up branch which was done - carry over int newLower = static_cast (ceil(value2)); assert (newLower>node.lower_[variable2]); node.lower_[variable2]=newLower; } if (node.lower_[variable2]>node.upper_[variable2]) { // infeasible node.descendants_=2; // ignore branchingTree.sizeDeferred_++; } } } break; } } } else { break; } jNode=next; } } // solve //resolve(); //assert(!getIterationCount()); if ((numberNodes%1000)==0) printf("%d nodes, redundant down %d (%d) up %d (%d) tree size %d\n", numberNodes,nRedundantDown,nRedundantDown2,nRedundantUp,nRedundantUp2,branchingTree.size()); #else if ((numberNodes%1000)==0) printf("%d nodes, tree size %d\n", numberNodes,branchingTree.size()); #endif if (CoinCpuTime()-time1>3600.0) { printf("stopping after 3600 seconds\n"); exit(77); } OsiNodeSimple newNode(*this,numberIntegers,which,ws); // something extra may have been fixed by strong branching // if so go round again while (newNode.variable_==numberIntegers) { resolve(); newNode = OsiNodeSimple(*this,numberIntegers,which,getWarmStart()); } if (newNode.objectiveValue_<1.0e100) { if (newNode.variable_>=0) assert (fabs(newNode.value_-floor(newNode.value_+0.5))>1.0e-6); newNode.parent_ = kNode; // push on stack branchingTree.push_back(newNode); } } else { // infeasible delete ws; } } else { // maximum iterations - exit std::cout<<"Exiting on maximum iterations" <setProblemStatus(1); } delete [] which; delete [] originalLower; delete [] originalUpper; delete [] relaxedLower; delete [] relaxedUpper; } else { if(messageHandler()) *messageHandler() <<"The LP relaxation is infeasible" <setProblemStatus(1); //throw CoinError("The LP relaxation is infeasible or too expensive", //"branchAndBound", "OsiClpSolverInterface"); } } void OsiClpSolverInterface::setSpecialOptions(unsigned int value) { if ((value&131072)!=0&&(specialOptions_&131072)==0) { // Try and keep scaling factors around delete baseModel_; baseModel_ = new ClpSimplex(*modelPtr_); ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(baseModel_->matrix_); if (!clpMatrix||clpMatrix->scale(baseModel_)) { // switch off again delete baseModel_; baseModel_=NULL; value &= ~131072; } else { // Off current scaling modelPtr_->setRowScale(NULL); modelPtr_->setColumnScale(NULL); lastNumberRows_=baseModel_->numberRows(); rowScale_ = CoinDoubleArrayWithLength(2*lastNumberRows_,0); int i; double * scale; double * inverseScale; scale = rowScale_.array(); inverseScale = scale + lastNumberRows_; const double * rowScale = baseModel_->rowScale_; for (i=0;inumberColumns(); columnScale_ = CoinDoubleArrayWithLength(2*numberColumns,0); scale = columnScale_.array(); inverseScale = scale + numberColumns; const double * columnScale = baseModel_->columnScale_; for (i=0;isetExtraGap(0.0); matrixByRowAtContinuous_->setExtraMajor(0.0); matrixByRowAtContinuous_->reverseOrderedCopyOf(*modelPtr_->matrix()); //continuousModel_->createRim(63); } // Pass in disaster handler void OsiClpSolverInterface::passInDisasterHandler(OsiClpDisasterHandler * handler) { delete disasterHandler_; if ( handler ) disasterHandler_ = dynamic_cast(handler->clone()); else disasterHandler_ = NULL; } /* Strip off rows to get to this number of rows. If solver wants it can restore a copy of "base" (continuous) model here */ void OsiClpSolverInterface::restoreBaseModel(int numberRows) { if (continuousModel_&&continuousModel_->numberRows()==numberRows) { modelPtr_->numberRows_ = numberRows; //ClpDisjointCopyN ( continuousModel_->columnLower_, modelPtr_->numberColumns_,modelPtr_->columnLower_ ); //ClpDisjointCopyN ( continuousModel_->columnUpper_, modelPtr_->numberColumns_,modelPtr_->columnUpper_ ); // Could keep copy of scaledMatrix_ around?? delete modelPtr_->scaledMatrix_; modelPtr_->scaledMatrix_=NULL; if (continuousModel_->rowCopy_) { modelPtr_->copy(continuousModel_->rowCopy_,modelPtr_->rowCopy_); } else { delete modelPtr_->rowCopy_; modelPtr_->rowCopy_=NULL; } modelPtr_->copy(continuousModel_->matrix_,modelPtr_->matrix_); if (matrixByRowAtContinuous_) { if (matrixByRow_) { *matrixByRow_ = *matrixByRowAtContinuous_; } else { //printf("BBBB could new\n"); // matrixByRow_ = new CoinPackedMatrix(*matrixByRowAtContinuous_); } } else { delete matrixByRow_; matrixByRow_=NULL; } } else { OsiSolverInterface::restoreBaseModel(numberRows); } } // Tighten bounds - lightweight int OsiClpSolverInterface::tightenBounds(int lightweight) { if (!integerInformation_||(specialOptions_&262144)!=0) return 0; // no integers //CoinPackedMatrix matrixByRow(*getMatrixByRow()); int numberRows = getNumRows(); int numberColumns = 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 * columnUpper = getColUpper(); const double * columnLower = getColLower(); const double * rowUpper = getRowUpper(); const double * rowLower = getRowLower(); // Column copy of matrix const double * element = getMatrixByCol()->getElements(); const int * row = getMatrixByCol()->getIndices(); const CoinBigIndex * columnStart = getMatrixByCol()->getVectorStarts(); const int * columnLength = getMatrixByCol()->getVectorLengths(); const double *objective = getObjCoefficients() ; double direction = getObjSense(); double * down = new double [numberRows]; if (lightweight>0) { int * first = new int[numberRows]; CoinZeroN(first,numberRows); CoinZeroN(down,numberRows); double * sum = new double [numberRows]; CoinZeroN(sum,numberRows); int numberTightened=0; for (int iColumn=0;iColumnintegerType_; for (int iRow=0;iRow-1.0e20) lowerRow -= down[iRow]; double upperRow = rowUpper[iRow]; if (upperRow<1.0e20) upperRow -= down[iRow]; double lower = columnLower[iColumn]; double upper = columnUpper[iColumn]; double value=0.0; for (CoinBigIndex j = columnStart[iColumn]; j0.0) { if (lowerRow>-1.0e20) newLower = lowerRow/value; if (upperRow<1.0e20) newUpper = upperRow/value; } else { if (upperRow<1.0e20) newLower = upperRow/value; if (lowerRow>-1.0e20) newUpper = lowerRow/value; } double tolerance2 = 1.0e-6+1.0e-8*sum[iRow]; if (integerInformation&&integerInformation[iColumn]) { if (newLower-floor(newLower)lower+10.0*tolerance2|| newUppernewUpper+tolerance) { //printf("XXYY inf on bound\n"); numberTightened=-1; break; } setColLower(iColumn,newLower); setColUpper(iColumn,CoinMax(newLower,newUpper)); } } } } delete [] first; delete [] down; delete [] sum; return numberTightened; } double * up = new double [numberRows]; double * sum = new double [numberRows]; int * type = new int [numberRows]; CoinZeroN(down,numberRows); CoinZeroN(up,numberRows); CoinZeroN(sum,numberRows); CoinZeroN(type,numberRows); double infinity = getInfinity(); for (iColumn=0;iColumn0.0) { if ((type[iRow]&1)==0) { if (lower!=-infinity) { down[iRow] += value*lower; sum[iRow]+=fabs(value*lower); } else { type[iRow] |= 1; } } if ((type[iRow]&2)==0) { if (upper!=infinity) { up[iRow] += value*upper; sum[iRow]+=fabs(value*upper); } else { type[iRow] |= 2; } } } else { if ((type[iRow]&1)==0) { if (upper!=infinity) { down[iRow] += value*upper; sum[iRow]+=fabs(value*upper); } else { type[iRow] |= 1; } } if ((type[iRow]&2)==0) { if (lower!=-infinity) { up[iRow] += value*lower; sum[iRow]+=fabs(value*lower); } else { type[iRow] |= 2; } } } } } } int nTightened=0; double tolerance = 1.0e-6; for (iRow=0;iRowrowUpper[iRow]) { if (down[iRow]>rowUpper[iRow]+tolerance+1.0e-8*sum[iRow]) { // infeasible #ifdef COIN_DEVELOP printf("infeasible on row %d\n",iRow); #endif nTightened=-1; break; } else { down[iRow]=rowUpper[iRow]; } } if ((type[iRow]&2)!=0) up[iRow]=infinity; if (up[iRow]1.0e8) continue; // Could do severe damage to accuracy if (integerInformation_[iColumn]) { if (lower!=floor(lower+0.5)) { #ifdef COIN_DEVELOP printf("increasing lower bound on %d from %g to %g\n",iColumn, lower,ceil(lower)); #endif lower=ceil(lower); gap=upper-lower; setColLower(iColumn,lower); } if (upper!=floor(upper+0.5)) { #ifdef COIN_DEVELOP printf("decreasing upper bound on %d from %g to %g\n",iColumn, upper,floor(upper)); #endif upper=floor(upper); gap=upper-lower; setColUpper(iColumn,upper); } double newLower=lower; double newUpper=upper; for (CoinBigIndex j=start;j0.0) { if ((type[iRow]&1)==0) { // has to be at most something if (down[iRow] + value*gap > rowUpper[iRow]+tolerance) { double newGap = (rowUpper[iRow]-down[iRow])/value; // adjust newGap += 1.0e-10*sum[iRow]; newGap = floor(newGap); if (lower+newGapnewLower) newLower=upper-newGap; } } if (up[iRow]>rowUpper[iRow]) canGo |=2; // can't go up without affecting result } else { if ((type[iRow]&1)==0) { // has to be at least something if (down[iRow] - value*gap > rowUpper[iRow]+tolerance) { double newGap = -(rowUpper[iRow]-down[iRow])/value; // adjust newGap += 1.0e-10*sum[iRow]; newGap = floor(newGap); if (upper-newGap>newLower) newLower=upper-newGap; } } if (up[iRow]>rowUpper[iRow]) canGo |=1; // can't go down without affecting result if ((type[iRow]&2)==0) { // has to be at most something if (up[iRow] + value*gap < rowLower[iRow]-tolerance) { double newGap = -(up[iRow]-rowLower[iRow])/value; // adjust newGap += 1.0e-10*sum[iRow]; newGap = floor(newGap); if (lower+newGaplower) { nTightened++; if (newLower>newUpper) { // infeasible #if COIN_DEVELOP>1 printf("infeasible on column %d\n",iColumn); #endif nTightened=-1; break; } else { setColLower(iColumn,newLower); setColUpper(iColumn,newUpper); } for (CoinBigIndex j=start;j0.0) { if ((type[iRow]&1)==0) { down[iRow] += value*(newLower-lower); } if ((type[iRow]&2)==0) { up[iRow] += value*(newUpper-upper); } } else { if ((type[iRow]&1)==0) { down[iRow] += value*(newUpper-upper); } if ((type[iRow]&2)==0) { up[iRow] += value*(newLower-lower); } } } } else { if (canGo!=3) { double objValue = direction*objective[iColumn]; if (objValue>=0.0&&(canGo&1)==0) { #if COIN_DEVELOP>2 printf("dual fix down on column %d\n",iColumn); #endif // Only if won't cause numerical problems if (lower>-1.0e10) { nTightened++; setColUpper(iColumn,lower); } } else if (objValue<=0.0&&(canGo&2)==0) { #if COIN_DEVELOP>2 printf("dual fix up on column %d\n",iColumn); #endif // Only if won't cause numerical problems if (upper<1.0e10) { nTightened++; setColLower(iColumn,upper); } } } } } else { // just do dual tests for (CoinBigIndex j=start;j0.0) { if (down[iRow]rowUpper[iRow]) canGo |=2; // can't go up without affecting result } else { if (up[iRow]>rowUpper[iRow]) canGo |=1; // can't go down without affecting result if (down[iRow]=0.0&&(canGo&1)==0) { #if COIN_DEVELOP>2 printf("dual fix down on continuous column %d lower %g\n", iColumn,lower); #endif // Only if won't cause numerical problems if (lower>-1.0e10) { nTightened++; setColUpper(iColumn,lower); } } else if (objValue<=0.0&&(canGo&2)==0) { #if COIN_DEVELOP>2 printf("dual fix up on continuous column %d upper %g\n", iColumn,upper); #endif // Only if won't cause numerical problems if (upper<1.0e10) { nTightened++; setColLower(iColumn,upper); } } } } } if (lightweight<0) { // get max down and up again CoinZeroN(down,numberRows); CoinZeroN(up,numberRows); CoinZeroN(type,numberRows); int * seqDown = new int [2*numberRows]; int * seqUp=seqDown+numberRows; for (int i=0;i0.0) { if ((type[iRow]&1)==0) { if (lower>-1.0e8) { down[iRow] += value*lower; } else if (seqDown[iRow]<0) { seqDown[iRow]=iColumn; } else { type[iRow] |= 1; } } if ((type[iRow]&2)==0) { if (upper<1.0e8) { up[iRow] += value*upper; sum[iRow]+=fabs(value*upper); } else if (seqUp[iRow]<0) { seqUp[iRow]=iColumn; } else { type[iRow] |= 2; } } } else { if ((type[iRow]&1)==0) { if (upper<1.0e8) { down[iRow] += value*upper; sum[iRow]+=fabs(value*upper); } else if (seqDown[iRow]<0) { seqDown[iRow]=iColumn; } else { type[iRow] |= 1; } } if ((type[iRow]&2)==0) { if (lower>-1.0e8) { up[iRow] += value*lower; sum[iRow]+=fabs(value*lower); } else if (seqUp[iRow]<0) { seqUp[iRow]=iColumn; } else { type[iRow] |= 2; } } } } } } for (iColumn=0;iColumn1.0e8) continue; // Could do severe damage to accuracy double newLower=upper; double newUpper=lower; bool badUpper=false; bool badLower=false; double objValue = objective[iColumn]*direction; for (CoinBigIndex j=start;j0.0) { if (rowLower[iRow]>-COIN_DBL_MAX) { if (!badUpper&&(type[iRow]&1)==0&& (seqDown[iRow]<0||seqDown[iRow]==iColumn)) { double s=down[iRow]; if (seqDown[iRow]!=iColumn) s -= lower*value; if (s+newUpper*valuerowUpper[iRow]) { newLower = CoinMin(newLower,(rowUpper[iRow]-s)/value); } } else { badLower=true; } } } else { if (rowUpper[iRow]rowUpper[iRow]) { newUpper = CoinMax(newUpper,(rowUpper[iRow]-s)/value); } } else { badUpper=true; } } if (rowLower[iRow]>-COIN_DBL_MAX) { if (!badLower&&(type[iRow]&1)==0&& (seqDown[iRow]<0||seqDown[iRow]==iColumn)) { double s=down[iRow]; if (seqDown[iRow]!=iColumn) s -= lower*value; if (s+newLower*value0.0) newLower=lower; if (badUpper||objValue<0.0) newUpper=upper; if (newUpperlower) { nTightened++; if (newLower>newUpper) { // infeasible #if COIN_DEVELOP>0 printf("infeasible on column %d\n",iColumn); #endif nTightened=-1; break; } else { newLower=CoinMax(newLower,lower); newUpper=CoinMin(newUpper,upper); if (integerInformation_[iColumn]) { newLower=ceil(newLower-1.0e-5); newUpper=floor(newUpper+1.0e-5); } setColLower(iColumn,newLower); setColUpper(iColumn,newUpper); } } } delete [] seqDown; } delete [] type; delete [] down; delete [] up; delete [] sum; return nTightened; } // Return number of entries in L part of current factorization CoinBigIndex OsiClpSolverInterface::getSizeL() const { return modelPtr_->factorization_->numberElementsL(); } // Return number of entries in U part of current factorization CoinBigIndex OsiClpSolverInterface::getSizeU() const { return modelPtr_->factorization_->numberElementsU(); } /* Add a named row (constraint) to the problem. */ void OsiClpSolverInterface::addRow(const CoinPackedVectorBase& vec, const char rowsen, const double rowrhs, const double rowrng, std::string name) { int ndx = getNumRows() ; addRow(vec,rowsen,rowrhs,rowrng) ; setRowName(ndx,name) ; } /* Add a named column (primal variable) to the problem. */ void OsiClpSolverInterface::addCol(int numberElements, const int* rows, const double* elements, const double collb, const double colub, const double obj, std::string name) { int ndx = getNumCols() ; addCol(numberElements,rows,elements,collb,colub,obj) ; setColName(ndx,name) ; } /* Start faster dual - returns negative if problems 1 if infeasible, Options to pass to solver 1 - create external reduced costs for columns 2 - create external reduced costs for rows 4 - create external row activity (columns always done) Above only done if feasible When set resolve does less work */ int OsiClpSolverInterface::startFastDual(int options) { stuff_.zap(3); stuff_.solverOptions_=options; return modelPtr_->startFastDual2(&stuff_); } // Sets integer tolerance and increment void OsiClpSolverInterface::setStuff(double tolerance,double increment) { stuff_.integerTolerance_ = tolerance; stuff_.integerIncrement_ = increment; } // Stops faster dual void OsiClpSolverInterface::stopFastDual() { modelPtr_->stopFastDual2(&stuff_); } // Compute largest amount any at continuous away from bound void OsiClpSolverInterface::computeLargestAway() { // get largest scaled away from bound ClpSimplex temp=*modelPtr_; // save logLevel (in case derived message handler) int saveLogLevel=temp.logLevel(); temp.setLogLevel(0); temp.dual(); if (temp.status()==1) temp.primal(); // may mean we have optimal so continuous cutoff temp.dual(0,7); temp.setLogLevel(saveLogLevel); 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;iRow4000) modelPtr_->setSpecialOptions(modelPtr_->specialOptions()&~(2048+4096)); } // Pass in Message handler (not deleted at end) void OsiClpSolverInterface::passInMessageHandler(CoinMessageHandler * handler) { if (defaultHandler_) { delete handler_; handler_ = NULL; } defaultHandler_=false; handler_=handler; if (modelPtr_) modelPtr_->passInMessageHandler(handler); } // Set log level (will also set underlying solver's log level) void OsiClpSolverInterface::setLogLevel(int value) { handler_->setLogLevel(value); if (modelPtr_) modelPtr_->setLogLevel(value); } // Set fake objective (and take ownership) void OsiClpSolverInterface::setFakeObjective(ClpLinearObjective * fakeObjective) { delete fakeObjective_; fakeObjective_ = fakeObjective; } // Set fake objective void OsiClpSolverInterface::setFakeObjective(double * fakeObjective) { delete fakeObjective_; if (fakeObjective) fakeObjective_ = new ClpLinearObjective(fakeObjective, modelPtr_->numberColumns_); else fakeObjective_ = NULL; } /* Solve when primal column and dual row solutions are near-optimal options - 0 no presolve (use primal and dual) 1 presolve (just use primal) 2 no presolve (just use primal) basis - 0 use all slack basis 1 try and put some in basis */ void OsiClpSolverInterface::crossover(int options,int basis) { int numberRows = modelPtr_->getNumRows(); int numberColumns = modelPtr_->getNumCols(); // Get row activities and column reduced costs const double * objective = modelPtr_->objective(); double direction = modelPtr_->optimizationDirection(); double * dual = modelPtr_->dualRowSolution(); double * dj = modelPtr_->dualColumnSolution(); CoinMemcpyN(objective,numberColumns,dj); if (direction==-1.0) { for (int i=0;iclpMatrix()->transposeTimes(-1.0,dual,dj); double * rowActivity = modelPtr_->primalRowSolution(); double * columnActivity = modelPtr_->primalColumnSolution(); CoinZeroN(rowActivity,numberRows); modelPtr_->clpMatrix()->times(1.0,columnActivity,rowActivity); modelPtr_->checkSolution(); printf("%d primal infeasibilities summing to %g\n", modelPtr_->numberPrimalInfeasibilities(), modelPtr_->sumPrimalInfeasibilities()); printf("%d dual infeasibilities summing to %g\n", modelPtr_->numberDualInfeasibilities(), modelPtr_->sumDualInfeasibilities()); // get which variables are fixed double * saveLower=NULL; double * saveUpper=NULL; ClpPresolve pinfo2; bool extraPresolve=false; bool useBoth= (options==0); // create all slack basis modelPtr_->createStatus(); // Point to model - so can use in presolved model ClpSimplex * model2 = modelPtr_; double tolerance = modelPtr_->primalTolerance()*10.0; if (options==1) { int numberTotal = numberRows+numberColumns; saveLower = new double [numberTotal]; saveUpper = new double [numberTotal]; CoinMemcpyN(modelPtr_->columnLower(),numberColumns,saveLower); CoinMemcpyN(modelPtr_->rowLower(),numberRows,saveLower+numberColumns); CoinMemcpyN(modelPtr_->columnUpper(),numberColumns,saveUpper); CoinMemcpyN(modelPtr_->rowUpper(),numberRows,saveUpper+numberColumns); double * lower = modelPtr_->columnLower(); double * upper = modelPtr_->columnUpper(); double * solution = modelPtr_->primalColumnSolution(); int nFix=0; for (int i=0;i-1.0e10||upper[i]<1.0e10)) { double value = solution[i]; if (valueupper[i]-tolerance&&value-lower[i]>upper[i]-value) { solution[i]=upper[i]; lower[i]=upper[i]; nFix++; } } } #ifdef CLP_INVESTIGATE printf("%d columns fixed\n",nFix); #endif #if 0 int nr=modelPtr_->numberRows(); lower = modelPtr_->rowLower(); upper = modelPtr_->rowUpper(); solution = modelPtr_->primalRowSolution(); nFix=0; for (int i=0;iupper[i]-tolerance&&value-lower[i]>upper[i]-value) { solution[i]=upper[i]; lower[i]=upper[i]; nFix++; } } } #ifdef CLP_INVESTIGATE printf("%d row slacks fixed\n",nFix); #endif #endif extraPresolve=true; // do presolve model2 = pinfo2.presolvedModel(*modelPtr_,modelPtr_->presolveTolerance(), false,5,true); if (!model2) { model2=modelPtr_; CoinMemcpyN(saveLower,numberColumns,model2->columnLower()); CoinMemcpyN(saveLower+numberColumns,numberRows,model2->rowLower()); delete [] saveLower; CoinMemcpyN(saveUpper,numberColumns,model2->columnUpper()); CoinMemcpyN(saveUpper+numberColumns,numberRows,model2->rowUpper()); delete [] saveUpper; saveLower=NULL; saveUpper=NULL; extraPresolve=false; } } if (model2->factorizationFrequency()==200) { // User did not touch preset model2->defaultFactorizationFrequency(); } if (basis) { // throw some into basis int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); double * dsort = new double[numberColumns]; int * sort = new int[numberColumns]; int n=0; const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); double * primalSolution = model2->primalColumnSolution(); const double * dualSolution = model2->dualColumnSolution(); int i; for ( i=0;isetRowStatus(i,ClpSimplex::superBasic); for ( i=0;itolerance) { if (fabs(dualSolution[i])<1.0e-5) distance *= 100.0; dsort[n]=-distance; sort[n++]=i; model2->setStatus(i,ClpSimplex::superBasic); } else if (distance>tolerance) { model2->setStatus(i,ClpSimplex::superBasic); } else if (primalSolution[i]<=columnLower[i]+tolerance) { model2->setStatus(i,ClpSimplex::atLowerBound); primalSolution[i]=columnLower[i]; } else { model2->setStatus(i,ClpSimplex::atUpperBound); primalSolution[i]=columnUpper[i]; } } CoinSort_2(dsort,dsort+n,sort); n = CoinMin(numberRows,n); for ( i=0;isetStatus(iColumn,ClpSimplex::basic); } delete [] sort; delete [] dsort; } // Start crossover if (useBoth) { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); double * rowPrimal = new double [numberRows]; double * columnPrimal = new double [numberColumns]; double * rowDual = new double [numberRows]; double * columnDual = new double [numberColumns]; // move solutions CoinMemcpyN(model2->primalRowSolution(), numberRows,rowPrimal); CoinMemcpyN(model2->dualRowSolution(), numberRows,rowDual); CoinMemcpyN(model2->primalColumnSolution(), numberColumns,columnPrimal); CoinMemcpyN(model2->dualColumnSolution(), numberColumns,columnDual); // primal values pass double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); // save primal solution and copy back dual CoinMemcpyN(model2->primalRowSolution(), numberRows,rowPrimal); CoinMemcpyN(rowDual, numberRows,model2->dualRowSolution()); CoinMemcpyN(model2->primalColumnSolution(), numberColumns,columnPrimal); CoinMemcpyN(columnDual, numberColumns,model2->dualColumnSolution()); // clean up reduced costs and flag variables double * dj = model2->dualColumnSolution(); double * cost = model2->objective(); double * saveCost = new double[numberColumns]; CoinMemcpyN(cost,numberColumns,saveCost); double * saveLower = new double[numberColumns]; double * lower = model2->columnLower(); CoinMemcpyN(lower,numberColumns,saveLower); double * saveUpper = new double[numberColumns]; double * upper = model2->columnUpper(); CoinMemcpyN(upper,numberColumns,saveUpper); int i; for ( i=0;igetStatus(i)==ClpSimplex::basic) { dj[i]=0.0; } else if (model2->getStatus(i)==ClpSimplex::atLowerBound) { if (direction*dj[i]getStatus(i)==ClpSimplex::atUpperBound) { if (direction*dj[i]>tolerance) { if (direction*dj[i]>0.0) { //if (dj[i]>1.0e-3) //printf("bad dj at ub %d %g\n",i,dj[i]); cost[i] -= dj[i]; dj[i]=0.0; } } else { lower[i]=upper[i]; } } } // just dual values pass model2->dual(2); CoinMemcpyN(saveCost,numberColumns,cost); delete [] saveCost; CoinMemcpyN(saveLower,numberColumns,lower); delete [] saveLower; CoinMemcpyN(saveUpper,numberColumns,upper); delete [] saveUpper; // move solutions CoinMemcpyN(rowPrimal, numberRows,model2->primalRowSolution()); CoinMemcpyN(columnPrimal, numberColumns,model2->primalColumnSolution()); // and finish delete [] rowPrimal; delete [] columnPrimal; delete [] rowDual; delete [] columnDual; model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); model2->primal(1); } else { // primal values pass double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); model2->primal(1); } if (extraPresolve) { pinfo2.postsolve(true); delete model2; modelPtr_->primal(1); CoinMemcpyN(saveLower,numberColumns,modelPtr_->columnLower()); CoinMemcpyN(saveLower+numberColumns,numberRows,modelPtr_->rowLower()); CoinMemcpyN(saveUpper,numberColumns,modelPtr_->columnUpper()); CoinMemcpyN(saveUpper+numberColumns,numberRows,modelPtr_->rowUpper()); delete [] saveLower; delete [] saveUpper; modelPtr_->primal(1); } // Save basis in Osi object setWarmStart(NULL); } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- OsiClpDisasterHandler::OsiClpDisasterHandler (OsiClpSolverInterface * model) : ClpDisasterHandler(), osiModel_(model), whereFrom_(0), phase_(0), inTrouble_(false) { if (model) setSimplex(model->getModelPtr()); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- OsiClpDisasterHandler::OsiClpDisasterHandler (const OsiClpDisasterHandler & rhs) : ClpDisasterHandler(rhs), osiModel_(rhs.osiModel_), whereFrom_(rhs.whereFrom_), phase_(rhs.phase_), inTrouble_(rhs.inTrouble_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- OsiClpDisasterHandler::~OsiClpDisasterHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- OsiClpDisasterHandler & OsiClpDisasterHandler::operator=(const OsiClpDisasterHandler& rhs) { if (this != &rhs) { ClpDisasterHandler::operator=(rhs); osiModel_ = rhs.osiModel_; whereFrom_ = rhs.whereFrom_; phase_ = rhs.phase_; inTrouble_ = rhs.inTrouble_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpDisasterHandler * OsiClpDisasterHandler::clone() const { return new OsiClpDisasterHandler(*this); } void OsiClpDisasterHandler::intoSimplex() { inTrouble_=false; } bool OsiClpDisasterHandler::check() const { // Exit if really large number of iterations if (model_->numberIterations()> model_->baseIteration()+100000+100*(model_->numberRows()+model_->numberColumns())) return true; if ((whereFrom_&2)==0||!model_->nonLinearCost()) { // dual if (model_->numberIterations()baseIteration()+model_->numberRows()+1000) { return false; } else if (phase_<2) { if (model_->numberIterations()> model_->baseIteration()+2*model_->numberRows()+model_->numberColumns()+2000|| model_->largestDualError()>=1.0e-1) { // had model_->numberDualInfeasibilitiesWithoutFree()|| #ifdef COIN_DEVELOP printf("trouble in phase %d\n",phase_); #endif if (osiModel_->largestAway()>0.0) { // go for safety model_->setSpecialOptions(model_->specialOptions()&~(2048+4096)); int frequency = model_->factorizationFrequency(); if (frequency>100) frequency=100; model_->setFactorizationFrequency(frequency); double oldBound = model_->dualBound(); double newBound = CoinMax(1.0001e8, CoinMin(10.0*osiModel_->largestAway(),1.e10)); if (newBound!=oldBound) { model_->setDualBound(newBound); if (model_->upperRegion()&&model_->algorithm()<0) { // need to fix up fake bounds (static_cast(model_))->resetFakeBounds(0); } } osiModel_->setLargestAway(-1.0); } return true; } else { return false; } } else { assert (phase_==2); if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+model_->numberColumns()+2000|| model_->largestPrimalError()>=1.0e3) { #ifdef COIN_DEVELOP printf("trouble in phase %d\n",phase_); #endif return true; } else { return false; } } } else { // primal if (model_->numberIterations()baseIteration()+2*model_->numberRows()+model_->numberColumns()+4000) { return false; } else if (phase_<2) { if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+2000+ model_->numberColumns()&& model_->numberDualInfeasibilitiesWithoutFree()>0&& model_->numberPrimalInfeasibilities()>0&& model_->nonLinearCost()->changeInCost()>1.0e8) { #ifdef COIN_DEVELOP printf("trouble in phase %d\n",phase_); #endif return true; } else { return false; } } else { assert (phase_==2); if (model_->numberIterations()> model_->baseIteration()+3*model_->numberRows()+2000|| model_->largestPrimalError()>=1.0e3) { #ifdef COIN_DEVELOP printf("trouble in phase %d\n",phase_); #endif return true; } else { return false; } } } } void OsiClpDisasterHandler::saveInfo() { inTrouble_=true; } // Type of disaster 0 can fix, 1 abort int OsiClpDisasterHandler::typeOfDisaster() { return 0; } /* set model. */ void OsiClpDisasterHandler::setOsiModel(OsiClpSolverInterface * model) { osiModel_=model; model_=model->getModelPtr(); } // Create C++ lines to get to current state void OsiClpSolverInterface::generateCpp( FILE * fp) { modelPtr_->generateCpp(fp,true); // Stuff that can't be done easily // setupForRepeatedUse here if (!messageHandler()->prefix()) fprintf(fp,"3 clpModel->messageHandler()->setPrefix(false);\n"); OsiClpSolverInterface defaultModel; OsiClpSolverInterface * other = &defaultModel; int iValue1, iValue2; double dValue1, dValue2; bool takeHint1,takeHint2; int add; OsiHintStrength strength1,strength2; std::string strengthName[] = {"OsiHintIgnore","OsiHintTry","OsiHintDo", "OsiForceDo"}; iValue1 = this->specialOptions(); iValue2 = other->specialOptions(); fprintf(fp,"%d int save_specialOptions = osiclpModel->specialOptions();\n",iValue1==iValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setSpecialOptions(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1); fprintf(fp,"%d osiclpModel->setSpecialOptions(save_specialOptions);\n",iValue1==iValue2 ? 7 : 6); iValue1 = this->messageHandler()->logLevel(); iValue2 = other->messageHandler()->logLevel(); fprintf(fp,"%d int save_messageHandler = osiclpModel->messageHandler()->logLevel();\n",iValue1==iValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->messageHandler()->setLogLevel(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1); fprintf(fp,"%d osiclpModel->messageHandler()->setLogLevel(save_messageHandler);\n",iValue1==iValue2 ? 7 : 6); iValue1 = this->cleanupScaling(); iValue2 = other->cleanupScaling(); fprintf(fp,"%d int save_cleanupScaling = osiclpModel->cleanupScaling();\n",iValue1==iValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setCleanupScaling(%d);\n",iValue1==iValue2 ? 4 : 3,iValue1); fprintf(fp,"%d osiclpModel->setCleanupScaling(save_cleanupScaling);\n",iValue1==iValue2 ? 7 : 6); dValue1 = this->smallestElementInCut(); dValue2 = other->smallestElementInCut(); fprintf(fp,"%d double save_smallestElementInCut = osiclpModel->smallestElementInCut();\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setSmallestElementInCut(%g);\n",dValue1==dValue2 ? 4 : 3,dValue1); fprintf(fp,"%d osiclpModel->setSmallestElementInCut(save_smallestElementInCut);\n",dValue1==dValue2 ? 7 : 6); dValue1 = this->smallestChangeInCut(); dValue2 = other->smallestChangeInCut(); fprintf(fp,"%d double save_smallestChangeInCut = osiclpModel->smallestChangeInCut();\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setSmallestChangeInCut(%g);\n",dValue1==dValue2 ? 4 : 3,dValue1); fprintf(fp,"%d osiclpModel->setSmallestChangeInCut(save_smallestChangeInCut);\n",dValue1==dValue2 ? 7 : 6); this->getIntParam(OsiMaxNumIterationHotStart,iValue1); other->getIntParam(OsiMaxNumIterationHotStart,iValue2); fprintf(fp,"%d int save_OsiMaxNumIterationHotStart;\n",iValue1==iValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->getIntParam(OsiMaxNumIterationHotStart,save_OsiMaxNumIterationHotStart);\n",iValue1==iValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setIntParam(OsiMaxNumIterationHotStart,%d);\n",iValue1==iValue2 ? 4 : 3,iValue1); fprintf(fp,"%d osiclpModel->setIntParam(OsiMaxNumIterationHotStart,save_OsiMaxNumIterationHotStart);\n",iValue1==iValue2 ? 7 : 6); this->getDblParam(OsiDualObjectiveLimit,dValue1); other->getDblParam(OsiDualObjectiveLimit,dValue2); fprintf(fp,"%d double save_OsiDualObjectiveLimit;\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->getDblParam(OsiDualObjectiveLimit,save_OsiDualObjectiveLimit);\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setDblParam(OsiDualObjectiveLimit,%g);\n",dValue1==dValue2 ? 4 : 3,dValue1); fprintf(fp,"%d osiclpModel->setDblParam(OsiDualObjectiveLimit,save_OsiDualObjectiveLimit);\n",dValue1==dValue2 ? 7 : 6); this->getDblParam(OsiPrimalObjectiveLimit,dValue1); other->getDblParam(OsiPrimalObjectiveLimit,dValue2); fprintf(fp,"%d double save_OsiPrimalObjectiveLimit;\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->getDblParam(OsiPrimalObjectiveLimit,save_OsiPrimalObjectiveLimit);\n",dValue1==dValue2 ? 2 : 1); fprintf(fp,"%d osiclpModel->setDblParam(OsiPrimalObjectiveLimit,%g);\n",dValue1==dValue2 ? 4 : 3,dValue1); fprintf(fp,"%d osiclpModel->setDblParam(OsiPrimalObjectiveLimit,save_OsiPrimalObjectiveLimit);\n",dValue1==dValue2 ? 7 : 6); this->getHintParam(OsiDoPresolveInInitial,takeHint1,strength1); other->getHintParam(OsiDoPresolveInInitial,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoPresolveInInitial;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoPresolveInInitial;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoPresolveInInitial,saveHint_OsiDoPresolveInInitial,saveStrength_OsiDoPresolveInInitial);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInInitial,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInInitial,saveHint_OsiDoPresolveInInitial,saveStrength_OsiDoPresolveInInitial);\n",add+6); this->getHintParam(OsiDoDualInInitial,takeHint1,strength1); other->getHintParam(OsiDoDualInInitial,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoDualInInitial;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoDualInInitial;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoDualInInitial,saveHint_OsiDoDualInInitial,saveStrength_OsiDoDualInInitial);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInInitial,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInInitial,saveHint_OsiDoDualInInitial,saveStrength_OsiDoDualInInitial);\n",add+6); this->getHintParam(OsiDoPresolveInResolve,takeHint1,strength1); other->getHintParam(OsiDoPresolveInResolve,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoPresolveInResolve;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoPresolveInResolve;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoPresolveInResolve,saveHint_OsiDoPresolveInResolve,saveStrength_OsiDoPresolveInResolve);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInResolve,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoPresolveInResolve,saveHint_OsiDoPresolveInResolve,saveStrength_OsiDoPresolveInResolve);\n",add+6); this->getHintParam(OsiDoDualInResolve,takeHint1,strength1); other->getHintParam(OsiDoDualInResolve,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoDualInResolve;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoDualInResolve;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoDualInResolve,saveHint_OsiDoDualInResolve,saveStrength_OsiDoDualInResolve);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInResolve,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoDualInResolve,saveHint_OsiDoDualInResolve,saveStrength_OsiDoDualInResolve);\n",add+6); this->getHintParam(OsiDoScale,takeHint1,strength1); other->getHintParam(OsiDoScale,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoScale;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoScale;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoScale,saveHint_OsiDoScale,saveStrength_OsiDoScale);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoScale,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoScale,saveHint_OsiDoScale,saveStrength_OsiDoScale);\n",add+6); this->getHintParam(OsiDoCrash,takeHint1,strength1); other->getHintParam(OsiDoCrash,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoCrash;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoCrash;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoCrash,saveHint_OsiDoCrash,saveStrength_OsiDoCrash);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoCrash,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoCrash,saveHint_OsiDoCrash,saveStrength_OsiDoCrash);\n",add+6); this->getHintParam(OsiDoReducePrint,takeHint1,strength1); other->getHintParam(OsiDoReducePrint,takeHint2,strength2); add = ((takeHint1==takeHint2)&&(strength1==strength2)) ? 1 : 0; fprintf(fp,"%d bool saveHint_OsiDoReducePrint;\n",add+1); fprintf(fp,"%d OsiHintStrength saveStrength_OsiDoReducePrint;\n",add+1); fprintf(fp,"%d osiclpModel->getHintParam(OsiDoReducePrint,saveHint_OsiDoReducePrint,saveStrength_OsiDoReducePrint);\n",add+1); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoReducePrint,%s,%s);\n",add+3,takeHint1 ? "true" : "false",strengthName[strength1].c_str()); fprintf(fp,"%d osiclpModel->setHintParam(OsiDoReducePrint,saveHint_OsiDoReducePrint,saveStrength_OsiDoReducePrint);\n",add+6); } // So unit test can find out if NDEBUG set bool OsiClpHasNDEBUG() { #ifdef NDEBUG return true; #else return false; #endif } Clp-1.15.10/src/OsiClp/Makefile.am0000644000076600007660000000325212253625222015072 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 1152 2007-12-28 03:59:07Z andreasw $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # libOsiClp # ######################################################################## # Name of the library compiled in this directory. lib_LTLIBRARIES = libOsiClp.la # List all source files for this library, including headers libOsiClp_la_SOURCES = OsiClpSolverInterface.cpp OsiClpSolverInterface.hpp # List all additionally required libraries if DEPENDENCY_LINKING libOsiClp_la_LIBADD = $(OSICLPLIB_LIBS) ../libClp.la endif # This is for libtool (on Windows) libOsiClp_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)/..` $(COINUTILS_CFLAGS) $(OSI_CFLAGS) # 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 = OsiClpSolverInterface.hpp Clp-1.15.10/src/OsiClp/Makefile.in0000644000076600007660000005566012253625222015115 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@ subdir = src/OsiClp 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_clp.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@libOsiClp_la_DEPENDENCIES = \ @DEPENDENCY_LINKING_TRUE@ $(am__DEPENDENCIES_1) ../libClp.la am_libOsiClp_la_OBJECTS = OsiClpSolverInterface.lo libOsiClp_la_OBJECTS = $(am_libOsiClp_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 = $(libOsiClp_la_SOURCES) DIST_SOURCES = $(libOsiClp_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@ ADD_FFLAGS = @ADD_FFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMDINCDIR = @AMDINCDIR@ AMDLIB = @AMDLIB@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BLAS_CFLAGS = @BLAS_CFLAGS@ BLAS_CFLAGS_INSTALLED = @BLAS_CFLAGS_INSTALLED@ BLAS_DATA = @BLAS_DATA@ BLAS_DATA_INSTALLED = @BLAS_DATA_INSTALLED@ BLAS_DEPENDENCIES = @BLAS_DEPENDENCIES@ BLAS_LIBS = @BLAS_LIBS@ BLAS_LIBS_INSTALLED = @BLAS_LIBS_INSTALLED@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CHOLMODINCDIR = @CHOLMODINCDIR@ CHOLMODLIB = @CHOLMODLIB@ CLPLIB_CFLAGS = @CLPLIB_CFLAGS@ CLPLIB_CFLAGS_INSTALLED = @CLPLIB_CFLAGS_INSTALLED@ CLPLIB_DEPENDENCIES = @CLPLIB_DEPENDENCIES@ CLPLIB_LIBS = @CLPLIB_LIBS@ CLPLIB_LIBS_INSTALLED = @CLPLIB_LIBS_INSTALLED@ CLPLIB_PCLIBS = @CLPLIB_PCLIBS@ CLPLIB_PCREQUIRES = @CLPLIB_PCREQUIRES@ CLP_SVN_REV = @CLP_SVN_REV@ COINUTILS_CFLAGS = @COINUTILS_CFLAGS@ COINUTILS_CFLAGS_INSTALLED = @COINUTILS_CFLAGS_INSTALLED@ COINUTILS_DATA = @COINUTILS_DATA@ COINUTILS_DATA_INSTALLED = @COINUTILS_DATA_INSTALLED@ COINUTILS_DEPENDENCIES = @COINUTILS_DEPENDENCIES@ COINUTILS_LIBS = @COINUTILS_LIBS@ COINUTILS_LIBS_INSTALLED = @COINUTILS_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_ABC_FALSE = @COIN_HAS_ABC_FALSE@ COIN_HAS_ABC_TRUE = @COIN_HAS_ABC_TRUE@ COIN_HAS_AMD_FALSE = @COIN_HAS_AMD_FALSE@ COIN_HAS_AMD_TRUE = @COIN_HAS_AMD_TRUE@ COIN_HAS_BLAS_FALSE = @COIN_HAS_BLAS_FALSE@ COIN_HAS_BLAS_TRUE = @COIN_HAS_BLAS_TRUE@ COIN_HAS_CHOLMOD_FALSE = @COIN_HAS_CHOLMOD_FALSE@ COIN_HAS_CHOLMOD_TRUE = @COIN_HAS_CHOLMOD_TRUE@ COIN_HAS_COINUTILS_FALSE = @COIN_HAS_COINUTILS_FALSE@ COIN_HAS_COINUTILS_TRUE = @COIN_HAS_COINUTILS_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_MUMPS_FALSE = @COIN_HAS_MUMPS_FALSE@ COIN_HAS_MUMPS_TRUE = @COIN_HAS_MUMPS_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_OSI_FALSE = @COIN_HAS_OSI_FALSE@ COIN_HAS_OSI_TRUE = @COIN_HAS_OSI_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_WSMP_FALSE = @COIN_HAS_WSMP_FALSE@ COIN_HAS_WSMP_TRUE = @COIN_HAS_WSMP_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DBG_FFLAGS = @DBG_FFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FLIBS = @FLIBS@ 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@ 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@ MPICC = @MPICC@ MPICXX = @MPICXX@ MPIF77 = @MPIF77@ MUMPS_CFLAGS = @MUMPS_CFLAGS@ MUMPS_CFLAGS_INSTALLED = @MUMPS_CFLAGS_INSTALLED@ MUMPS_DATA = @MUMPS_DATA@ MUMPS_DATA_INSTALLED = @MUMPS_DATA_INSTALLED@ MUMPS_DEPENDENCIES = @MUMPS_DEPENDENCIES@ MUMPS_LIBS = @MUMPS_LIBS@ MUMPS_LIBS_INSTALLED = @MUMPS_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@ OPT_FFLAGS = @OPT_FFLAGS@ OSICLPLIB_CFLAGS = @OSICLPLIB_CFLAGS@ OSICLPLIB_CFLAGS_INSTALLED = @OSICLPLIB_CFLAGS_INSTALLED@ OSICLPLIB_DEPENDENCIES = @OSICLPLIB_DEPENDENCIES@ OSICLPLIB_LIBS = @OSICLPLIB_LIBS@ OSICLPLIB_LIBS_INSTALLED = @OSICLPLIB_LIBS_INSTALLED@ OSICLPLIB_PCLIBS = @OSICLPLIB_PCLIBS@ OSICLPLIB_PCREQUIRES = @OSICLPLIB_PCREQUIRES@ 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@ OSI_CFLAGS = @OSI_CFLAGS@ OSI_CFLAGS_INSTALLED = @OSI_CFLAGS_INSTALLED@ OSI_DATA = @OSI_DATA@ OSI_DATA_INSTALLED = @OSI_DATA_INSTALLED@ OSI_DEPENDENCIES = @OSI_DEPENDENCIES@ OSI_LIBS = @OSI_LIBS@ OSI_LIBS_INSTALLED = @OSI_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@ STRIP = @STRIP@ VERSION = @VERSION@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ 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 ######################################################################## # libOsiClp # ######################################################################## # Name of the library compiled in this directory. lib_LTLIBRARIES = libOsiClp.la # List all source files for this library, including headers libOsiClp_la_SOURCES = OsiClpSolverInterface.cpp OsiClpSolverInterface.hpp # List all additionally required libraries @DEPENDENCY_LINKING_TRUE@libOsiClp_la_LIBADD = $(OSICLPLIB_LIBS) ../libClp.la # This is for libtool (on Windows) libOsiClp_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)/..` $(COINUTILS_CFLAGS) $(OSI_CFLAGS) # 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 = OsiClpSolverInterface.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/OsiClp/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --foreign src/OsiClp/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 libOsiClp.la: $(libOsiClp_la_OBJECTS) $(libOsiClp_la_DEPENDENCIES) $(CXXLINK) -rpath $(libdir) $(libOsiClp_la_LDFLAGS) $(libOsiClp_la_OBJECTS) $(libOsiClp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OsiClpSolverInterface.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: Clp-1.15.10/src/AbcSimplexDual.cpp0000644000076600007660000062376512240211604015216 0ustar coincoin/* $Id: AbcSimplexDual.cpp 1989 2013-11-11 17:27:32Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Notes on implementation of dual simplex algorithm. When dual feasible: If primal feasible, we are optimal. Otherwise choose an infeasible basic variable to leave basis (normally going to nearest bound) (B). We now need to find an incoming variable which will leave problem dual feasible so we get the row of the tableau corresponding to the basic variable (with the correct sign depending if basic variable above or below feasibility region - as that affects whether reduced cost on outgoing variable has to be positive or negative). We now perform a ratio test to determine which incoming variable will preserve dual feasibility (C). If no variable found then problem is infeasible (in primal sense). If there is a variable, we then perform pivot and repeat. Trivial? ------------------------------------------- A) How do we get dual feasible? If all variables have bounds then it is trivial to get feasible by putting non-basic variables to correct bounds. OSL did not have a phase 1/phase 2 approach but instead effectively put fake bounds on variables and this is the approach here, although I had hoped to make it cleaner. If there is a weight of X on getting dual feasible: Non-basic variables with negative reduced costs are put to lesser of their upper bound and their lower bound + X. Similarly, mutatis mutandis, for positive reduced costs. Free variables should normally be in basis, otherwise I have coding which may be able to come out (and may not be correct). In OSL, this weight was changed heuristically, here at present it is only increased if problem looks finished. If problem is feasible I check for unboundedness. If not unbounded we could play with going into primal. As long as weights increase any algorithm would be finite. B) Which outgoing variable to choose is a virtual base class. For difficult problems steepest edge is preferred while for very easy (large) problems we will need partial scan. C) Sounds easy, but this is hardest part of algorithm. 1) Instead of stopping at first choice, we may be able to flip that variable to other bound and if objective still improving choose again. These mini iterations can increase speed by orders of magnitude but we may need to go to more of a bucket choice of variable rather than looking at them one by one (for speed). 2) Accuracy. Reduced costs may be of wrong sign but less than tolerance. Pivoting on these makes objective go backwards. OSL modified cost so a zero move was made, Gill et al (in primal analogue) modified so a strictly positive move was made. It is not quite as neat in dual but that is what we try and do. The two problems are that re-factorizations can change reduced costs above and below tolerances and that when finished we need to reset costs and try again. 3) Degeneracy. Gill et al helps but may not be enough. We may need more. Also it can improve speed a lot if we perturb the costs significantly. References: Forrest and Goldfarb, Steepest-edge simplex algorithms for linear programming - Mathematical Programming 1992 Forrest and Tomlin, Implementing the simplex method for the Optimization Subroutine Library - IBM Systems Journal 1992 Gill, Murray, Saunders, Wright A Practical Anti-Cycling Procedure for Linear and Nonlinear Programming SOL report 1988 TODO: a) Better recovery procedures. At present I never check on forward progress. There is checkpoint/restart with reducing re-factorization frequency, but this is only on singular factorizations. b) Fast methods for large easy problems (and also the option for the code to automatically choose which method). c) We need to be able to stop in various ways for OSI - this is fairly easy. */ #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "AbcSimplexDual.hpp" #include "ClpEventHandler.hpp" #include "AbcSimplexFactorization.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "CoinFloatEqual.hpp" #include "AbcDualRowDantzig.hpp" #include "AbcDualRowSteepest.hpp" #include "ClpMessage.hpp" #include "ClpLinearObjective.hpp" class ClpSimplex; #include #include #include #include #include //#define CLP_DEBUG 1 #ifdef NDEBUG #define NDEBUG_CLP #endif #ifndef CLP_INVESTIGATE #define NDEBUG_CLP #endif // dual /* *** Method This is a vanilla version of dual simplex. It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of dualBound_ being given to getting dual feasible. In this version I have used the idea that this weight can be thought of as a fake bound. If the distance between the lower and upper bounds on a variable is less than the feasibility weight then we are always better off flipping to other bound to make dual feasible. If the distance is greater then we make up a fake bound dualBound_ away from one bound. If we end up optimal or primal infeasible, we check to see if bounds okay. If so we have finished, if not we increase dualBound_ and continue (after checking if unbounded). I am undecided about free variables - there is coding but I am not sure about it. At present I put them in basis anyway. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find outgoing variable. This will be changed to keep an updated list of infeasibilities (or squares if steepest edge). Also on easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure of the exact details. The flow of dual is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by flipping variables so dual feasible. If looks finished check fake dual bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot row (outgoing variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot row in tableau Choose incoming column. If we don't find one then we look primal infeasible so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find incoming column, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration (we will need to implement flagging of basic variables sometime) and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve flipping variables to stay dual feasible. } } At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot out option. Needs dantzig, uninitialized and full steepest edge options (can still use partial scan) May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. */ #define CLEAN_FIXED 0 // Startup part of dual (may be extended to other algorithms) // To force to follow another run put logfile name here and define //#define FORCE_FOLLOW #ifdef FORCE_FOLLOW static FILE * fpFollow = NULL; static const char * forceFile = NULL; static int force_in = -1; static int force_out = -1; static int force_way_in = -1; static int force_way_out = -1; static int force_iterations = 0; int force_argc=0; const char ** force_argv=NULL; #endif void AbcSimplexDual::startupSolve() { #ifdef FORCE_FOLLOW int ifld; for (ifld=1;ifld1.0e30) { abcUpper_[i]=abcLower_[i]+dualBound_; setFakeUpper(i); } } } assert (numberBasic==numberRows_); } #endif // initialize - no values pass and algorithm_ is -1 // put in standard form (and make row copy) // create modifiable copies of model rim and do optional scaling // If problem looks okay // Do initial factorization numberFake_ = 0; // Number of variables at fake bounds numberChanged_ = 0; // Number of variables with changed costs /// Initial coding here statusOfProblemInDual(0); } void AbcSimplexDual::finishSolve() { assert (problemStatus_ || !sumPrimalInfeasibilities_); } void AbcSimplexDual::gutsOfDual() { double largestPrimalError = 0.0; double largestDualError = 0.0; lastCleaned_ = 0; // last time objective or bounds cleaned up numberDisasters_=0; // This says whether to restore things etc //startupSolve(); // startup will have factorized so can skip // Start check for cycles abcProgress_.startCheck(); // Say change made on first iteration changeMade_ = 1; // Say last objective infinite //lastObjectiveValue_=-COIN_DBL_MAX; if ((stateOfProblem_&VALUES_PASS)!=0) { // modify costs so nonbasic dual feasible with fake for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { switch(getInternalStatus(iSequence)) { case basic: case AbcSimplex::isFixed: break; case isFree: case superBasic: //abcCost_[iSequence]-=djSaved_[iSequence]; //abcDj_[iSequence]-=djSaved_[iSequence]; djSaved_[iSequence]=0.0; break; case atLowerBound: if (djSaved_[iSequence]<0.0) { //abcCost_[iSequence]-=djSaved_[iSequence]; //abcDj_[iSequence]-=djSaved_[iSequence]; djSaved_[iSequence]=0.0; } break; case atUpperBound: if (djSaved_[iSequence]>0.0) { //abcCost_[iSequence]-=djSaved_[iSequence]; //abcDj_[iSequence]-=djSaved_[iSequence]; djSaved_[iSequence]=0.0; } break; } } } progressFlag_ = 0; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible */ int factorizationType=1; double pivotTolerance=abcFactorization_->pivotTolerance(); while (problemStatus_ < 0) { // If getting nowhere - return double limit = numberRows_ + numberColumns_; limit = 10000.0 +2000.0 * limit; #if ABC_NORMAL_DEBUG>0 if (numberIterations_ > limit) { printf("Set flag so ClpSimplexDual done\n"); abort(); } #endif bool disaster = false; if (disasterArea_ && disasterArea_->check()) { disasterArea_->saveInfo(); disaster = true; } if (numberIterations_>baseIteration_) { // may factorize, checks if problem finished statusOfProblemInDual(factorizationType); factorizationType=1; largestPrimalError = CoinMax(largestPrimalError, largestPrimalError_); largestDualError = CoinMax(largestDualError, largestDualError_); if (disaster) problemStatus_ = 3; } int saveNumberIterations=numberIterations_; // exit if victory declared if (problemStatus_ >= 0) break; // test for maximum iterations if (hitMaximumIterations()) { problemStatus_ = 3; break; } // Check event int eventStatus = eventHandler_->event(ClpEventHandler::endOfFactorization); if (eventStatus >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } if (!numberPrimalInfeasibilities_&&problemStatus_<0) { #if ABC_NORMAL_DEBUG>0 printf("Primal feasible - sum dual %g - go to primal\n",sumDualInfeasibilities_); #endif problemStatus_=10; break; } // Do iterations ? loop round #if PARTITION_ROW_COPY==1 stateOfProblem_ |= NEED_BASIS_SORT; #endif while (true) { #if PARTITION_ROW_COPY==1 if ((stateOfProblem_&NEED_BASIS_SORT)!=0) { int iVector=getAvailableArray(); abcMatrix_->sortUseful(usefulArray_[iVector]); setAvailableArray(iVector); stateOfProblem_ &= ~NEED_BASIS_SORT; } #endif problemStatus_=-1; if ((stateOfProblem_&VALUES_PASS)!=0) { assert (djSaved_-abcDj_==numberTotal_); abcDj_=djSaved_; djSaved_=NULL; } #if ABC_PARALLEL if (parallelMode_==0) { #endif whileIteratingSerial(); #if ABC_PARALLEL } else { #if ABC_PARALLEL==1 whileIteratingThread(); #else whileIteratingCilk(); #endif } #endif if ((stateOfProblem_&VALUES_PASS)!=0) { djSaved_=abcDj_; abcDj_=djSaved_-numberTotal_; } if (pivotRow_!=-100) { if (numberIterations_>saveNumberIterations||problemStatus_>=0) { if (problemStatus_==10&&abcFactorization_->pivots()&&numberTimesOptimal_<3) { factorizationType=5; problemStatus_=-4; if (!numberPrimalInfeasibilities_) factorizationType=9; } else if (problemStatus_==-2) { factorizationType=5; } break; } else if (abcFactorization_->pivots()||problemStatus_==-6|| pivotTolerancepivotTolerance()) { factorizationType=5; if (pivotTolerancepivotTolerance()) { pivotTolerance=abcFactorization_->pivotTolerance(); if (!abcFactorization_->pivots()) abcFactorization_->minimumPivotTolerance(CoinMin(0.25,1.05*abcFactorization_->minimumPivotTolerance())); } break; } else { bool tryFake=numberAtFakeBound()>0&¤tDualBound_<1.0e17; if (problemStatus_==-5||tryFake) { if (numberTimesOptimal_>10) problemStatus_=4; numberTimesOptimal_++; int numberChanged=-1; if (numberFlagged_) { numberFlagged_=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) { clearFlagged(iPivot); } } numberChanged=0; } else if (tryFake) { double dummyChange; numberChanged = changeBounds(0,dummyChange); if (numberChanged>0) { handler_->message(CLP_DUAL_ORIGINAL, messages_) << CoinMessageEol; bounceTolerances(3 /*(numberChanged>0) ? 3 : 1*/); // temp #if ABC_NORMAL_DEBUG>0 //printf("should not need to break out of loop\n"); #endif abcProgress_.reset(); break; } else if (numberChanged<-1) { // some flipped bounceTolerances(3); abcProgress_.reset(); } } else if (numberChanged<0) { // what now printf("No iterations since last inverts A - nothing done - think\n"); abort(); } } else if (problemStatus_!=-4) { // what now printf("No iterations since last inverts B - nothing done - think\n"); abort(); } } } else { // end of values pass // we need to tell statusOf.. to restore costs etc // and take off flag bounceTolerances(2); assert (!solution_); delete [] solution_; solution_=NULL; gutsOfSolution(3); makeNonFreeVariablesDualFeasible(); stateOfProblem_ &= ~VALUES_PASS; problemStatus_=-2; factorizationType=5; break; } } if (problemStatus_ == 1 && (progressFlag_&8) != 0 && fabs(rawObjectiveValue_) > 1.0e10 ) { #if ABC_NORMAL_DEBUG>0 printf("fix looks infeasible when has been\n"); // goto primal #endif problemStatus_ = 10; // infeasible - but has looked feasible } if (!problemStatus_ && abcFactorization_->pivots()) { gutsOfSolution(1); // need to compute duals //computeInternalObjectiveValue(); checkCutoff(true); } } largestPrimalError_ = largestPrimalError; largestDualError_ = largestDualError; } /// The duals are updated by the given arrays. static void updateDualsInDualBit2(CoinPartitionedVector & row, double * COIN_RESTRICT djs, double theta, int iBlock) { int offset=row.startPartition(iBlock); double * COIN_RESTRICT work=row.denseVector()+offset; const int * COIN_RESTRICT which=row.getIndices()+offset; int number=row.getNumElements(iBlock); for (int i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; work[i] = 0.0; double value = djs[iSequence] - theta * alphaI; djs[iSequence] = value; } row.setNumElementsPartition(iBlock,0); } static void updateDualsInDualBit(CoinPartitionedVector & row, double * djs, double theta, int numberBlocks) { for (int iBlock=1;iBlockusefulArray(3)->compact(); CoinPartitionedVector & array=usefulArray_[arrayForTableauRow_]; //array.compact(); int numberBlocks=array.getNumPartitions(); int number=array.getNumElements(); if(numberBlocks) { if (number>100) { updateDualsInDualBit(array,abcDj_,theta_,numberBlocks); } else { for (int iBlock=0;iBlock= 0) { // make sure valid int returnValue = firstFree_; int iColumn = firstFree_ + 1; #ifdef PAN if (fakeSuperBasic(firstFree_)<0) { // somehow cleaned up returnValue=-1; for (; iColumn < numberTotal_; iColumn++) { if (getInternalStatus(iColumn) == isFree|| getInternalStatus(iColumn) == superBasic) { if (fakeSuperBasic(iColumn)>=0) { if (fabs(abcDj_[iColumn]) > 1.0e2 * dualTolerance_) break; } } } if (iColumn=0) { #endif if (fabs(abcDj_[iColumn]) > dualTolerance_) break; #ifdef PAN } #endif } } firstFree_ = iColumn; if (firstFree_ == numberTotal_) firstFree_ = -1; return returnValue; } else { return -1; } } /* Chooses dual pivot row For easy problems we can just choose one of the first rows we look at */ void AbcSimplexDual::dualPivotRow() { //int lastPivotRow=pivotRow_; pivotRow_=-1; const double * COIN_RESTRICT lowerBasic = lowerBasic_; const double * COIN_RESTRICT upperBasic = upperBasic_; const double * COIN_RESTRICT solutionBasic = solutionBasic_; const int * COIN_RESTRICT pivotVariable=abcPivotVariable_; freeSequenceIn_=-1; double worstValuesPass=0.0; if ((stateOfProblem_&VALUES_PASS)!=0) { for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { switch(getInternalStatus(iSequence)) { case basic: #if ABC_NORMAL_DEBUG>0 if (fabs(abcDj_[iSequence])>1.0e-6) printf("valuespass basic dj %d status %d dj %g\n",iSequence, getInternalStatus(iSequence),abcDj_[iSequence]); #endif break; case AbcSimplex::isFixed: break; case isFree: case superBasic: #if ABC_NORMAL_DEBUG>0 if (fabs(abcDj_[iSequence])>1.0e-6) printf("Bad valuespass dj %d status %d dj %g\n",iSequence, getInternalStatus(iSequence),abcDj_[iSequence]); #endif break; case atLowerBound: #if ABC_NORMAL_DEBUG>0 if (abcDj_[iSequence]<-1.0e-6) printf("Bad valuespass dj %d status %d dj %g\n",iSequence, getInternalStatus(iSequence),abcDj_[iSequence]); #endif break; case atUpperBound: #if ABC_NORMAL_DEBUG>0 if (abcDj_[iSequence]>1.0e-6) printf("Bad valuespass dj %d status %d dj %g\n",iSequence, getInternalStatus(iSequence),abcDj_[iSequence]); #endif break; } } // get worst basic dual - later do faster using steepest infeasibility array // does not have to be worst - just bad int iWorst=-1; double worst=dualTolerance_; for (int i=0;iworst) { iWorst=i; worst=fabs(abcDj_[iSequence]); } } if (iWorst>=0) { pivotRow_=iWorst; worstValuesPass=abcDj_[abcPivotVariable_[iWorst]]; } else { // factorize and clean up costs pivotRow_=-100; return; } } if (false&&numberFreeNonBasic_>abcFactorization_->maximumPivots()) { lastFirstFree_=-1; firstFree_=-1; } if (firstFree_>=0) { // free int nextFree = nextSuperBasic(); if (nextFree>=0) { freeSequenceIn_=nextFree; // **** should skip price (and maybe weights update) // unpack vector and find a good pivot unpack(usefulArray_[arrayForBtran_], nextFree); abcFactorization_->updateColumn(usefulArray_[arrayForBtran_]); double * COIN_RESTRICT work = usefulArray_[arrayForBtran_].denseVector(); int number = usefulArray_[arrayForBtran_].getNumElements(); int * COIN_RESTRICT which = usefulArray_[arrayForBtran_].getIndices(); double bestFeasibleAlpha = 0.0; int bestFeasibleRow = -1; double bestInfeasibleAlpha = 0.0; int bestInfeasibleRow = -1; // Go for big infeasibilities unless big changes double maxInfeas = (fabs(dualOut_)>1.0e3) ? 0.001 : 1.0e6; for (int i = 0; i < number; i++) { int iRow = which[i]; double alpha = fabs(work[iRow]); if (alpha > 1.0e-3) { double value = solutionBasic[iRow]; double lower = lowerBasic[iRow]; double upper = upperBasic[iRow]; double infeasibility = 0.0; if (value > upper) infeasibility = value - upper; else if (value < lower) infeasibility = lower - value; infeasibility=CoinMin(maxInfeas,infeasibility); if (infeasibility * alpha > bestInfeasibleAlpha && alpha > 1.0e-1) { if (!flagged(pivotVariable[iRow])) { bestInfeasibleAlpha = infeasibility * alpha; bestInfeasibleRow = iRow; } } if (alpha > bestFeasibleAlpha && (lower > -1.0e20 || upper < 1.0e20)) { bestFeasibleAlpha = alpha; bestFeasibleRow = iRow; } } } if (bestInfeasibleRow >= 0) pivotRow_ = bestInfeasibleRow; else if (bestFeasibleAlpha > 1.0e-2) pivotRow_ = bestFeasibleRow; usefulArray_[arrayForBtran_].clear(); if (pivotRow_<0) { // no good freeSequenceIn_=-1; if (!abcFactorization_->pivots()) { lastFirstFree_=-1; firstFree_=-1; } } } } if (pivotRow_<0) { // put back so can test //pivotRow_=lastPivotRow; // get pivot row using whichever method it is pivotRow_ = abcDualRowPivot_->pivotRow(); } if (pivotRow_ >= 0) { sequenceOut_ = pivotVariable[pivotRow_]; valueOut_ = solutionBasic[pivotRow_]; lowerOut_ = lowerBasic[pivotRow_]; upperOut_ = upperBasic[pivotRow_]; // if we have problems we could try other way and hope we get a // zero pivot? if (valueOut_ > upperOut_) { directionOut_ = -1; dualOut_ = valueOut_ - upperOut_; } else if (valueOut_ < lowerOut_) { directionOut_ = 1; dualOut_ = lowerOut_ - valueOut_; } else { // odd (could be free) - it's feasible - go to nearest if (valueOut_ - lowerOut_ < upperOut_ - valueOut_) { directionOut_ = 1; dualOut_ = lowerOut_ - valueOut_; } else { directionOut_ = -1; dualOut_ = valueOut_ - upperOut_; } } if (worstValuesPass) { // in values pass so just use sign of dj // We don't want to go through any barriers so set dualOut low // free variables will never be here // need to think about tolerances with inexact solutions // could try crashing in variables away from bounds and with near zero djs // pivot to take out bad slack and increase objective double fakeValueOut=solution_[sequenceOut_]; dualOut_ = 1.0e-10; if (upperOut_>lowerOut_|| fabs(fakeValueOut-upperOut_)<100.0*primalTolerance_) { if (abcDj_[sequenceOut_] > 0.0) { directionOut_ = 1; } else { directionOut_ = -1; } } else { // foolishly trust primal solution if (fakeValueOut > upperOut_) { directionOut_ = -1; } else { directionOut_ = 1; } } #if 1 // make sure plausible but only when fake primals stored if (directionOut_ < 0 && fabs(fakeValueOut - upperOut_) > dualBound_ + primalTolerance_) { if (fabs(fakeValueOut - upperOut_) > fabs(fakeValueOut - lowerOut_)) directionOut_ = 1; } else if (directionOut_ > 0 && fabs(fakeValueOut - lowerOut_) > dualBound_ + primalTolerance_) { if (fabs(fakeValueOut - upperOut_) < fabs(fakeValueOut - lowerOut_)) directionOut_ = -1; } #endif } #if ABC_NORMAL_DEBUG>3 assert(dualOut_ >= 0.0); #endif } else { sequenceOut_=-1; } alpha_=0.0; upperTheta_=COIN_DBL_MAX; return ; } // Checks if any fake bounds active - if so returns number and modifies // dualBound_ and everything. // Free variables will be left as free // Returns number of bounds changed if >=0 // Returns -1 if not initialize and no effect // Fills in changeVector which can be used to see if unbounded // initialize is 0 or 3 // and cost of change vector int AbcSimplexDual::changeBounds(int initialize, double & changeCost) { assert (initialize==0||initialize==1||initialize==3||initialize==4); numberFake_ = 0; double * COIN_RESTRICT abcLower = abcLower_; double * COIN_RESTRICT abcUpper = abcUpper_; double * COIN_RESTRICT abcSolution = abcSolution_; double * COIN_RESTRICT abcCost = abcCost_; if (!initialize) { int numberInfeasibilities; double newBound; newBound = 5.0 * currentDualBound_; numberInfeasibilities = 0; changeCost = 0.0; // put back original bounds and then check CoinAbcMemcpy(abcLower,lowerSaved_,numberTotal_); CoinAbcMemcpy(abcUpper,upperSaved_,numberTotal_); const double * COIN_RESTRICT dj = abcDj_; int iSequence; // bounds will get bigger - just look at ones at bounds int numberFlipped=0; double checkBound=1.000000000001*currentDualBound_; for (iSequence = 0; iSequence < numberTotal_; iSequence++) { double lowerValue = abcLower[iSequence]; double upperValue = abcUpper[iSequence]; double value = abcSolution[iSequence]; setFakeBound(iSequence, AbcSimplexDual::noFake); switch(getInternalStatus(iSequence)) { case basic: case AbcSimplex::isFixed: break; case isFree: case superBasic: break; case atUpperBound: if (fabs(value - upperValue) > primalTolerance_) { // can we flip if (value-lowerValue-currentDualTolerance_) { abcSolution_[iSequence]=lowerValue; setInternalStatus(iSequence,atLowerBound); numberFlipped++; } else { numberInfeasibilities++; } } break; case atLowerBound: if (fabs(value - lowerValue) > primalTolerance_) { // can we flip if (upperValue-valuemessage(CLP_DUAL_CHECKB, messages_) << newBound << CoinMessageEol; int iSequence; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { double lowerValue = abcLower[iSequence]; double upperValue = abcUpper[iSequence]; double newLowerValue; double newUpperValue; Status status = getInternalStatus(iSequence); if (status == atUpperBound || status == atLowerBound) { double value = abcSolution[iSequence]; if (value - lowerValue <= upperValue - value) { newLowerValue = CoinMax(lowerValue, value - 0.666667 * newBound); newUpperValue = CoinMin(upperValue, newLowerValue + newBound); } else { newUpperValue = CoinMin(upperValue, value + 0.666667 * newBound); newLowerValue = CoinMax(lowerValue, newUpperValue - newBound); } abcLower[iSequence] = newLowerValue; abcUpper[iSequence] = newUpperValue; if (newLowerValue > lowerValue) { if (newUpperValue < upperValue) { setFakeBound(iSequence, AbcSimplexDual::bothFake); #ifdef CLP_INVESTIGATE abort(); // No idea what should happen here - I have never got here #endif numberFake_++; } else { setFakeBound(iSequence, AbcSimplexDual::lowerFake); assert (abcLower[iSequence]>lowerSaved_[iSequence]); assert (abcUpper[iSequence]==upperSaved_[iSequence]); numberFake_++; } } else { if (newUpperValue < upperValue) { setFakeBound(iSequence, AbcSimplexDual::upperFake); assert (abcLower[iSequence]==lowerSaved_[iSequence]); assert (abcUpper[iSequence]0 printf("new dual bound %g\n",currentDualBound_); #endif } else { numberInfeasibilities = -1-numberFlipped; } return numberInfeasibilities; } else { int iSequence; if (initialize == 3) { for (iSequence = 0; iSequence < numberTotal_; iSequence++) { #if ABC_NORMAL_DEBUG>1 int bad=-1; if (getFakeBound(iSequence)==noFake) { if (abcLower_[iSequence]!=lowerSaved_[iSequence]|| abcUpper_[iSequence]!=upperSaved_[iSequence]) bad=0; } else if (getFakeBound(iSequence)==lowerFake) { if (abcLower_[iSequence]==lowerSaved_[iSequence]|| abcUpper_[iSequence]!=upperSaved_[iSequence]) bad=1; } else if (getFakeBound(iSequence)==upperFake) { if (abcLower_[iSequence]!=lowerSaved_[iSequence]|| abcUpper_[iSequence]==upperSaved_[iSequence]) bad=2; } else { if (abcLower_[iSequence]==lowerSaved_[iSequence]|| abcUpper_[iSequence]==upperSaved_[iSequence]) bad=3; } if (bad>=0) printf("%d status %d l %g,%g u %g,%g\n",iSequence,internalStatus_[iSequence], abcLower_[iSequence],lowerSaved_[iSequence], abcUpper_[iSequence],upperSaved_[iSequence]); #endif setFakeBound(iSequence, AbcSimplexDual::noFake); } CoinAbcMemcpy(abcLower_,lowerSaved_,numberTotal_); CoinAbcMemcpy(abcUpper_,upperSaved_,numberTotal_); } double testBound = /*0.999999 **/ currentDualBound_; for (iSequence = 0; iSequence < numberTotal_; iSequence++) { Status status = getInternalStatus(iSequence); if (status == atUpperBound || status == atLowerBound) { double lowerValue = abcLower[iSequence]; double upperValue = abcUpper[iSequence]; double value = abcSolution[iSequence]; if (lowerValue > -largeValue_ || upperValue < largeValue_) { if (true || lowerValue - value > -0.5 * currentDualBound_ || upperValue - value < 0.5 * currentDualBound_) { if (fabs(lowerValue - value) <= fabs(upperValue - value)) { if (upperValue > lowerValue + testBound) { if (getFakeBound(iSequence) == AbcSimplexDual::noFake) numberFake_++; abcUpper[iSequence] = lowerValue + currentDualBound_; double difference = upperSaved_[iSequence]-abcUpper[iSequence]; if (difference<1.0e-10*(1.0+fabs(upperSaved_[iSequence])+dualBound_)) abcUpper[iSequence] = upperSaved_[iSequence]; assert (abcUpper[iSequence]<=upperSaved_[iSequence]+1.0e-3*currentDualBound_); assert (abcLower[iSequence]>=lowerSaved_[iSequence]-1.0e-3*currentDualBound_); if (upperSaved_[iSequence]-abcUpper[iSequence]> abcLower[iSequence]-lowerSaved_[iSequence]) { setFakeBound(iSequence, AbcSimplexDual::upperFake); assert (abcLower[iSequence]==lowerSaved_[iSequence]); assert (abcUpper[iSequence]lowerSaved_[iSequence]); assert (abcUpper[iSequence]==upperSaved_[iSequence]); } } } else { if (lowerValue < upperValue - testBound) { if (getFakeBound(iSequence) == AbcSimplexDual::noFake) numberFake_++; abcLower[iSequence] = upperValue - currentDualBound_; double difference = abcLower[iSequence]-lowerSaved_[iSequence]; if (difference<1.0e-10*(1.0+fabs(lowerSaved_[iSequence])+dualBound_)) abcLower[iSequence] = lowerSaved_[iSequence]; assert (abcUpper[iSequence]<=upperSaved_[iSequence]+1.0e-3*currentDualBound_); assert (abcLower[iSequence]>=lowerSaved_[iSequence]-1.0e-3*currentDualBound_); if (upperSaved_[iSequence]-abcUpper[iSequence]> abcLower[iSequence]-lowerSaved_[iSequence]) { setFakeBound(iSequence, AbcSimplexDual::upperFake); //assert (abcLower[iSequence]==lowerSaved_[iSequence]); abcLower[iSequence]=CoinMax(abcLower[iSequence],lowerSaved_[iSequence]); assert (abcUpper[iSequence]lowerSaved_[iSequence]); //assert (abcUpper[iSequence]==upperSaved_[iSequence]); abcUpper[iSequence]=CoinMin(abcUpper[iSequence],upperSaved_[iSequence]); } } } } else { if (getFakeBound(iSequence) == AbcSimplexDual::noFake) numberFake_++; abcLower[iSequence] = -0.5 * currentDualBound_; abcUpper[iSequence] = 0.5 * currentDualBound_; setFakeBound(iSequence, AbcSimplexDual::bothFake); abort(); } if (status == atUpperBound) abcSolution[iSequence] = abcUpper[iSequence]; else abcSolution[iSequence] = abcLower[iSequence]; } else { // set non basic free variables to fake bounds // I don't think we should ever get here CoinAssert(!("should not be here")); abcLower[iSequence] = -0.5 * currentDualBound_; abcUpper[iSequence] = 0.5 * currentDualBound_; setFakeBound(iSequence, AbcSimplexDual::bothFake); numberFake_++; setInternalStatus(iSequence, atUpperBound); abcSolution[iSequence] = 0.5 * currentDualBound_; } } else if (status == basic) { // make sure not at fake bound and bounds correct setFakeBound(iSequence, AbcSimplexDual::noFake); double gap = abcUpper[iSequence] - abcLower[iSequence]; if (gap > 0.5 * currentDualBound_ && gap < 2.0 * currentDualBound_) { abcLower[iSequence] = lowerSaved_[iSequence];; abcUpper[iSequence] = upperSaved_[iSequence];; } } } return 0; } } /* order of variables is a) atLo/atUp b) free/superBasic pre pass done in AbcMatrix to get possibles dj's will be stored in a parallel array (tempArray) for first pass this pass to be done inside AbcMatrix then as now use perturbationArray as variable tolerance idea is to use large tolerances and then balance and reduce every so often this should be in conjunction with dualBound changes variables always stay at bounds on accuracy issues - only deliberate flips allowed variable tolerance should be 0.8-1.0 desired (at end) use going to clpMatrix_ as last resort */ /* Array has tableau row Puts candidates in list Returns upper theta (infinity if no pivot) and may set sequenceIn_ if free */ void AbcSimplexDual::dualColumn1(bool doAll) { const CoinIndexedVector & update = usefulArray_[arrayForBtran_]; CoinPartitionedVector & tableauRow = usefulArray_[arrayForTableauRow_]; CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; if ((stateOfProblem_&VALUES_PASS)==0) upperTheta_=1.0e31; else upperTheta_=fabs(abcDj_[sequenceOut_])-0.5*dualTolerance_; assert (upperTheta_>0.0); if (!doAll) upperTheta_ = abcMatrix_->dualColumn1(update,tableauRow,candidateList); else upperTheta_ = dualColumn1B(); //tableauRow.compact(); //candidateList.compact(); //tableauRow.setPackedMode(true); //candidateList.setPackedMode(true); } /* Array has tableau row Puts candidates in list Returns upper theta (infinity if no pivot) and may set sequenceIn_ if free */ double AbcSimplexDual::dualColumn1A() { const CoinIndexedVector & update = usefulArray_[arrayForBtran_]; CoinPartitionedVector & tableauRow = usefulArray_[arrayForTableauRow_]; CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; int numberRemaining = 0; double upperTheta = upperTheta_; // pivot elements double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); // indices int * COIN_RESTRICT indexCandidate = candidateList.getIndices(); const double * COIN_RESTRICT abcDj = abcDj_; //const double * COIN_RESTRICT abcPerturbation = abcPerturbation_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; const double * COIN_RESTRICT pi=update.denseVector(); const int * COIN_RESTRICT piIndex = update.getIndices(); int number = update.getNumElements(); int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); assert (!tableauRow.getNumElements()); int numberNonZero=0; // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = currentAcceptablePivot_; double dualT=-currentDualTolerance_; const double multiplier[] = { 1.0, -1.0}; if (ordinaryVariables_) { for (int i=0;i= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iRow; } } } } else { double badFree = 0.0; double freePivot = currentAcceptablePivot_; alpha_ = 0.0; // We can also see if infeasible or pivoting on free for (int i=0;i= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iRow; } } else if ((type&7)<6) { //} else if (getInternalStatus(iRow)==isFree||getInternalStatus(iRow)==superBasic) { bool keep; index[numberNonZero]=iRow; array[numberNonZero++]=piValue; bestPossible = CoinMax(bestPossible, fabs(piValue)); double oldValue = abcDj[iRow]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iRow+addSequence)==isFree&&fabs(piValue)<1.0e-3) //break; if (oldValue > currentDualTolerance_) { keep = true; } else if (oldValue < -currentDualTolerance_) { keep = true; } else { if (fabs(piValue) > CoinMax(10.0 * currentAcceptablePivot_, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(piValue)); } } if (keep) { // free - choose largest if (fabs(piValue) > freePivot) { freePivot = fabs(piValue); sequenceIn_ = iRow; theta_ = oldValue / piValue; alpha_ = piValue; } } } } } //tableauRow.setNumElements(numberNonZero); //candidateList.setNumElements(numberRemaining); tableauRow.setNumElementsPartition(0,numberNonZero); candidateList.setNumElementsPartition(0,numberRemaining); if (!numberRemaining && sequenceIn_ < 0&&upperTheta_>1.0e29) { return COIN_DBL_MAX; // Looks infeasible } else { return upperTheta; } } /* Array has tableau row Puts candidates in list Returns upper theta (infinity if no pivot) and may set sequenceIn_ if free */ double AbcSimplexDual::dualColumn1B() { CoinPartitionedVector & tableauRow = usefulArray_[arrayForTableauRow_]; CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; tableauRow.compact(); candidateList.clearAndReset(); tableauRow.setPackedMode(true); candidateList.setPackedMode(true); int numberRemaining = 0; double upperTheta = upperTheta_; // pivot elements double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); // indices int * COIN_RESTRICT indexCandidate = candidateList.getIndices(); const double * COIN_RESTRICT abcDj = abcDj_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); int numberNonZero=tableauRow.getNumElements(); // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = currentAcceptablePivot_; double dualT=-currentDualTolerance_; const double multiplier[] = { 1.0, -1.0}; if (ordinaryVariables_) { for (int i=0;izeroTolerance_) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } } } else { double badFree = 0.0; double freePivot = currentAcceptablePivot_; double currentDualTolerance = currentDualTolerance_; for (int i=0;izeroTolerance_) { if ((iStatus&4)==0) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } if (keep) { #ifdef PAN if (fakeSuperBasic(iSequence)>=0) { #endif if (iSequence==freeSequenceIn_) tableauValue=COIN_DBL_MAX; // free - choose largest if (fabs(tableauValue) > fabs(freePivot)) { freePivot = tableauValue; sequenceIn_ = iSequence; theta_ = oldValue / tableauValue; alpha_ = tableauValue; } #ifdef PAN } #endif } } } } } } candidateList.setNumElements(numberRemaining); if (!numberRemaining && sequenceIn_ < 0&&upperTheta_>1.0e29) { return COIN_DBL_MAX; // Looks infeasible } else { return upperTheta; } } //#define MORE_CAREFUL //#define PRINT_RATIO_PROGRESS #define MINIMUMTHETA 1.0e-18 #define MAXTRY 100 #define TOL_TYPE -1 #if TOL_TYPE==-1 #define useTolerance1() (0.0) #define useTolerance2() (0.0) #define goToTolerance1() (0.0) #define goToTolerance2() (0.0) #elif TOL_TYPE==0 #define useTolerance1() (currentDualTolerance_) #define useTolerance2() (currentDualTolerance_) #define goToTolerance1() (0.0) #define goToTolerance2() (0.0) #elif TOL_TYPE==1 #define useTolerance1() (perturbedTolerance) #define useTolerance2() (0.0) #define goToTolerance1() (0.0) #define goToTolerance2() (0.0) #elif TOL_TYPE==2 #define useTolerance1() (perturbedTolerance) #define useTolerance2() (perturbedTolerance) #define goToTolerance1() (0.0) #define goToTolerance2() (0.0) #elif TOL_TYPE==3 #define useTolerance1() (perturbedTolerance) #define useTolerance2() (perturbedTolerance) #define goToTolerance1() (perturbedTolerance) #define goToTolerance2() (0.0) #elif TOL_TYPE==4 #define useTolerance1() (perturbedTolerance) #define useTolerance2() (perturbedTolerance) #define goToTolerance1() (perturbedTolerance) #define goToTolerance2() (perturbedTolerance) #else XXXX #endif #if CLP_CAN_HAVE_ZERO_OBJ<2 #define MODIFYCOST 2 #endif #define DONT_MOVE_OBJECTIVE static void dualColumn2Bit(AbcSimplexDual * dual,dualColumnResult * result, int numberBlocks) { for (int iBlock=1;iBlockdualColumn2First(result[iBlock]); } dual->dualColumn2First(result[0]); cilk_sync; } void AbcSimplexDual::dualColumn2First(dualColumnResult & result) { CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; CoinPartitionedVector & flipList = usefulArray_[arrayForFlipBounds_]; int iBlock=result.block; int numberSwapped = result.numberSwapped; int numberRemaining = result.numberRemaining; double tentativeTheta=result.tentativeTheta; // pivot elements double * COIN_RESTRICT array=candidateList.denseVector(); // indices int * COIN_RESTRICT indices = candidateList.getIndices(); const double * COIN_RESTRICT abcLower = abcLower_; const double * COIN_RESTRICT abcUpper = abcUpper_; const double * COIN_RESTRICT abcDj = abcDj_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; const double multiplier[] = { 1.0, -1.0}; // For list of flipped int * COIN_RESTRICT flippedIndex = flipList.getIndices(); double * COIN_RESTRICT flippedElement = flipList.denseVector(); // adjust //if (iBlock>=0) { int offset=candidateList.startPartition(iBlock); assert(offset==flipList.startPartition(iBlock)); array += offset; indices+=offset; flippedIndex+=offset; flippedElement+=offset; //} double thruThis = 0.0; double bestPivot = currentAcceptablePivot_; int bestSequence = -1; int numberInList=numberRemaining; numberRemaining = 0; double upperTheta = 1.0e50; double increaseInThis = 0.0; //objective increase in this loop for (int i = 0; i < numberInList; i++) { int iSequence = indices[i]; assert (getInternalStatus(iSequence) != isFree && getInternalStatus(iSequence) != superBasic); int iStatus = internalStatus[iSequence] & 3; // treat as if at lower bound double mult = multiplier[iStatus]; double alpha = array[i]; double oldValue = abcDj[iSequence]*mult; double value = oldValue - tentativeTheta * alpha; assert (alpha>0.0); //double perturbedTolerance = abcPerturbation[iSequence]; if (value < -currentDualTolerance_) { // possible here or could go through double range = abcUpper[iSequence] - abcLower[iSequence]; thruThis += range * alpha; increaseInThis += (oldValue - useTolerance1()) * range; // goes on swapped list (also means candidates if too many) flippedElement[numberSwapped] = alpha; flippedIndex[numberSwapped++] = iSequence; if (alpha > bestPivot) { bestPivot = alpha; bestSequence = iSequence; } } else { // won't go through this time value = oldValue - upperTheta * alpha; if (value < -currentDualTolerance_ && alpha >= currentAcceptablePivot_) upperTheta = (oldValue + currentDualTolerance_) / alpha; array[numberRemaining] = alpha; indices[numberRemaining++] = iSequence; } } result.bestEverPivot=bestPivot; result.sequence=bestSequence; result.numberSwapped=numberSwapped; result.numberRemaining=numberRemaining; result.thruThis=thruThis; result.increaseInThis=increaseInThis; result.theta=upperTheta; } void AbcSimplexDual::dualColumn2Most(dualColumnResult & result) { CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; CoinPartitionedVector & flipList = usefulArray_[arrayForFlipBounds_]; int numberBlocksReal=candidateList.getNumPartitions(); flipList.setPartitions(numberBlocksReal,candidateList.startPartitions()); int numberBlocks; if (!numberBlocksReal) numberBlocks=1; else numberBlocks=numberBlocksReal; //usefulArray_[arrayForTableauRow_].compact(); //candidateList.compact(); int numberSwapped = 0; int numberRemaining = candidateList.getNumElements(); double totalThru = 0.0; // for when variables flip int sequenceIn=-1; double bestEverPivot = currentAcceptablePivot_; // If we think we need to modify costs (not if something from broad sweep) bool modifyCosts = false; // Increase in objective due to swapping bounds (may be negative) double increaseInObjective = 0.0; // pivot elements double * COIN_RESTRICT array=candidateList.denseVector(); // indices int * COIN_RESTRICT indices = candidateList.getIndices(); const double * COIN_RESTRICT abcLower = abcLower_; const double * COIN_RESTRICT abcUpper = abcUpper_; //const double * COIN_RESTRICT abcSolution = abcSolution_; const double * COIN_RESTRICT abcDj = abcDj_; //const double * COIN_RESTRICT abcPerturbation = abcPerturbation_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess const double multiplier[] = { 1.0, -1.0}; // For list of flipped int numberLastSwapped=0; int * COIN_RESTRICT flippedIndex = flipList.getIndices(); double * COIN_RESTRICT flippedElement = flipList.denseVector(); // If sum of bad small pivots too much #ifdef MORE_CAREFUL bool badSumPivots = false; #endif // not free int lastSequence = -1; double lastTheta = 0.0; double lastPivotValue = 0.0; double thisPivotValue=0.0; // if free then always choose , otherwise ... double theta = 1.0e50; // now flip flop between spare arrays until reasonable theta tentativeTheta = CoinMax(10.0 * upperTheta_, 1.0e-7); // loops increasing tentative theta until can't go through #ifdef PRINT_RATIO_PROGRESS int iPass=0; #endif dualColumnResult result2[8]; for (int iBlock=0;iBlockbestPivot) { bestPivot=result2[iBlock].bestEverPivot; bestSequence=result2[iBlock].sequence; } numberSwapped+=result2[iBlock].numberSwapped; numberRemaining+=result2[iBlock].numberRemaining; thruThis+=result2[iBlock].thruThis; increaseInThis+=result2[iBlock].increaseInThis; if (upperTheta>result2[iBlock].theta) upperTheta=result2[iBlock].theta; } // end of pass #ifdef PRINT_RATIO_PROGRESS iPass++; printf("Iteration %d pass %d dualOut %g thru %g increase %g numberRemain %d\n", numberIterations_,iPass,fabs(dualOut_),totalThru+thruThis,increaseInObjective+increaseInThis, numberRemaining); #endif if (totalThru + thruThis > fabs(dualOut_)-fabs(1.0e-9*dualOut_)-1.0e-12 || (increaseInObjective + increaseInThis < 0.0&&bestSequence>=0) || !numberRemaining) { // We should be pivoting in this batch // so compress down to this lot numberRemaining=0; candidateList.clearAndReset(); for (int iBlock=0;iBlock0.0); //double perturbedTolerance = abcPerturbation[iSequence]; if (value < -currentDualTolerance_) { if (alpha >= currentAcceptablePivot_) { upperTheta = (oldValue + currentDualTolerance_) / alpha; } } } bestPivot = currentAcceptablePivot_; sequenceIn = -1; double largestPivot = currentAcceptablePivot_; // Sum of bad small pivots #ifdef MORE_CAREFUL double sumBadPivots = 0.0; badSumPivots = false; #endif // Make sure upperTheta will work (-O2 and above gives problems) upperTheta *= 1.0000000001; for (int i = 0; i < numberInList; i++) { int iSequence = indices[i]; int iStatus = internalStatus[iSequence] & 3; // treat as if at lower bound double mult = multiplier[iStatus]; double alpha = array[i]; double oldValue = abcDj[iSequence]*mult; double value = oldValue - upperTheta * alpha; assert (alpha>0.0); //double perturbedTolerance = abcPerturbation[iSequence]; double badDj = 0.0; if (value <= 0.0) { // add to list of swapped flippedElement[numberSwapped] = alpha; flippedIndex[numberSwapped++] = iSequence; badDj = oldValue - useTolerance2(); // select if largest pivot bool take = (alpha > bestPivot); #ifdef MORE_CAREFUL if (alpha < currentAcceptablePivot_ && upperTheta < 1.0e20) { if (value < -currentDualTolerance_) { double gap = abcUpper[iSequence] - abcLower[iSequence]; if (gap < 1.0e20) sumBadPivots -= value * gap; else sumBadPivots += 1.0e20; //printf("bad %d alpha %g dj at lower %g\n", // iSequence,alpha,value); } } #endif if (take&&flagged(iSequence)) { if (bestPivot>currentAcceptablePivot_) take=false; } if (take) { sequenceIn = iSequence; thisPivotValue=alpha; bestPivot = alpha; if (flagged(iSequence)) bestPivot=currentAcceptablePivot_; bestSequence = iSequence; theta = (oldValue+goToTolerance1()) / alpha; //assert (oldValue==abcDj[iSequence]); largestPivot = CoinMax(largestPivot, 0.5 * bestPivot); } double range = abcUpper[iSequence] - abcLower[iSequence]; thruThis += range * fabs(alpha); increaseInThis += badDj * range; } else { // add to list of remaining array[numberRemaining] = alpha; indices[numberRemaining++] = iSequence; } } #ifdef MORE_CAREFUL // If we have done pivots and things look bad set alpha_ 0.0 to force factorization if (sumBadPivots > 1.0e4) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 1) printf("maybe forcing re-factorization - sum %g %d pivots\n", sumBadPivots, abcFactorization_->pivots()); #endif if(abcFactorization_->pivots() > 3) { badSumPivots = true; #ifdef PRINT_RATIO_PROGRESS printf("maybe forcing re-factorization - sum %g %d pivots\n", sumBadPivots, abcFactorization_->pivots()); #endif break; } } #endif // If we stop now this will be increase in objective (I think) double increase = (fabs(dualOut_) - totalThru) * theta; increase += increaseInObjective; if (theta < 0.0) thruThis += fabs(dualOut_); // force using this one if (((increaseInObjective < 0.0 && increase < 0.0)|| (theta>1.0e9 && lastTheta < 1.0e-5)) && lastSequence >= 0) { // back // We may need to be more careful - we could do by // switch so we always do fine grained? bestPivot = 0.0; bestSequence=-1; } else { // add in totalThru += thruThis; increaseInObjective += increaseInThis; lastTheta=theta; } if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && (bestPivot < 1.0e-3 || totalThru * 2.0 > fabs(dualOut_))) { // back to previous one sequenceIn = lastSequence; thisPivotValue=lastPivotValue; #ifdef PRINT_RATIO_PROGRESS printf("Try %d back to previous bestPivot %g bestEver %g totalThru %g\n", iTry,bestPivot,bestEverPivot,totalThru); #endif break; } else if (sequenceIn == -1 && upperTheta > largeValue_) { if (lastPivotValue > currentAcceptablePivot_) { // back to previous one sequenceIn = lastSequence; thisPivotValue=lastPivotValue; #ifdef PRINT_RATIO_PROGRESS printf("Try %d no pivot this time large theta %g lastPivot %g\n", iTry,upperTheta,lastPivotValue); #endif } else { // can only get here if all pivots too small #ifdef PRINT_RATIO_PROGRESS printf("XXBAD Try %d no pivot this time large theta %g lastPivot %g\n", iTry,upperTheta,lastPivotValue); #endif } break; } else if (totalThru >= fabs(dualOut_)) { #ifdef PRINT_RATIO_PROGRESS printf("Try %d upperTheta %g totalThru %g - can modify costs\n", iTry,upperTheta,lastPivotValue); #endif modifyCosts = true; // fine grain - we can modify costs break; // no point trying another loop } else { lastSequence = sequenceIn; lastPivotValue=thisPivotValue; if (bestPivot > bestEverPivot) { bestEverPivot = bestPivot; //bestEverSequence=bestSequence; } modifyCosts = true; // fine grain - we can modify costs } #ifdef PRINT_RATIO_PROGRESS printf("Onto next pass totalthru %g bestPivot %g\n", totalThru,lastPivotValue); #endif numberLastSwapped=numberSwapped; } break; } else { // skip this lot if (bestPivot > 1.0e-3 || bestPivot > bestEverPivot) { #ifdef PRINT_RATIO_PROGRESS printf("Continuing bestPivot %g bestEver %g %d swapped - new tentative %g\n", bestPivot,bestEverPivot,numberSwapped,2*upperTheta); #endif bestEverPivot = bestPivot; //bestEverSequence=bestSequence; lastPivotValue=bestPivot; lastSequence = bestSequence; for (int iBlock=0;iBlock 100) currentAcceptablePivot_ = acceptablePivot_; if (abcFactorization_->pivots() > 10 || (abcFactorization_->pivots() && sumDualInfeasibilities_)) currentAcceptablePivot_ = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (abcFactorization_->pivots() > 5) currentAcceptablePivot_ = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (abcFactorization_->pivots()) currentAcceptablePivot_ = acceptablePivot_; // relax // If very large infeasibility use larger acceptable pivot if (abcFactorization_->pivots()) { double value=CoinMax(currentAcceptablePivot_,1.0e-12*fabs(dualOut_)); currentAcceptablePivot_=CoinMin(1.0e2*currentAcceptablePivot_,value); } // return at once if no free but there were free if (lastFirstFree_>=0&&sequenceIn_<0) { candidateList.clearAndReset(); upperTheta_=COIN_DBL_MAX; } if (upperTheta_==COIN_DBL_MAX) { usefulArray_[arrayForTableauRow_].compact(); assert (!candidateList.getNumElements()); return; } int numberSwapped = 0; //int numberRemaining = candidateList.getNumElements(); double useThru = 0.0; // for when variables flip // If we think we need to modify costs (not if something from broad sweep) bool modifyCosts = false; // pivot elements //double * COIN_RESTRICT array=candidateList.denseVector(); // indices const double * COIN_RESTRICT abcLower = abcLower_; const double * COIN_RESTRICT abcUpper = abcUpper_; const double * COIN_RESTRICT abcSolution = abcSolution_; const double * COIN_RESTRICT abcDj = abcDj_; //const double * COIN_RESTRICT abcPerturbation = abcPerturbation_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; // We can also see if infeasible or pivoting on free const double multiplier[] = { 1.0, -1.0}; // For list of flipped int numberLastSwapped=0; int * COIN_RESTRICT flippedIndex = flipList.getIndices(); double * COIN_RESTRICT flippedElement = flipList.denseVector(); // If sum of bad small pivots too much #ifdef MORE_CAREFUL bool badSumPivots = false; #endif if (sequenceIn_<0) { int lastSequence = -1; double lastPivotValue = 0.0; double thisPivotValue=0.0; dualColumnResult result; dualColumn2Most(result); sequenceIn_=result.sequence; lastSequence=result.lastSequence; thisPivotValue=result.thisPivotValue; lastPivotValue=result.lastPivotValue; numberSwapped=result.numberSwapped; numberLastSwapped=result.numberLastSwapped; modifyCosts=result.modifyCosts; useThru=result.useThru; #ifdef PRINT_RATIO_PROGRESS printf("Iteration %d - out of loop - sequenceIn %d pivotValue %g\n", numberIterations_,sequenceIn_,thisPivotValue); #endif // can get here without sequenceIn_ set but with lastSequence if (sequenceIn_ < 0 && lastSequence >= 0) { // back to previous one sequenceIn_ = lastSequence; thisPivotValue=lastPivotValue; #ifdef PRINT_RATIO_PROGRESS printf("BUT back one - out of loop - sequenceIn %d pivotValue %g\n", sequenceIn_,thisPivotValue); #endif } // Movement should be minimum for anti-degeneracy - unless // fixed variable out // no need if just one candidate assert( numberSwapped-numberLastSwapped>=0); double minimumTheta; if (upperOut_ > lowerOut_&&numberSwapped-numberLastSwapped>1) #ifndef TRY_ABC_GUS minimumTheta = MINIMUMTHETA; #else minimumTheta = minimumThetaMovement_; #endif else minimumTheta = 0.0; if (sequenceIn_ >= 0) { double oldValue; alpha_ = thisPivotValue; // correct sign int iStatus = internalStatus[sequenceIn_] & 3; alpha_ *= multiplier[iStatus]; oldValue = abcDj[sequenceIn_]; theta_ = CoinMax(oldValue / alpha_, 0.0); if (theta_ < minimumTheta && fabs(alpha_) < 1.0e5 && 1) { // can't pivot to zero theta_ = minimumTheta; } // may need to adjust costs so all dual feasible AND pivoted is exactly 0 if (modifyCosts #ifdef MORE_CAREFUL &&!badSumPivots #endif ) { for (int i = numberLastSwapped; i < numberSwapped; i++) { int iSequence = flippedIndex[i]; int iStatus = internalStatus[iSequence] & 3; // treat as if at lower bound double mult = multiplier[iStatus]; double alpha = flippedElement[i]; flippedElement[i]=0.0; if (iSequence==sequenceIn_) continue; double oldValue = abcDj[iSequence]*mult; double value = oldValue - theta_ * alpha; //double perturbedTolerance = abcPerturbation[iSequence]; if (-value > currentDualTolerance_) { //thisIncrease = true; #if MODIFYCOST if (numberIterations_>=normalDualColumnIteration_) { // modify cost to hit new tolerance double modification = alpha * theta_ - oldValue - currentDualTolerance_; if ((specialOptions_&(2048 + 4096)) != 0) { if ((specialOptions_ & 2048) != 0) { if (fabs(modification) < 1.0e-10) modification = 0.0; } else { if (fabs(modification) < 1.0e-12) modification = 0.0; } } abcDj_[iSequence] += mult*modification; abcCost_[iSequence] += mult*modification; if (modification) numberChanged_ ++; // Say changed costs } #endif } } numberSwapped=numberLastSwapped; } } } #ifdef MORE_CAREFUL // If we have done pivots and things look bad set alpha_ 0.0 to force factorization if ((badSumPivots || fabs(theta_ * badFree) > 10.0 * currentDualTolerance_) && abcFactorization_->pivots()) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 1) printf("forcing re-factorization\n"); #endif sequenceIn_ = -1; } #endif if (sequenceIn_ >= 0) { lowerIn_ = abcLower[sequenceIn_]; upperIn_ = abcUpper[sequenceIn_]; valueIn_ = abcSolution[sequenceIn_]; dualIn_ = abcDj_[sequenceIn_]; if (numberTimesOptimal_) { // can we adjust cost back closer to original //*** add coding } if (numberIterations_>=normalDualColumnIteration_) { #if MODIFYCOST>1 // modify cost to hit zero exactly // so (dualIn_+modification)==theta_*alpha_ //double perturbedTolerance = abcPerturbation[sequenceIn_]; double modification = theta_ * alpha_ - (dualIn_+goToTolerance2()); // But should not move objective too much ?? #ifdef DONT_MOVE_OBJECTIVE double moveObjective = fabs(modification * abcSolution[sequenceIn_]); double smallMove = CoinMax(fabs(rawObjectiveValue_), 1.0e-3); if (moveObjective > smallMove) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 1) printf("would move objective by %g - original mod %g sol value %g\n", moveObjective, modification, abcSolution[sequenceIn_]); #endif modification *= smallMove / moveObjective; } #endif #ifdef MORE_CAREFUL if (badSumPivots) modification = 0.0; #endif if (atFakeBound(sequenceIn_)&&fabs(modification)3 if ((handler_->logLevel() & 32) && fabs(modification) > 1.0e-15) printf("exact %d new cost %g, change %g\n", sequenceIn_, abcCost_[sequenceIn_], modification); #endif #endif } if (alpha_ < 0.0) { // as if from upper bound directionIn_ = -1; upperIn_ = valueIn_; } else { // as if from lower bound directionIn_ = 1; lowerIn_ = valueIn_; } } else { // no pivot alpha_ = 0.0; } // clear array //printf("dualout %g theta %g alpha %g dj %g thru %g swapped %d product %g guess %g useThru %g\n", // dualOut_,theta_,alpha_,abcDj_[sequenceIn_],useThru,numberSwapped, // fabs(dualOut_)*theta_,objectiveValue()+(fabs(dualOut_)-useThru)*theta_,useThru); objectiveChange_ = (fabs(dualOut_)-useThru)*theta_; rawObjectiveValue_+= objectiveChange_; //CoinZeroN(array, maximumNumberInList); //candidateList.setNumElements(0); candidateList.clearAndReset(); flipList.setNumElements(numberSwapped); if (numberSwapped) flipList.setPackedMode(true); #ifdef PRINT_RATIO_PROGRESS printf("%d flipped\n",numberSwapped); #endif } /* Checks if tentative optimal actually means unbounded Returns -3 if not, 2 if is unbounded */ int AbcSimplexDual::checkUnbounded(CoinIndexedVector & ray, double changeCost) { int status = 2; // say unbounded abcFactorization_->updateColumn(ray); // get reduced cost int number = ray.getNumElements(); int * COIN_RESTRICT index = ray.getIndices(); double * COIN_RESTRICT array = ray.denseVector(); const int * COIN_RESTRICT abcPivotVariable = abcPivotVariable_; for (int i = 0; i < number; i++) { int iRow = index[i]; int iPivot = abcPivotVariable[iRow]; changeCost -= cost(iPivot) * array[iRow]; } double way; if (changeCost > 0.0) { //try going down way = 1.0; } else if (changeCost < 0.0) { //try going up way = -1.0; } else { #if ABC_NORMAL_DEBUG>3 printf("can't decide on up or down\n"); #endif way = 0.0; status = -3; } double movement = 1.0e10 * way; // some largish number double zeroTolerance = 1.0e-14 * dualBound_; for (int i = 0; i < number; i++) { int iRow = index[i]; int iPivot = abcPivotVariable[iRow]; double arrayValue = array[iRow]; if (fabs(arrayValue) < zeroTolerance) arrayValue = 0.0; double newValue = solution(iPivot) + movement * arrayValue; if (newValue > upper(iPivot) + primalTolerance_ || newValue < lower(iPivot) - primalTolerance_) status = -3; // not unbounded } if (status == 2) { // create ray delete [] ray_; ray_ = new double [numberColumns_]; CoinZeroN(ray_, numberColumns_); for (int i = 0; i < number; i++) { int iRow = index[i]; int iPivot = abcPivotVariable[iRow]; double arrayValue = array[iRow]; if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance) ray_[iPivot] = way * array[iRow]; } } ray.clear(); return status; } // Saves good status etc void AbcSimplex::saveGoodStatus() { // save arrays CoinMemcpyN(internalStatus_, numberTotal_, internalStatusSaved_); // save costs CoinMemcpyN(abcCost_,numberTotal_,abcCost_+2*numberTotal_); CoinMemcpyN(abcSolution_,numberTotal_,solutionSaved_); } // Restores previous good status and says trouble void AbcSimplex::restoreGoodStatus(int type) { #if PARTITION_ROW_COPY==1 stateOfProblem_ |= NEED_BASIS_SORT; #endif if (type) { if (alphaAccuracy_ != -1.0) alphaAccuracy_ = -2.0; // trouble - restore solution CoinMemcpyN(internalStatusSaved_, numberTotal_, internalStatus_); CoinMemcpyN(abcCost_+2*numberTotal_,numberTotal_,abcCost_); CoinMemcpyN(solutionSaved_,numberTotal_, abcSolution_); int * COIN_RESTRICT abcPivotVariable = abcPivotVariable_; // redo pivotVariable int numberBasic=0; for (int i=0;iusefulArray(whichArray[0]); CoinIndexedVector * array2 = model->usefulArray(whichArray[1]); int numberRefinements=model->computePrimals(array1,array2); model->checkPrimalSolution(true); return numberRefinements; } static int computeDualsAndCheck(AbcSimplexDual * model,const int whichArray[2]) { CoinIndexedVector * array1 = model->usefulArray(whichArray[0]); CoinIndexedVector * array2 = model->usefulArray(whichArray[1]); int numberRefinements=model->computeDuals(NULL,array1,array2); model->checkDualSolutionPlusFake(); return numberRefinements; } // Computes solutions - 1 do duals, 2 do primals, 3 both int AbcSimplex::gutsOfSolution(int type) { AbcSimplexDual * dual = reinterpret_cast(this); // do work and check int numberRefinements=0; #if ABC_PARALLEL if (type!=3) { #endif if ((type&2)!=0) { //work space int whichArray[2]; for (int i=0;i<2;i++) whichArray[i]=getAvailableArray(); numberRefinements=computePrimalsAndCheck(dual,whichArray); for (int i=0;i<2;i++) setAvailableArray(whichArray[i]); } if ((type&1)!=0 #if CAN_HAVE_ZERO_OBJ>1 &&(specialOptions_&2097152)==0 #endif ) { //work space int whichArray[2]; for (int i=0;i<2;i++) whichArray[i]=getAvailableArray(); numberRefinements+=computeDualsAndCheck(dual,whichArray); for (int i=0;i<2;i++) setAvailableArray(whichArray[i]); } #if ABC_PARALLEL } else { #ifndef NDEBUG abcFactorization_->checkMarkArrays(); #endif // redo to do in parallel //work space int whichArray[5]; for (int i=1;i<5;i++) whichArray[i]=getAvailableArray(); if (parallelMode_==0) { numberRefinements+=computePrimalsAndCheck(dual,whichArray+3); numberRefinements+=computeDualsAndCheck(dual,whichArray+1); } else { #if ABC_PARALLEL==1 threadInfo_[0].stuff[0]=whichArray[1]; threadInfo_[0].stuff[1]=whichArray[2]; stopStart_=1+32*1; startParallelStuff(1); #else whichArray[0]=1; CoinAbcThreadInfo info; info.status=1; info.stuff[0]=whichArray[1]; info.stuff[1]=whichArray[2]; int n=cilk_spawn computeDualsAndCheck(dual,whichArray+1); #endif numberRefinements=computePrimalsAndCheck(dual,whichArray+3); #if ABC_PARALLEL==1 numberRefinements+=stopParallelStuff(1); #else cilk_sync; numberRefinements+=n; #endif } for (int i=1;i<5;i++) setAvailableArray(whichArray[i]); } #endif rawObjectiveValue_ +=sumNonBasicCosts_; setClpSimplexObjectiveValue(); if (handler_->logLevel() > 3 || (largestPrimalError_ > 1.0e-2 || largestDualError_ > 1.0e-2)) handler_->message(CLP_SIMPLEX_ACCURACY, messages_) << largestPrimalError_ << largestDualError_ << CoinMessageEol; if ((largestPrimalError_ > 1.0e1||largestDualError_>1.0e1) && numberRows_ > 100 && numberIterations_) { #if ABC_NORMAL_DEBUG>0 printf("Large errors - primal %g dual %g\n", largestPrimalError_,largestDualError_); #endif // Change factorization tolerance //if (abcFactorization_->zeroTolerance() > 1.0e-18) //abcFactorization_->zeroTolerance(1.0e-18); } return numberRefinements; } // Make non free variables dual feasible by moving to a bound int AbcSimplexDual::makeNonFreeVariablesDualFeasible(bool changeCosts) { const double multiplier[] = { 1.0, -1.0}; // sign????????????? double dualT = - 100.0*currentDualTolerance_; int numberMoved=0; int numberChanged=0; double * COIN_RESTRICT solution = abcSolution_; double * COIN_RESTRICT lower = abcLower_; double * COIN_RESTRICT upper = abcUpper_; double saveNonBasicCosts =sumNonBasicCosts_; double largestCost=dualTolerance_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { unsigned char iStatus = internalStatus_[iSequence] & 7; if (iStatus<4) { double mult = multiplier[iStatus]; double dj = abcDj_[iSequence] * mult; if (dj < dualT) { largestCost=CoinMax(fabs(abcPerturbation_[iSequence]),largestCost); } } else if (iStatus!=7) { largestCost=CoinMax(fabs(abcPerturbation_[iSequence]),largestCost); } } for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { unsigned char iStatus = internalStatus_[iSequence] & 7; if (iStatus<4) { double mult = multiplier[iStatus]; double dj = abcDj_[iSequence] * mult; // ? should use perturbationArray if (dj < dualT&&changeCosts) { double gap=upper[iSequence]-lower[iSequence]; if (gap>1.1*currentDualBound_) { assert(getFakeBound(iSequence)==AbcSimplexDual::noFake); if (!iStatus) { upper[iSequence]=lower[iSequence]+currentDualBound_; setFakeBound(iSequence, AbcSimplexDual::upperFake); } else { lower[iSequence]=upper[iSequence]-currentDualBound_; setFakeBound(iSequence, AbcSimplexDual::lowerFake); } } double costDifference=abcPerturbation_[iSequence]-abcCost_[iSequence]; if (costDifference*mult>0.0) { #if ABC_NORMAL_DEBUG>0 //printf("can improve situation on %d by %g\n",iSequence,costDifference*mult); #endif dj+=costDifference*mult; abcDj_[iSequence]+=costDifference; abcCost_[iSequence]=abcPerturbation_[iSequence]; costDifference=0.0; } double changeInObjective=-gap*dj; // probably need to be more intelligent if ((changeInObjective>1.0e3||gap>CoinMax(0.5*dualBound_,1.0e3))&&dj>-1.0e-1) { // change cost costDifference=(-dj-0.5*dualTolerance_)*mult; if (fabs(costDifference)<100000.0*dualTolerance_) { dj+=costDifference*mult; abcDj_[iSequence]+=costDifference; abcCost_[iSequence]+=costDifference; numberChanged++; } } } if (dj < dualT&&!changeCosts) { numberMoved++; if (iStatus==0) { // at lower bound // to upper bound setInternalStatus(iSequence, atUpperBound); solution[iSequence] = upper[iSequence]; sumNonBasicCosts_ += abcCost_[iSequence]*(upper[iSequence]-lower[iSequence]); } else { // at upper bound // to lower bound setInternalStatus(iSequence, atLowerBound); solution[iSequence] = lower[iSequence]; sumNonBasicCosts_ -= abcCost_[iSequence]*(upper[iSequence]-lower[iSequence]); } } } } #if ABC_NORMAL_DEBUG>0 if (numberMoved+numberChanged) printf("makeDualfeasible %d moved, %d had costs changed - sum dual %g\n", numberMoved,numberChanged,sumDualInfeasibilities_); #endif rawObjectiveValue_ +=(sumNonBasicCosts_-saveNonBasicCosts); setClpSimplexObjectiveValue(); return numberMoved; } int AbcSimplexDual::whatNext() { int returnCode=0; assert (!stateOfIteration_); // see if update stable #if ABC_NORMAL_DEBUG>3 if ((handler_->logLevel() & 32)) printf("btran alpha %g, ftran alpha %g\n", btranAlpha_, alpha_); #endif int numberPivots=abcFactorization_->pivots(); //double checkValue = 1.0e-7; // numberPivots<5 ? 1.0e-7 : 1.0e-6; double checkValue = numberPivots ? 1.0e-7 : 1.0e-5; // relax if free variable in if ((internalStatus_[sequenceIn_]&7)>1) checkValue=1.0e-5; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha_ << alpha_ << CoinMessageEol; // see with more relaxed criterion double test; if (fabs(btranAlpha_) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 10.0*checkValue;//1.0e-4 * (1.0 + fabs(alpha_)); bool needFlag = (fabs(btranAlpha_) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha_ - alpha_) > test); #if ABC_NORMAL_DEBUG>0 if (fabs(btranAlpha_ + alpha_) < 1.0e-5*(1.0 + fabs(alpha_))) { printf("alpha diff (%g,%g) %g check %g\n",btranAlpha_,alpha_,fabs(btranAlpha_-alpha_),checkValue*(1.0+fabs(alpha_))); } #endif if (numberPivots) { if (needFlag&&numberPivots<10) { // need to reject something assert (sequenceOut_>=0); char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("flag %d as alpha %g %g - after %d pivots\n", sequenceOut_, btranAlpha_, alpha_,numberPivots); #endif // Make safer? abcFactorization_->saferTolerances (1.0, -1.03); setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; lastBadIteration_ = numberIterations_; // say be more cautious } // Make safer? //if (numberPivots<5) //abcFactorization_->saferTolerances (-0.99, -1.01); problemStatus_ = -2; // factorize now returnCode = -2; stateOfIteration_=2; } else { if (needFlag) { // need to reject something assert (sequenceOut_>=0); char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag a %g %g\n", btranAlpha_, alpha_); #endif // Make safer? double tolerance=abcFactorization_->pivotTolerance(); abcFactorization_->saferTolerances (1.0, -1.03); setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha_) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; stateOfIteration_=2; } else { stateOfIteration_=1; if (tolerancepivotTolerance()) { stateOfIteration_=2; returnCode=-2; } } } } } if (!stateOfIteration_) { // check update returnCode=abcFactorization_->checkReplacePart2(pivotRow_,btranAlpha_,alpha_,ftAlpha_); } return returnCode; } /* Checks if finished. type 0 initial 1 normal 2 initial but we have solved problem before 3 can skip factorization Updates status */ void AbcSimplexDual::statusOfProblemInDual(int type) { // If lots of iterations then adjust costs if large ones int numberPivots = abcFactorization_->pivots(); #if 0 printf("statusOf %d pivots type %d pstatus %d forceFac %d dont %d\n", numberPivots,type,problemStatus_,forceFactorization_,dontFactorizePivots_); #endif int saveType=type; double lastSumDualInfeasibilities=sumDualInfeasibilities_; double lastSumPrimalInfeasibilities=sumPrimalInfeasibilities_; if (type>=4) { // force factorization type &= 3; numberPivots=9999999; } //double realDualInfeasibilities = 0.0; double changeCost; bool unflagVariables = numberFlagged_>0; int weightsSaved = 0; int numberBlackMarks=0; if (!type) { // be optimistic stateOfProblem_ &= ~PESSIMISTIC; // but use 0.1 double newTolerance = CoinMax(0.1, saveData_.pivotTolerance_); abcFactorization_->pivotTolerance(newTolerance); } if (type != 3&&(numberPivots>dontFactorizePivots_||numberIterations_==baseIteration_)) { // factorize // save dual weights abcDualRowPivot_->saveWeights(this, 1); weightsSaved = 2; // is factorization okay? int factorizationStatus=0; if ((largestPrimalError_ > 1.0e1||largestDualError_>1.0e1) && numberRows_ > 100 && numberIterations_>baseIteration_) { double newTolerance = CoinMin(1.1* abcFactorization_->pivotTolerance(), 0.99); abcFactorization_->pivotTolerance(newTolerance); } #ifdef EARLY_FACTORIZE if ((numberEarly_&0xffff)<=5||!usefulArray_[ABC_NUMBER_USEFUL-1].getNumElements()) { //#define KEEP_TRYING_EARLY #ifdef KEEP_TRYING_EARLY int savedEarly=numberEarly_>>16; int newEarly=(numberEarly_&0xffff); newEarly=CoinMin(savedEarly,1+2*newEarly); numberEarly_=(savedEarly<<16)|newEarly; #endif factorizationStatus = internalFactorize(type ? 1 : 2); } else { CoinIndexedVector & vector = usefulArray_[ABC_NUMBER_USEFUL-1]; bool bad = vector.getNumElements()<0; const int * indices = vector.getIndices(); double * array = vector.denseVector(); int capacity = vector.capacity(); capacity--; int numberPivotsStored = indices[capacity]; #if ABC_NORMAL_DEBUG>0 printf("early status %s nPivots %d\n",bad ? "bad" : "good",numberPivotsStored); #endif if (!bad) { // do remaining pivots int iterationsDone=abcEarlyFactorization_->pivots(); factorizationStatus = abcEarlyFactorization_->replaceColumns(this,vector, iterationsDone,numberPivotsStored,true); if (!factorizationStatus) { // should be able to compare e.g. basics 1.0 #define GOOD_EARLY #ifdef GOOD_EARLY AbcSimplexFactorization * temp = abcFactorization_; abcFactorization_=abcEarlyFactorization_; abcEarlyFactorization_=temp; #endif moveToBasic(); #ifndef GOOD_EARLY int * pivotSave = CoinCopyOfArray(abcPivotVariable_,numberRows_); factorizationStatus = internalFactorize(type ? 1 : 2); { double * array = usefulArray_[3].denseVector(); double * array2 = usefulArray_[4].denseVector(); for (int iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = abcPivotVariable_[iPivot]; unpack(usefulArray_[3], iSequence); unpack(usefulArray_[4], iSequence); abcFactorization_->updateColumn(usefulArray_[3]); abcEarlyFactorization_->updateColumn(usefulArray_[4]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; int iPivot2; for (iPivot2=0;iPivot20 printf("switching off early factorization(in statusOf)\n"); #endif #ifndef KEEP_TRYING_EARLY numberEarly_=0; delete abcEarlyFactorization_; abcEarlyFactorization_=NULL; #else numberEarly_&=0xffff0000; #endif factorizationStatus = internalFactorize(1); } } #else factorizationStatus = internalFactorize(type ? 1 : 2); #endif if (factorizationStatus) { if (type == 1&&lastFlaggedIteration_!=1) { // use for real disaster lastFlaggedIteration_ = 1; // no - restore previous basis unflagVariables = false; // restore weights weightsSaved = 4; changeMade_++; // say something changed // Keep any flagged variables for (int i = 0; i < numberTotal_; i++) { if (flagged(i)) internalStatusSaved_[i] |= 64; //say flagged } restoreGoodStatus(type); // get correct bounds on all variables resetFakeBounds(1); numberBlackMarks=10; if (sequenceOut_>=0) { // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag d\n"); #endif setFlagged(sequenceOut_); lastBadIteration_ = numberIterations_; // say be more cautious // so can't happen immediately again sequenceOut_=-1; } //abcProgress_.clearBadTimes(); // Go to safe abcFactorization_->pivotTolerance(0.99); } else { #if ABC_NORMAL_DEBUG>0 printf("Bad initial basis\n"); #endif } if (internalFactorize(1)) { // try once more if (internalFactorize(0)) abort(); } #if PARTITION_ROW_COPY==1 int iVector=getAvailableArray(); abcMatrix_->sortUseful(usefulArray_[iVector]); setAvailableArray(iVector); #endif } else { lastFlaggedIteration_ = 0; } } // get primal and dual solutions numberBlackMarks+=gutsOfSolution(3)/2; assert (type!=0||numberIterations_==baseIteration_); // may be wrong if (!type) { initialSumInfeasibilities_=sumPrimalInfeasibilities_; initialNumberInfeasibilities_=numberPrimalInfeasibilities_; CoinAbcMemcpy(solutionSaved_+numberTotal_,abcSolution_,numberTotal_); CoinAbcMemcpy(internalStatusSaved_+numberTotal_,internalStatus_,numberTotal_); } double savePrimalInfeasibilities=sumPrimalInfeasibilities_; if ((moreSpecialOptions_&16384)!=0&&(moreSpecialOptions_&8192)==0) { if (numberIterations_==baseIteration_) { // If primal feasible and looks suited to primal go to primal if (!sumPrimalInfeasibilities_&&sumDualInfeasibilities_>1.0&& numberRows_*4>numberColumns_) { // do primal // mark so can perturb initialSumInfeasibilities_=-1.0; problemStatus_=10; return; } } else if ((numberIterations_>1000&& numberIterations_*10>numberRows_&&numberIterations_*4 1.0e10*(initialSumInfeasibilities_+1000.0)&&numberIterations_>10000&&sumDualInfeasibilities_>1.0)) { if (sumPrimalInfeasibilities_+1.0e2*sumDualInfeasibilities_> 2000.0*(initialSumInfeasibilities_+100.0)) { #if ABC_NORMAL_DEBUG>0 printf ("sump %g sumd %g initial %g\n",sumPrimalInfeasibilities_,sumDualInfeasibilities_, initialSumInfeasibilities_); #endif // but only if average gone up as well if (sumPrimalInfeasibilities_*initialNumberInfeasibilities_> 100.0*(initialSumInfeasibilities_+10.0)*numberPrimalInfeasibilities_) { #if ABC_NORMAL_DEBUG>0 printf("returning to do primal\n"); #endif // do primal problemStatus_=10; CoinAbcMemcpy(abcSolution_,solutionSaved_+numberTotal_,numberTotal_); CoinAbcMemcpy(internalStatus_,internalStatusSaved_+numberTotal_,numberTotal_); // mark so can perturb initialSumInfeasibilities_=-1.0; return; } } } } else if ((sumPrimalInfeasibilities_+sumDualInfeasibilities_> 1.0e6*(initialSumInfeasibilities_+1000.0)&&(moreSpecialOptions_&8192)==0&& numberIterations_>1000&& numberIterations_*10>numberRows_&&numberIterations_*4 1.0e10*(initialSumInfeasibilities_+1000.0)&&(moreSpecialOptions_&8192)==0&& numberIterations_>10000&&sumDualInfeasibilities_>1.0)) { // do primal problemStatus_=10; CoinAbcMemcpy(abcSolution_,solutionSaved_+numberTotal_,numberTotal_); CoinAbcMemcpy(internalStatus_,internalStatusSaved_+numberTotal_,numberTotal_); // mark so can perturb initialSumInfeasibilities_=-1.0; return; } //double saveDualInfeasibilities=sumDualInfeasibilities_; // 0 don't ignore, 1 ignore errors, 2 values pass int ignoreStuff=(firstFree_<0&&lastFirstFree_<0) ? 0 : 1; if ((stateOfProblem_&VALUES_PASS)!=0) ignoreStuff=2; { double thisObj = rawObjectiveValue(); double lastObj = abcProgress_.lastObjective(0); if ((lastObj > thisObj + 1.0e-3 * CoinMax(fabs(thisObj), fabs(lastObj)) + 1.0e-4|| (sumPrimalInfeasibilities_>10.0*lastSumPrimalInfeasibilities+1.0e3&& sumDualInfeasibilities_>10.0*CoinMax(lastSumDualInfeasibilities,1.0))) &&!ignoreStuff) { #if ABC_NORMAL_DEBUG>0 printf("bad - objective backwards %g %g errors %g %g suminf %g %g\n",lastObj,thisObj,largestDualError_,largestPrimalError_,sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif numberBlackMarks++; if (largestDualError_>1.0e-3||largestPrimalError_>1.0e-3|| (sumDualInfeasibilities_>10.0*CoinMax(lastSumDualInfeasibilities,1.0) &&firstFree_<0)) { #if ABC_NORMAL_DEBUG>0 printf("backtracking %d iterations - dual error %g primal error %g - sumDualInf %g\n", numberPivots, largestDualError_,largestPrimalError_,sumDualInfeasibilities_); #endif // restore previous basis unflagVariables = false; // restore weights weightsSaved = 4; changeMade_++; // say something changed // Keep any flagged variables for (int i = 0; i < numberTotal_; i++) { if (flagged(i)) internalStatusSaved_[i] |= 64; //say flagged } restoreGoodStatus(type); // get correct bounds on all variables resetFakeBounds(1); numberBlackMarks+=10; if (sequenceOut_>=0) { // need to reject something #if ABC_NORMAL_DEBUG>0 if (flagged(sequenceOut_)) printf("BAD %x already flagged\n",sequenceOut_); #endif char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag d\n"); #endif setFlagged(sequenceOut_); lastBadIteration_ = numberIterations_; // say be more cautious #if ABC_NORMAL_DEBUG>0 } else { printf("backtracking - no valid sequence out\n"); #endif } // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); // Go to safe //abcFactorization_->pivotTolerance(0.99); if (internalFactorize(1)) { abort(); } moveToBasic(); #if PARTITION_ROW_COPY==1 int iVector=getAvailableArray(); abcMatrix_->sortUseful(usefulArray_[iVector]); setAvailableArray(iVector); #endif // get primal and dual solutions numberBlackMarks+=gutsOfSolution(3); //gutsOfSolution(1); makeNonFreeVariablesDualFeasible(); } } } //#define PAN #ifdef PAN if (!type&&(specialOptions_&COIN_CBC_USING_CLP)==0&&firstFree_<0) { // first time - set large bad ones superbasic int whichArray=getAvailableArray(); double * COIN_RESTRICT work=usefulArray_[whichArray].denseVector(); int number=0; int * COIN_RESTRICT which=usefulArray_[whichArray].getIndices(); const double * COIN_RESTRICT reducedCost=abcDj_; const double * COIN_RESTRICT lower=abcLower_; const double * COIN_RESTRICT upper=abcUpper_; #if PRINT_PAN int nAtUb=0; #endif for (int i=0;i100000000.0) badValue = -djValue*CoinMin(gap,1.0e10); } else if (status==atUpperBound&&djValue>currentDualTolerance_) { double gap=upper[i]-lower[i]; if (gap>100000000.0) { badValue = djValue*CoinMin(gap,1.0e10); #if PRINT_PAN nAtUb++; #endif } } if (badValue) { work[number]=badValue; which[number++]=i; } } // for now don't do if primal feasible (probably should go to primal) if (!numberPrimalInfeasibilities_) { number=0; #if ABC_NORMAL_DEBUG>1 printf("XXXX doesn't work if primal feasible - also fix switch to Clp primal\n"); #endif } if (number&&ignoreStuff!=2) { CoinSort_2(work,work+number,which); int numberToDo=CoinMin(number,numberRows_/10); // ?? #if PRINT_PAN>1 CoinSort_2(which,which+numberToDo,work); int n=0; #endif #if PRINT_PAN printf("Panning %d variables (out of %d at lb and %d at ub)\n",numberToDo,number-nAtUb,nAtUb); #endif firstFree_=numberTotal_; for (int i=0;i1 if (!n) printf("Pan "); printf("%d ",iSequence); n++; if (n==10) { n=0; printf("\n"); } #endif setInternalStatus(iSequence,superBasic); firstFree_=CoinMin(firstFree_,iSequence); } #if PRINT_PAN>1 if (n) printf("\n"); #endif ordinaryVariables_=0; CoinAbcMemset0(work,number); stateOfProblem_ |= FAKE_SUPERBASIC; } setAvailableArray(whichArray); } #endif if (!sumOfRelaxedPrimalInfeasibilities_&&sumDualInfeasibilities_&&type&&saveType<9 &&ignoreStuff!=2) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; int numberFake=numberAtFakeBound(); if (!numberFake) { makeNonFreeVariablesDualFeasible(); numberDualInfeasibilities_=0; sumDualInfeasibilities_=0.0; // just primal gutsOfSolution(2); } } bool computeNewSumInfeasibilities=numberIterations_==baseIteration_; if ((!type||(firstFree_<0&&lastFirstFree_>=0))&&ignoreStuff!=2) { #ifdef PAN if ((stateOfProblem_&FAKE_SUPERBASIC)!=0&&firstFree_<0&&lastFirstFree_>=0&&type) { // clean up #if PRINT_PAN printf("Pan switch off after %d iterations\n",numberIterations_); #endif computeNewSumInfeasibilities=true; ordinaryVariables_=1; const double * COIN_RESTRICT reducedCost=abcDj_; const double * COIN_RESTRICT lower=abcLower_; const double * COIN_RESTRICT upper=abcUpper_; for (int i=0;i0 if(djValue<-dualTolerance_) printf("Odd at lb %d dj %g\n",i,djValue); #endif } else if (value>upper[i]-primalTolerance_) { setInternalStatus(i,atUpperBound); #if ABC_NORMAL_DEBUG>0 if(djValue>dualTolerance_) printf("Odd at ub %d dj %g\n",i,djValue); #endif } else { assert (status!=superBasic); } } if (status==isFree) ordinaryVariables_=0; } stateOfProblem_ &= ~FAKE_SUPERBASIC; } #endif // set up perturbation and dualBound_ // make dual feasible if (firstFree_<0) { if (numberFlagged_) { numberFlagged_=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) { clearFlagged(iPivot); } } } int numberChanged=resetFakeBounds(0); #if ABC_NORMAL_DEBUG>0 if (numberChanged>0) printf("Re-setting %d fake bounds %d gone dual infeasible - can expect backward objective\n", numberChanged,numberDualInfeasibilities_); #endif if (numberDualInfeasibilities_||numberChanged!=-1) { makeNonFreeVariablesDualFeasible(); numberDualInfeasibilities_=0; sumDualInfeasibilities_=0.0; sumOfRelaxedDualInfeasibilities_=0.0; // just primal gutsOfSolution(2); if (!numberIterations_ && sumPrimalInfeasibilities_ > 1.0e5*(savePrimalInfeasibilities+1.0e3) && (moreSpecialOptions_ & (256|8192)) == 0) { // Use primal problemStatus_=10; // mark so can perturb initialSumInfeasibilities_=-1.0; CoinAbcMemcpy(abcSolution_,solutionSaved_,numberTotal_); CoinAbcMemcpy(internalStatus_,internalStatusSaved_,numberTotal_); return; } // redo if(computeNewSumInfeasibilities) initialSumInfeasibilities_=sumPrimalInfeasibilities_; //computeObjective(); } } //bounceTolerances(type); } else if (numberIterations_>numberRows_&&stateDualColumn_==-2) { bounceTolerances(4); } // If bad accuracy treat as singular if ((largestPrimalError_ > 1.0e15 || largestDualError_ > 1.0e15) && numberIterations_>1000) { problemStatus_=10; //abort(); #if ABC_NORMAL_DEBUG>0 printf("Big problems - errors %g %g try primal\n",largestPrimalError_,largestDualError_); #endif } else if (goodAccuracy()&&numberIterations_>lastBadIteration_+200) { // Can reduce tolerance double newTolerance = CoinMax(0.995 * abcFactorization_->pivotTolerance(), saveData_.pivotTolerance_); if (!type) newTolerance = saveData_.pivotTolerance_; if (newTolerance>abcFactorization_->minimumPivotTolerance()) abcFactorization_->pivotTolerance(newTolerance); } bestObjectiveValue_ = CoinMax(bestObjectiveValue_, rawObjectiveValue_ - bestPossibleImprovement_); // Double check infeasibility if no action if (abcProgress_.lastIterationNumber(0) == numberIterations_) { if (abcDualRowPivot_->looksOptimal()) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } } else { double thisObj = rawObjectiveValue_ - bestPossibleImprovement_; #ifdef CLP_INVESTIGATE assert (bestPossibleImprovement_ > -1000.0 && rawObjectiveValue_ > -1.0e100); if (bestPossibleImprovement_) printf("obj %g add in %g -> %g\n", rawObjectiveValue_, bestPossibleImprovement_, thisObj); #endif double lastObj = abcProgress_.lastObjective(0); #ifndef NDEBUG #if ABC_NORMAL_DEBUG>3 resetFakeBounds(-1); #endif #endif if (lastObj < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj)) - 1.0e-3 && saveType<9) { numberTimesOptimal_ = 0; } } // Up tolerance if looks a bit odd if (numberIterations_ > CoinMax(1000, numberRows_ >> 4) && (specialOptions_ & 64) != 0) { if (sumPrimalInfeasibilities_ && sumPrimalInfeasibilities_ < 1.0e5) { int backIteration = abcProgress_.lastIterationNumber(CLP_PROGRESS - 1); if (backIteration > 0 && numberIterations_ - backIteration < 9 * CLP_PROGRESS) { if (abcFactorization_->pivotTolerance() < 0.9) { // up tolerance abcFactorization_->pivotTolerance(CoinMin(abcFactorization_->pivotTolerance() * 1.05 + 0.02, 0.91)); //printf("tol now %g\n",abcFactorization_->pivotTolerance()); abcProgress_.clearIterationNumbers(); } } } } // Check if looping int loop; if (type != 2) loop = abcProgress_.looping(); else loop = -1; if (abcProgress_.reallyBadTimes() > 10) { problemStatus_ = 10; // instead - try other algorithm #if ABC_NORMAL_DEBUG>3 printf("returning at %d\n", __LINE__); #endif } if (loop >= 0) { problemStatus_ = loop; //exit if in loop if (!problemStatus_) { // declaring victory // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else { problemStatus_ = 10; // instead - try other algorithm #if ABC_NORMAL_DEBUG>3 printf("returning at %d\n", __LINE__); #endif } return; } // really for free variables in if((progressFlag_ & 2) != 0) { //situationChanged = 2; } progressFlag_ &= (~3); //reset progress flag // mark as having gone optimal if looks like it if (!numberPrimalInfeasibilities_&& !numberDualInfeasibilities_) progressFlag_ |= 8; if (handler_->detail(CLP_SIMPLEX_STATUS, messages_) < 100) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } double approximateObjective = rawObjectiveValue_; //realDualInfeasibilities = sumDualInfeasibilities_; // If we need to carry on cleaning variables if (!numberPrimalInfeasibilities_ && (specialOptions_ & 1024) != 0 && CLEAN_FIXED) { for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (!flagged(iPivot) && pivoted(iPivot)) { // carry on numberPrimalInfeasibilities_ = -1; sumOfRelaxedPrimalInfeasibilities_ = 1.0; sumPrimalInfeasibilities_ = 1.0; break; } } } /* If we are primal feasible and any dual infeasibilities are on free variables then it is better to go to primal */ if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilitiesWithoutFree_ && numberDualInfeasibilities_) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; if (type&&ignoreStuff!=2) problemStatus_ = 10; else numberPrimalInfeasibilities_=1; } // check optimal // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0&&ignoreStuff!=2) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else if (sumOfRelaxedDualInfeasibilities_>1.0e-3&&firstFree_<0&&ignoreStuff!=2 &&numberIterations_>lastCleaned_+10) { #if ABC_NORMAL_DEBUG>0 printf("Making dual feasible\n"); #endif makeNonFreeVariablesDualFeasible(true); lastCleaned_=numberIterations_; numberDualInfeasibilities_=0; sumDualInfeasibilities_=0.0; // just primal gutsOfSolution(2); } // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if (primalFeasible()&&ignoreStuff!=2) { // may be optimal - or may be bounds are wrong int numberChangedBounds = changeBounds(0, changeCost); if (numberChangedBounds <= 0 && !numberDualInfeasibilities_) { //looks optimal - do we need to reset tolerance if (lastCleaned_ < numberIterations_ && /*numberTimesOptimal_*/ stateDualColumn_ < 4 && (numberChanged_ || (specialOptions_ & 4096) == 0)) { #if CLP_CAN_HAVE_ZERO_OBJ if ((specialOptions_&2097152)==0) { #endif numberTimesOptimal_++; if (stateDualColumn_==-2) { #if ABC_NORMAL_DEBUG>0 printf("Going straight from state -2 to 0\n"); #endif stateDualColumn_=-1; } changeMade_++; // say something changed if (numberTimesOptimal_ == 1) { if (fabs(currentDualTolerance_-dualTolerance_)>1.0e-12) { #if ABC_NORMAL_DEBUG>0 printf("changing dual tolerance from %g to %g (numberTimesOptimal_==%d)\n", currentDualTolerance_,dualTolerance_,numberTimesOptimal_); #endif currentDualTolerance_ = dualTolerance_; } } else { if (numberTimesOptimal_ == 2) { // better to have small tolerance even if slower abcFactorization_->zeroTolerance(CoinMin(abcFactorization_->zeroTolerance(), 1.0e-15)); } #if ABC_NORMAL_DEBUG>0 printf("changing dual tolerance from %g to %g (numberTimesOptimal_==%d)\n", currentDualTolerance_,dualTolerance_*pow(2.0,numberTimesOptimal_-1),numberTimesOptimal_); #endif currentDualTolerance_ = dualTolerance_ * pow(2.0, numberTimesOptimal_ - 1); } if (numberChanged_>0) { handler_->message(CLP_DUAL_ORIGINAL, messages_) << CoinMessageEol; //realDualInfeasibilities = sumDualInfeasibilities_; } else if (numberChangedBounds<-1) { // bounds were flipped //gutsOfSolution(2); } if (stateDualColumn_>=0) stateDualColumn_++; #ifndef TRY_ABC_GUS int returnCode=bounceTolerances(1); if (returnCode) #endif // always go to primal problemStatus_=10; lastCleaned_ = numberIterations_; #if CLP_CAN_HAVE_ZERO_OBJ } else { // no cost - skip checks problemStatus_=0; } #endif } else { problemStatus_ = 0; // optimal if (lastCleaned_ < numberIterations_ && numberChanged_) { handler_->message(CLP_SIMPLEX_GIVINGUP, messages_) << CoinMessageEol; } } } else if (numberChangedBounds<-1) { // some flipped bounceTolerances(2); #if ABC_NORMAL_DEBUG>0 printf("numberChangedBounds %d numberAtFakeBound %d at line %d in file %s\n", numberChangedBounds,numberAtFakeBound(),__LINE__,__FILE__); #endif } else if (numberAtFakeBound()) { handler_->message(CLP_DUAL_BOUNDS, messages_) << currentDualBound_ << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("changing bounds\n"); printf("numberChangedBounds %d numberAtFakeBound %d at line %d in file %s\n", numberChangedBounds,numberAtFakeBound(),__LINE__,__FILE__); #endif if (!numberDualInfeasibilities_&&!numberPrimalInfeasibilities_) { // check unbounded // find a variable with bad dj int iChosen = -1; if ((specialOptions_ & 0x03000000) == 0) { double largest = 100.0 * primalTolerance_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double djValue = abcDj_[iSequence]; double originalLo = lowerSaved_[iSequence]; double originalUp = upperSaved_[iSequence]; if (fabs(djValue) > fabs(largest)) { if (getInternalStatus(iSequence) != basic) { if (djValue > 0 && originalLo < -1.0e20) { if (djValue > fabs(largest)) { largest = djValue; iChosen = iSequence; } } else if (djValue < 0 && originalUp > 1.0e20) { if (-djValue > fabs(largest)) { largest = djValue; iChosen = iSequence; } } } } } } if (iChosen >= 0) { int iVector=getAvailableArray(); unpack(usefulArray_[iVector],iChosen); //double changeCost; problemStatus_ = checkUnbounded(usefulArray_[iVector], 0.0/*changeCost*/); usefulArray_[iVector].clear(); setAvailableArray(iVector); } } gutsOfSolution(3); //bounceTolerances(2); //realDualInfeasibilities = sumDualInfeasibilities_; } // unflag all variables (we may want to wait a bit?) if (unflagVariables) { int numberFlagged = numberFlagged_; numberFlagged_=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) { clearFlagged(iPivot); } } #if ABC_NORMAL_DEBUG>3 if (numberFlagged) { printf("unflagging %d variables - tentativeStatus %d probStat %d ninf %d nopt %d\n", numberFlagged, tentativeStatus, problemStatus_, numberPrimalInfeasibilities_, numberTimesOptimal_); } #endif unflagVariables = numberFlagged > 0; if (numberFlagged && !numberPivots) { /* looks like trouble as we have not done any iterations. Try changing pivot tolerance then give it a few goes and give up */ if (abcFactorization_->pivotTolerance() < 0.9) { abcFactorization_->pivotTolerance(0.99); problemStatus_ = -1; } else if (numberTimesOptimal_ < 3) { numberTimesOptimal_++; problemStatus_ = -1; } else { unflagVariables = false; //secondaryStatus_ = 1; // and say probably infeasible if ((moreSpecialOptions_ & 256) == 0||(abcState_&CLP_ABC_BEEN_FEASIBLE)!=0) { // try primal problemStatus_ = 10; } else { // almost certainly infeasible problemStatus_ = 1; } #if ABC_NORMAL_DEBUG>3 printf("returning at %d\n", __LINE__); #endif } } } } if (problemStatus_ < 0) { saveGoodStatus(); if (weightsSaved) { // restore weights (if saved) - also recompute infeasibility list abcDualRowPivot_->saveWeights(this, weightsSaved); } else { abcDualRowPivot_->recomputeInfeasibilities(); } } // see if cutoff reached checkCutoff(false); // If we are in trouble and in branch and bound give up if ((specialOptions_ & 1024) != 0) { int looksBad = 0; if (largestPrimalError_ * largestDualError_ > 1.0e2) { looksBad = 1; } else if (largestPrimalError_ > 1.0e-2 && rawObjectiveValue_ > CoinMin(1.0e15, 1.0e3 * limit)) { looksBad = 2; } if (looksBad) { if (abcFactorization_->pivotTolerance() < 0.9) { // up tolerance abcFactorization_->pivotTolerance(CoinMin(abcFactorization_->pivotTolerance() * 1.05 + 0.02, 0.91)); } else if (numberIterations_ > 10000) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 2) printf("bad dual - saying infeasible %d\n", looksBad); #endif problemStatus_ = 1; secondaryStatus_ = 1; // and say was on cutoff } else if (largestPrimalError_ > 1.0e5) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 2) printf("bad dual - going to primal %d %g\n", looksBad, largestPrimalError_); #endif allSlackBasis(); problemStatus_ = 10; } } } //if (problemStatus_ < 0 && !changeMade_) { //problemStatus_ = 4; // unknown //} lastGoodIteration_ = numberIterations_; if (numberIterations_ > lastBadIteration_ + 200) { moreSpecialOptions_ &= ~16; // clear check accuracy flag if (numberFlagged_) { numberFlagged_=0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (flagged(iPivot)) { clearFlagged(iPivot); } } } } if (problemStatus_ < 0&&ignoreStuff!=2) { //sumDualInfeasibilities_ = realDualInfeasibilities; // back to say be careful if (sumDualInfeasibilities_) { numberDualInfeasibilities_ = 1; } else if (!numberPrimalInfeasibilities_) { // Looks good problemStatus_=0; } } double thisObj = abcProgress_.lastObjective(0); double lastObj = abcProgress_.lastObjective(1); if (lastObj > thisObj + 1.0e-4 * CoinMax(fabs(thisObj), fabs(lastObj)) + 1.0e-4&& lastFirstFree_<0) { //printf("BAD - objective backwards\n"); //bounceTolerances(3); numberBlackMarks+=3; } if (numberBlackMarks>0&&numberIterations_>baseIteration_) { // be very careful int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if ((stateOfProblem_&PESSIMISTIC)==0||true) { if (largestDualError_>10.0*CoinMax(lastDualError_,1.0e-6) ||largestPrimalError_>10.0*CoinMax(lastPrimalError_,1.0e-6)) maxFactor = CoinMin(maxFactor,20); forceFactorization_ = CoinMax(1, (maxFactor >> 1)); } else if (numberBlackMarks>2) { forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); } } stateOfProblem_ |= PESSIMISTIC; if (numberBlackMarks>=10) forceFactorization_ = 1; } lastPrimalError_=largestPrimalError_; lastDualError_=largestDualError_; lastFirstFree_=firstFree_; if (ignoreStuff==2) { // in values pass lastFirstFree_=-1; // firstFree_=-1; } if (alphaAccuracy_ > 0.0) alphaAccuracy_ = 1.0; // If we are stopping - use plausible objective // Maybe only in fast dual if (problemStatus_ > 2) rawObjectiveValue_ = approximateObjective; if (problemStatus_ == 1 && (progressFlag_&8) != 0 && fabs(rawObjectiveValue_) > 1.0e10 ) problemStatus_ = 10; // infeasible - but has looked feasible checkMoveBack(true); #if 0 { double * array = usefulArray_[arrayForTableauRow_].denseVector(); for (int iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = abcPivotVariable_[iPivot]; unpack(usefulArray_[arrayForTableauRow_],iSequence); abcFactorization_->updateColumn(usefulArray_[arrayForTableauRow_]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; for (int i = 0; i < numberRows_; i++) assert (fabs(array[i]) < 1.0e-4); usefulArray_[arrayForTableauRow_].clear(); } } #endif #if 0 { // save status, cost and solution unsigned char * saveStatus = CoinCopyOfArray(internalStatus_,numberTotal_); double * saveSolution = CoinCopyOfArray(abcSolution_,numberTotal_); double * saveCost = CoinCopyOfArray(abcCost_,numberTotal_); printf("TestA sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); if (perturbation_>100) CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_); else CoinAbcMemcpy(abcCost_,abcPerturbation_,numberTotal_); moveToBasic(); gutsOfSolution(3); for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { bool changed=fabs(saveCost[iSequence]-abcCost_[iSequence])>1.0e-10; bool bad=false; int iStatus=internalStatus_[iSequence]&7; if (getInternalStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double distanceUp = abcUpper_[iSequence] - abcSolution_[iSequence]; double distanceDown = abcSolution_[iSequence] - abcLower_[iSequence]; double value = abcDj_[iSequence]; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown <= primalTolerance_) { // should not be negative if (value < 0.0) { value = - value; if (value > currentDualTolerance_) { bad=true; } } } else { // free value=fabs(value); if (value > currentDualTolerance_) { bad=true; } } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > 0.0) { if (value > currentDualTolerance_) { bad=true; } } } } if (changed||bad) printf("seq %d status %d current cost %g original %g dj %g %s\n", iSequence,iStatus,saveCost[iSequence],abcCost_[iSequence], abcDj_[iSequence],bad ? "(bad)" : ""); } printf("TestB sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); if (numberDualInfeasibilities_) { makeNonFreeVariablesDualFeasible(); moveToBasic(); gutsOfSolution(3); printf("TestC sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); } CoinAbcMemcpy(internalStatus_,saveStatus,numberTotal_); CoinAbcMemcpy(abcSolution_,saveSolution,numberTotal_); CoinAbcMemcpy(abcCost_,saveCost,numberTotal_); delete [] saveStatus; delete [] saveSolution; delete [] saveCost; moveToBasic(); gutsOfSolution(3); printf("TestD sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); } #endif #if 0 { const double multiplier[] = { 1.0, -1.0}; // sign????????????? double dualT = - currentDualTolerance_; double largestCostDifference=0.1*currentDualTolerance_; int numberCostDifference=0; double largestBadDj=0.0; int numberBadDj=0; double sumBadDj=0.0; double sumCanMoveBad=0.0; int numberCanMoveBad=0; double sumCanMoveOthers=0.0; int numberCanMoveOthers=0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { double costDifference=abcPerturbation_[iSequence]-abcCost_[iSequence]; if (fabs(costDifference)>0.1*currentDualTolerance_) { if (fabs(costDifference)>largestCostDifference) largestCostDifference=fabs(costDifference); numberCostDifference++; } unsigned char iStatus = internalStatus_[iSequence] & 7; if (iStatus<4) { double mult = multiplier[iStatus]; double dj = abcDj_[iSequence] * mult; if (dj < dualT) { sumBadDj+=dualT-dj; numberBadDj++; if (dualT-dj>largestBadDj) largestBadDj=dualT-dj; if (costDifference*mult>0.0) { sumCanMoveBad+=costDifference*mult; numberCanMoveBad++; //dj+=costDifference*mult; abcDj_[iSequence]+=costDifference; abcCost_[iSequence]=abcPerturbation_[iSequence]; } } else if (costDifference*mult>0.0) { sumCanMoveOthers+=costDifference*mult; numberCanMoveOthers++; //dj+=costDifference*mult; abcDj_[iSequence]+=costDifference; abcCost_[iSequence]=abcPerturbation_[iSequence]; } } } if (numberCostDifference+numberBadDj+numberCanMoveBad+numberCanMoveOthers) { printf("largest diff %g (%d), largest bad dj %g (%d - sum %g), can move bad %g (%d), good %g (%d) - %d at fake bound\n",largestCostDifference,numberCostDifference,largestBadDj, numberBadDj, sumBadDj,sumCanMoveBad=0.0,numberCanMoveBad, sumCanMoveOthers,numberCanMoveOthers,numberAtFakeBound()); } } #endif } // see if cutoff reached bool AbcSimplexDual::checkCutoff(bool computeObjective) { double objValue=COIN_DBL_MAX; if (computeObjective) objValue = computeInternalObjectiveValue(); else objValue = minimizationObjectiveValue(); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); // Looks as if numberAtFakeBound() being computed too often if(fabs(limit) < 1.0e30 && objValue > limit && !numberAtFakeBound()) { bool looksInfeasible = !numberDualInfeasibilities_; if (objValue > limit + fabs(0.1 * limit) + 1.0e2 * sumDualInfeasibilities_ + 1.0e4 && sumDualInfeasibilities_ < largestDualError_ && numberIterations_ > 0.5 * numberRows_ + 1000) looksInfeasible = true; if (looksInfeasible&&!computeObjective) objValue = computeInternalObjectiveValue(); if (looksInfeasible) { // Even if not perturbed internal costs may have changed // be careful if(objValue > limit) { problemStatus_ = 1; secondaryStatus_ = 1; // and say was on cutoff return true; } } } return false; } #define CLEANUP_DJS 0 /* While updateDualsInDual sees what effect is of flip this does actual flipping. If change >0.0 then value in array >0.0 => from lower to upper returns 3 if skip this iteration and re-factorize */ int AbcSimplexDual::flipBounds() { CoinIndexedVector & array = usefulArray_[arrayForFlipBounds_]; CoinIndexedVector & output = usefulArray_[arrayForFlipRhs_]; output.clear(); int numberFlipped=array.getNumElements(); if (numberFlipped) { #if CLP_CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)==0) { #endif // do actual flips // do in parallel once got spare space in factorization #if ABC_PARALLEL==2 #endif int number=array.getNumElements(); const int * COIN_RESTRICT which=array.getIndices(); double * COIN_RESTRICT work = array.denseVector(); double * COIN_RESTRICT solution = abcSolution_; const double * COIN_RESTRICT lower = abcLower_; const double * COIN_RESTRICT upper = abcUpper_; #if CLEANUP_DJS double * COIN_RESTRICT cost = abcCost_; double * COIN_RESTRICT dj = abcDj_; // see if we can clean up djs // may have perturbation const double * COIN_RESTRICT originalCost = abcPerturbation_; #else const double * COIN_RESTRICT cost = abcCost_; const double * COIN_RESTRICT dj = abcDj_; #endif const double multiplier[] = { 1.0, -1.0}; for (int i = 0; i < number; i++) { double value=work[i]*theta_; work[i]=0.0; int iSequence = which[i]; unsigned char iStatus = internalStatus_[iSequence]&3; assert ((internalStatus_[iSequence]&7)==0|| (internalStatus_[iSequence]&7)==1); double mult = multiplier[iStatus]; double djValue = dj[iSequence] * mult-value; //double perturbedTolerance = abcPerturbation_[iSequence]; if (djValue<-currentDualTolerance_) { // might just happen - if so just skip assert (iSequence!=sequenceIn_); double movement=(upper[iSequence]-lower[iSequence])*mult; if (iStatus==0) { // at lower bound // to upper bound setInternalStatus(iSequence, atUpperBound); solution[iSequence] = upper[iSequence]; #if CLEANUP_DJS if (cost[iSequence]originalCost[iSequence]) { double difference = CoinMin(cost[iSequence]-originalCost[iSequence],-djValue); dj[iSequence]-=difference; cost[iSequence]-=difference; } #endif } abcMatrix_->add(output, iSequence, movement); objectiveChange_ += cost[iSequence]*movement; } } array.setNumElements(0); // double check something flipped if (output.getNumElements()) { #if ABC_PARALLEL==0 abcFactorization_->updateColumn(output); #else assert (FACTOR_CPU>2); abcFactorization_->updateColumnCpu(output,1); #endif abcDualRowPivot_->updatePrimalSolution(output,1.0); } #if CLP_CAN_HAVE_ZERO_OBJ>1 } else { clearArrays(3); } #endif } // recompute dualOut_ valueOut_ = solutionBasic_[pivotRow_]; if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } #if 0 // amount primal will move movement_ = -dualOut_ * directionOut_ / alpha_; double movementOld = oldDualOut * directionOut_ / alpha_; // so objective should increase by fabs(dj)*movement_ // but we already have objective change - so check will be good if (objectiveChange_ + fabs(movementOld * dualIn_) < -CoinMax(1.0e-5, 1.0e-12 * fabs(rawObjectiveValue_))) { #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() & 32) printf("movement %g, movementOld %g swap change %g, rest %g * %g\n", objectiveChange_ + fabs(movement_ * dualIn_), movementOld,objectiveChange_, movement_, dualIn_); #endif } if (0) { if(abcFactorization_->pivots()) { // going backwards - factorize problemStatus_ = -2; // factorize now stateOfIteration_=2; } } #endif return numberFlipped; } /* Undo a flip */ void AbcSimplexDual::flipBack(int number) { CoinIndexedVector & array = usefulArray_[arrayForFlipBounds_]; const int * COIN_RESTRICT which=array.getIndices(); double * COIN_RESTRICT solution = abcSolution_; const double * COIN_RESTRICT lower = abcLower_; const double * COIN_RESTRICT upper = abcUpper_; for (int i = 0; i < number; i++) { int iSequence = which[i]; unsigned char iStatus = internalStatus_[iSequence]&3; assert ((internalStatus_[iSequence]&7)==0|| (internalStatus_[iSequence]&7)==1); if (iStatus==0) { // at lower bound // to upper bound setInternalStatus(iSequence, atUpperBound); solution[iSequence] = upper[iSequence]; } else { // at upper bound // to lower bound setInternalStatus(iSequence, atLowerBound); solution[iSequence] = lower[iSequence]; } } } // Restores bound to original bound void AbcSimplexDual::originalBound( int iSequence) { if (getFakeBound(iSequence) != noFake) { numberFake_--;; setFakeBound(iSequence, noFake); abcLower_[iSequence] = lowerSaved_[iSequence]; abcUpper_[iSequence] = upperSaved_[iSequence]; } } /* As changeBounds but just changes new bounds for a single variable. Returns true if change */ bool AbcSimplexDual::changeBound( int iSequence) { // old values double oldLower = abcLower_[iSequence]; double oldUpper = abcUpper_[iSequence]; double value = abcSolution_[iSequence]; bool modified = false; // original values double lowerValue = lowerSaved_[iSequence]; double upperValue = upperSaved_[iSequence]; setFakeBound(iSequence,noFake); if (value == oldLower) { if (upperValue > oldLower + currentDualBound_) { abcUpper_[iSequence] = oldLower + currentDualBound_; setFakeBound(iSequence, upperFake); assert (abcLower_[iSequence]==lowerSaved_[iSequence]); assert (abcUpper_[iSequence]lowerSaved_[iSequence]); assert (abcUpper_[iSequence]==upperSaved_[iSequence]); modified = true; numberFake_++; } } else { assert(value == oldLower || value == oldUpper); } return modified; } /* Checks number of variables at fake bounds. This is used by fastDual so can exit gracefully before end */ int AbcSimplexDual::numberAtFakeBound() { int numberFake = 0; if (numberFake_) { for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { FakeBound bound = getFakeBound(iSequence); switch(getInternalStatus(iSequence)) { case basic: break; case isFree: case superBasic: case AbcSimplex::isFixed: //setFakeBound (iSequence, noFake); break; case atUpperBound: if (bound == upperFake || bound == bothFake) numberFake++; break; case atLowerBound: if (bound == lowerFake || bound == bothFake) numberFake++; break; } } } return numberFake; } int AbcSimplexDual::resetFakeBounds(int type) { if (type == 0||type==1) { // put back original bounds and then check //CoinAbcMemcpy(abcLower_,lowerSaved_,numberTotal_); //CoinAbcMemcpy(abcUpper_,upperSaved_,numberTotal_); double dummyChangeCost = 0.0; return changeBounds(3+type, dummyChangeCost); } else if (type < 0) { #ifndef NDEBUG // just check int iSequence; int nFake = 0; int nErrors = 0; int nSuperBasic = 0; int nWarnings = 0; for (iSequence = 0; iSequence < numberTotal_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); Status status = getInternalStatus(iSequence); bool isFake = false; #ifdef CLP_INVESTIGATE char RC = 'C'; int jSequence = iSequence; if (jSequence >= numberColumns_) { RC = 'R'; jSequence -= numberColumns_; } #endif double lowerValue = lowerSaved_[iSequence]; double upperValue = upperSaved_[iSequence]; double value = abcSolution_[iSequence]; CoinRelFltEq equal; if (status == atUpperBound || status == atLowerBound) { if (fakeStatus == AbcSimplexDual::upperFake) { if(!equal(abcUpper_[iSequence], (lowerValue + currentDualBound_)) || !(equal(abcUpper_[iSequence], value) || equal(abcLower_[iSequence], value))) { nErrors++; #ifdef CLP_INVESTIGATE printf("** upperFake %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue); #endif } isFake = true;; } else if (fakeStatus == AbcSimplexDual::lowerFake) { if(!equal(abcLower_[iSequence], (upperValue - currentDualBound_)) || !(equal(abcUpper_[iSequence], value) || equal(abcLower_[iSequence], value))) { nErrors++; #ifdef CLP_INVESTIGATE printf("** lowerFake %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue); #endif } isFake = true;; } else if (fakeStatus == AbcSimplexDual::bothFake) { nWarnings++; #ifdef CLP_INVESTIGATE printf("** %d at bothFake?\n", iSequence); #endif } else if (abcUpper_[iSequence] - abcLower_[iSequence] > 2.0 * currentDualBound_) { nErrors++; #ifdef CLP_INVESTIGATE printf("** noFake! %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue); #endif } } else if (status == superBasic || status == isFree) { nSuperBasic++; //printf("** free or superbasic %c%d %g <= %g <= %g true %g, %g - status %d\n", // RC,jSequence,abcLower_[iSequence],abcSolution_[iSequence], // abcUpper_[iSequence],lowerValue,upperValue,status); } else if (status == basic) { bool odd = false; if (!equal(abcLower_[iSequence], lowerValue)) odd = true; if (!equal(abcUpper_[iSequence], upperValue)) odd = true; if (odd) { #ifdef CLP_INVESTIGATE printf("** basic %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue); #endif nWarnings++; } } else if (status == isFixed) { if (!equal(abcUpper_[iSequence], abcLower_[iSequence])) { nErrors++; #ifdef CLP_INVESTIGATE printf("** fixed! %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue); #endif } } if (isFake) { nFake++; } else { if (fakeStatus != AbcSimplexDual::noFake) { nErrors++; #ifdef CLP_INVESTIGATE printf("** bad fake status %c%d %d\n", RC, jSequence, fakeStatus); #endif } } } if (nFake != numberFake_) { #ifdef CLP_INVESTIGATE printf("nfake %d numberFake %d\n", nFake, numberFake_); #endif nErrors++; } if (nErrors || type <= -1000) { #ifdef CLP_INVESTIGATE printf("%d errors, %d warnings, %d free/superbasic, %d fake\n", nErrors, nWarnings, nSuperBasic, numberFake_); printf("currentDualBound %g\n", currentDualBound_); #endif if (type <= -1000) { iSequence = -type; iSequence -= 1000; #ifdef CLP_INVESTIGATE char RC = 'C'; int jSequence = iSequence; if (jSequence >= numberColumns_) { RC = 'R'; jSequence -= numberColumns_; } double lowerValue = lowerSaved_[iSequence]; double upperValue = upperSaved_[iSequence]; printf("*** movement>1.0e30 for %c%d %g <= %g <= %g true %g, %g - status %d\n", RC, jSequence, abcLower_[iSequence], abcSolution_[iSequence], abcUpper_[iSequence], lowerValue, upperValue, internalStatus_[iSequence]); #endif assert (nErrors); // should have been picked up } assert (!nErrors); } #endif } else { CoinAbcMemcpy(abcLower_,lowerSaved_,numberTotal_); CoinAbcMemcpy(abcUpper_,upperSaved_,numberTotal_); // reset using status numberFake_ = 0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); if (fakeStatus != AbcSimplexDual::noFake) { Status status = getInternalStatus(iSequence); if (status == basic) { setFakeBound(iSequence, AbcSimplexDual::noFake); continue; } double lowerValue = abcLower_[iSequence]; double upperValue = abcUpper_[iSequence]; double value = abcSolution_[iSequence]; numberFake_++; if (fakeStatus == AbcSimplexDual::upperFake) { abcUpper_[iSequence] = lowerValue + currentDualBound_; if (status == AbcSimplex::atLowerBound) { abcSolution_[iSequence] = lowerValue; } else if (status == AbcSimplex::atUpperBound) { abcSolution_[iSequence] = abcUpper_[iSequence]; } else { abort(); } } else if (fakeStatus == AbcSimplexDual::lowerFake) { abcLower_[iSequence] = upperValue - currentDualBound_; if (status == AbcSimplex::atLowerBound) { abcSolution_[iSequence] = abcLower_[iSequence]; } else if (status == AbcSimplex::atUpperBound) { abcSolution_[iSequence] = upperValue; } else { abort(); } } else { assert (fakeStatus == AbcSimplexDual::bothFake); if (status == AbcSimplex::atLowerBound) { abcLower_[iSequence] = value; abcUpper_[iSequence] = value + currentDualBound_; } else if (status == AbcSimplex::atUpperBound) { abcUpper_[iSequence] = value; abcLower_[iSequence] = value - currentDualBound_; } else if (status == AbcSimplex::isFree || status == AbcSimplex::superBasic) { abcLower_[iSequence] = value - 0.5 * currentDualBound_; abcUpper_[iSequence] = value + 0.5 * currentDualBound_; } else { abort(); } } } } } return -1; } // maybe could JUST check against perturbationArray void AbcSimplex::checkDualSolutionPlusFake() { sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; sumFakeInfeasibilities_=0.0; int firstFreePrimal = -1; int firstFreeDual = -1; int numberSuperBasicWithDj = 0; bestPossibleImprovement_ = 0.0; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, largestDualError_); // allow tolerance at least slightly bigger than standard double relaxedTolerance = currentDualTolerance_ + error; // allow bigger tolerance for possible improvement double possTolerance = 5.0 * relaxedTolerance; sumOfRelaxedDualInfeasibilities_ = 0.0; //rawObjectiveValue_ -=sumNonBasicCosts_; sumNonBasicCosts_ = 0.0; const double * COIN_RESTRICT abcLower = abcLower_; const double * COIN_RESTRICT abcUpper = abcUpper_; const double * COIN_RESTRICT abcSolution = abcSolution_; #ifdef CLEANUP_DJS double * COIN_RESTRICT abcDj = abcDj_; double * COIN_RESTRICT abcCost = abcCost_; // see if we can clean up djs // may have perturbation const double * COIN_RESTRICT originalCost = abcPerturbation_; #else const double * COIN_RESTRICT abcDj = abcDj_; const double * COIN_RESTRICT abcCost = abcCost_; #endif //const double * COIN_RESTRICT abcPerturbation = abcPerturbation_; int badDjSequence=-1; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic) { sumNonBasicCosts_ += abcSolution[iSequence]*abcCost[iSequence]; // not basic double distanceUp = abcUpper[iSequence] - abcSolution[iSequence]; double distanceDown = abcSolution[iSequence] - abcLower[iSequence]; double value = abcDj[iSequence]; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown <= primalTolerance_) { // should not be negative if (value < 0.0) { value = - value; if (value > currentDualTolerance_) { bool treatAsSuperBasic=false; if (getInternalStatus(iSequence)==superBasic) { #ifdef PAN if (fakeSuperBasic(iSequence)>=0) { #endif treatAsSuperBasic=true; numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; #ifdef PAN } #endif } if (!treatAsSuperBasic) { sumDualInfeasibilities_ += value - currentDualTolerance_; badDjSequence=iSequence; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } #ifdef CLEANUP_DJS } else { // adjust cost etc if (abcCost[iSequence]>originalCost[iSequence]) { double difference = CoinMin(abcCost[iSequence]-originalCost[iSequence],value); //printf("Lb %d changing cost from %g to %g, dj from %g to %g\n", // iSequence,abcCost[iSequence],abcCost[iSequence]-difference, // abcDj[iSequence],abcDj[iSequence]-difference); abcDj[iSequence]=value-difference; abcCost[iSequence]-=difference; } #endif } } else { // free value=fabs(value); if (value > 1.0 * relaxedTolerance) { numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; } if (value > currentDualTolerance_) { sumDualInfeasibilities_ += value - currentDualTolerance_; if (value > possTolerance) bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value; if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } if (firstFreePrimal < 0) firstFreePrimal = iSequence; } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > 0.0) { if (value > currentDualTolerance_) { bool treatAsSuperBasic=false; if (getInternalStatus(iSequence)==superBasic) { #ifdef PAN if (fakeSuperBasic(iSequence)>=0) { #endif treatAsSuperBasic=true; numberSuperBasicWithDj++; if (firstFreeDual < 0) firstFreeDual = iSequence; #ifdef PAN } #endif } if (!treatAsSuperBasic) { sumDualInfeasibilities_ += value - currentDualTolerance_; badDjSequence=iSequence; if (value > possTolerance) bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10); if (value > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance; numberDualInfeasibilities_ ++; } } #ifdef CLEANUP_DJS } else { // adjust cost etc if (abcCost[iSequence]=0); abcCost[badDjSequence]-=abcDj_[badDjSequence]; abcDj_[badDjSequence]=0.0; } #endif numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_-numberSuperBasicWithDj; numberFreeNonBasic_=numberSuperBasicWithDj; firstFree_=-1; if (algorithm_ < 0 && firstFreeDual >= 0) { // dual firstFree_ = firstFreeDual; } else if ((numberSuperBasicWithDj || (abcProgress_.lastIterationNumber(0) <= 0))&&algorithm_>0) { firstFree_ = firstFreePrimal; } } // Perturbs problem void AbcSimplexDual::perturb(double factor) { const double * COIN_RESTRICT lower = lowerSaved_; const double * COIN_RESTRICT upper = upperSaved_; const double * COIN_RESTRICT perturbation = abcPerturbation_; double * COIN_RESTRICT cost = abcCost_; for (int i=0;i0 #define PERT_STATISTICS #endif #ifdef PERT_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, -3.0e4, -1.0e4, -3.0e3, -1.0e3, -3.0e2, -1.0e2, -3.0e1, -1.0e1, -3.0, -1.0, -3.0e-1, -1.0e-1, -3.0e-1, -1.0e-2, -3.0e-2, -1.0e-3, -3.0e-3, -1.0e-4, -3.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, 3.0e-5, 1.0e-4, 3.0e-4, 1.0e-3, 3.0e-3, 1.0e-2, 3.0e-2, 1.0e-1, 3.0e-1, 1.0, 3.0, 1.0e1, 3.0e1, 1.0e2, 3.0e2, 1.0e3, 3.0e3, 1.0e4, 3.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; } #endif // Perturbs problem void AbcSimplexDual::perturbB(double /*factorIn*/,int /*type*/) { double overallMultiplier= (perturbation_==50||perturbation_>54) ? 1.0 : 0.1; // dual perturbation double perturbation = 1.0e-20; // maximum fraction of cost to perturb double maximumFraction = 1.0e-5; int maxLength = 0; int minLength = numberRows_; double averageCost = 0.0; int numberNonZero = 0; // See if we need to perturb double * COIN_RESTRICT sort = new double[numberColumns_]; // Use objective BEFORE scaling ?? const double * COIN_RESTRICT obj = objective(); for (int i = 0; i < numberColumns_; i++) { double value = fabs(obj[i]); sort[i] = value; averageCost += fabs(abcCost_[i+maximumAbcNumberRows_]); if (value) numberNonZero++; } if (numberNonZero) averageCost /= static_cast (numberNonZero); else averageCost = 1.0; // allow for cost scaling averageCost *= objectiveScale_; std::sort(sort, sort + numberColumns_); int number = 1; double last = sort[0]; for (int i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } delete [] sort; #ifdef PERT_STATISTICS printf("%d different values\n",number); #endif #if 0 printf("nnz %d percent %d", number, (number * 100) / numberColumns_); if (number * 4 > numberColumns_) printf(" - Would not perturb\n"); else printf(" - Would perturb\n"); #endif // If small costs then more dangerous (better to scale) double numberMultiplier=1.25; if (averageCost<1.0e-3) numberMultiplier=20.0; else if (averageCost<1.0e-2) numberMultiplier=10.0; else if (averageCost<1.0e-1) numberMultiplier=3.0; else if (averageCost<1.0) numberMultiplier=2.0; numberMultiplier *= 2.0; // try if (number * numberMultiplier > numberColumns_||perturbation_>=100) { perturbation_=101; #if ABC_NORMAL_DEBUG>0 printf("Not perturbing - %d different costs, average %g\n", number,averageCost); #endif #ifdef CLEANUP_DJS // copy cost to perturbation CoinAbcMemcpy(abcPerturbation_,abcCost_,numberTotal_); #endif return ; // good enough } const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths()-maximumAbcNumberRows_; const double * COIN_RESTRICT lower = lowerSaved_; const double * COIN_RESTRICT upper = upperSaved_; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { if (lower[iSequence] < upper[iSequence]) { int length = columnLength[iSequence]; if (length > 2) { maxLength = CoinMax(maxLength, length); minLength = CoinMin(minLength, length); } } } bool uniformChange = false; bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; double constantPerturbation = 10.0 * dualTolerance_; #ifdef PERT_STATISTICS breakdown("Objective before perturbation", numberColumns_, abcCost_+numberRows_); #endif //#define PERTURB_OLD_WAY #ifndef PERTURB_OLD_WAY #if 1 #ifdef HEAVY_PERTURBATION if (perturbation_==50) perturbation_=HEAVY_PERTURBATION; #endif if (perturbation_ >= 50) { // Experiment // maximumFraction could be 1.0e-10 to 1.0 double m[] = {1.0e-10, 1.0e-9, 1.0e-8, 1.0e-7, 1.0e-6, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0}; int whichOne = CoinMin(perturbation_ - 51,10); if (whichOne<0) { if (numberRows_<5000) whichOne=2; // treat 50 as if 53 else whichOne=2; // treat 50 as if 52 } if (inCbcOrOther&&whichOne>0) whichOne--; maximumFraction = m[whichOne]; if (whichOne>7) constantPerturbation *= 10.0; //if (whichOne<2) //constantPerturbation = maximumFraction*1.0e-10 * dualTolerance_; } else if (inCbcOrOther) { maximumFraction = 1.0e-6; } #endif double smallestNonZero = 1.0e100; bool modifyRowCosts=false; numberNonZero = 0; //perturbation = 1.0e-10; perturbation = CoinMax(1.0e-10,maximumFraction); double * COIN_RESTRICT cost = abcCost_; bool allSame = true; double lastValue = 0.0; for (int iRow = 0; iRow < numberRows_; iRow++) { double lo = lower[iRow]; double up = upper[iRow]; if (lo < up) { double value = fabs(cost[iRow]); perturbation = CoinMax(perturbation, value); if (value) { modifyRowCosts = true; smallestNonZero = CoinMin(smallestNonZero, value); } } if (lo && lo > -1.0e10) { numberNonZero++; lo = fabs(lo); if (!lastValue) lastValue = lo; else if (fabs(lo - lastValue) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { numberNonZero++; up = fabs(up); if (!lastValue) lastValue = up; else if (fabs(up - lastValue) > 1.0e-7) allSame = false; } } double lastValue2 = 0.0; for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { double lo = lower[iSequence]; double up = upper[iSequence]; if (lo < up) { double value = fabs(cost[iSequence]); perturbation = CoinMax(perturbation, value); if (value) { smallestNonZero = CoinMin(smallestNonZero, value); } } if (lo && lo > -1.0e10) { //numberNonZero++; lo = fabs(lo); if (!lastValue2) lastValue2 = lo; else if (fabs(lo - lastValue2) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { //numberNonZero++; up = fabs(up); if (!lastValue2) lastValue2 = up; else if (fabs(up - lastValue2) > 1.0e-7) allSame = false; } } if (allSame) { // Check elements double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); if (smallestNegative == largestNegative && smallestPositive == largestPositive) { // Really hit perturbation double adjust = CoinMin(100.0 * maximumFraction, 1.0e-3 * CoinMax(lastValue, lastValue2)); maximumFraction = CoinMax(adjust, maximumFraction); } } perturbation = CoinMin(perturbation, smallestNonZero / maximumFraction); double largestZero = 0.0; double largest = 0.0; double largestPerCent = 0.0; // modify costs bool printOut = (handler_->logLevel() == 63); printOut = false; //assert (!modifyRowCosts); modifyRowCosts = false; const double * COIN_RESTRICT perturbationArray = perturbationSaved_; if (modifyRowCosts) { for (int iRow = 0; iRow < numberRows_; iRow++) { if (lower[iRow] < upper[iRow]) { double value = perturbation; double currentValue = cost[iRow]; value = CoinMin(value, maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-3)); double perturbationValue=2.0*(perturbationArray[iRow]-0.5); // for now back to normal random if (lower[iRow] > -largeValue_) { if (fabs(lower[iRow]) < fabs(upper[iRow])) value *= perturbationValue; else value *= -perturbationValue; } else if (upper[iRow] < largeValue_) { value *= -perturbationValue; } else { value = 0.0; } if (currentValue) { largest = CoinMax(largest, fabs(value)); if (fabs(value) > fabs(currentValue)*largestPerCent) largestPerCent = fabs(value / currentValue); } else { largestZero = CoinMax(largestZero, fabs(value)); } if (printOut) printf("row %d cost %g change %g\n", iRow, cost[iRow], value); cost[iRow] += value; } } } //double extraWeight = 10.0; // more its but faster double weight[]={1.0e-4,1.0e-2,1.0e-1,1.0,2.0,10.0,100.0,200.0,400.0,600.0,1000.0}; // good its double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,2.0,5.0,10.0,20.0,30.0,40.0,100.0}; double weight[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 40.0, 100.0}; //double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,20.0,50.0,100.0,120.0,130.0,140.0,200.0}; // Scale back if wanted double weight2[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; if (constantPerturbation < 99.0 * dualTolerance_&&false) { perturbation *= 0.1; //extraWeight = 0.5; memcpy(weight, weight2, sizeof(weight2)); } // adjust weights if all columns long double factor = 1.0; if (maxLength) { factor = 3.0 / static_cast (minLength); } // Make variables with more elements more expensive const double m1 = 0.5; double smallestAllowed = overallMultiplier*CoinMin(1.0e-2 * dualTolerance_, maximumFraction); double largestAllowed = overallMultiplier*CoinMax(1.0e3 * dualTolerance_, maximumFraction * averageCost); // smaller if in BAB //if (inCbcOrOther) //largestAllowed=CoinMin(largestAllowed,1.0e-5); //smallestAllowed = CoinMin(smallestAllowed,0.1*largestAllowed); randomNumberGenerator_.setSeed(1000000000); #if ABC_NORMAL_DEBUG>0 printf("perturbation %g constantPerturbation %g smallestNonZero %g maximumFraction %g smallestAllowed %g\n", perturbation,constantPerturbation,smallestNonZero,maximumFraction, smallestAllowed); #endif for (int iSequence = maximumAbcNumberRows_; iSequence < numberTotal_; iSequence++) { if (lower[iSequence] < upper[iSequence] && getInternalStatus(iSequence) != basic) { double value = perturbation; double currentValue = cost[iSequence]; double currentLargestAllowed=fabs(currentValue)*1.0e-3; if (!currentValue) currentLargestAllowed=1.0e-3; if (currentLargestAllowed<=10.0*smallestAllowed) continue; // don't perturb tiny value value = CoinMin(value, constantPerturbation + maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-8)); //value = CoinMin(value,constantPerturbation;+maximumFraction*fabs(currentValue)); double value2 = constantPerturbation + 1.0e-1 * smallestNonZero; if (uniformChange) { value = maximumFraction; value2 = maximumFraction; } //double perturbationValue=2.0*(perturbationArray[iSequence]-0.5); // for now back to normal random double perturbationValue=randomNumberGenerator_.randomDouble(); perturbationValue = 1.0-m1+m1*perturbationValue; // clean up if (lower[iSequence] > -largeValue_) { if (fabs(lower[iSequence]) < fabs(upper[iSequence])) { value *= perturbationValue; value2 *= perturbationValue; } else { //value *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); //value2 *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); value = 0.0; } } else if (upper[iSequence] < largeValue_) { value *= -perturbationValue; value2 *= -perturbationValue; } else { value = 0.0; } if (value) { int length = columnLength[iSequence]; if (length > 3) { length = static_cast (static_cast (length) * factor); length = CoinMax(3, length); } double multiplier; if (length < 10) multiplier = weight[length]; else multiplier = weight[10]; value *= multiplier; value = CoinMin(value, value2); if (value) { // get in range if (fabs(value) <= smallestAllowed) { value *= 10.0; while (fabs(value) <= smallestAllowed) value *= 10.0; } else if (fabs(value) > currentLargestAllowed) { value *= 0.1; while (fabs(value) > currentLargestAllowed) value *= 0.1; } } if (currentValue) { largest = CoinMax(largest, fabs(value)); if (fabs(value) > fabs(currentValue)*largestPerCent) largestPerCent = fabs(value / currentValue); } else { largestZero = CoinMax(largestZero, fabs(value)); } // but negative if at ub if (getInternalStatus(iSequence) == atUpperBound) value = -value; if (printOut) printf("col %d cost %g change %g\n", iSequence, cost[iSequence], value); cost[iSequence] += value; } } } #else // old way if (perturbation_ > 50) { // Experiment // maximumFraction could be 1.0e-10 to 1.0 double m[] = {1.0e-10, 1.0e-9, 1.0e-8, 1.0e-7, 1.0e-6, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0}; int whichOne = perturbation_ - 51; //if (inCbcOrOther&&whichOne>0) //whichOne--; maximumFraction = m[CoinMin(whichOne, 10)]; } else if (inCbcOrOther) { //maximumFraction = 1.0e-6; } int iRow; double smallestNonZero = 1.0e100; numberNonZero = 0; if (perturbation_ >= 50) { perturbation = 1.0e-8; if (perturbation_ > 50 && perturbation_ < 60) perturbation = CoinMax(1.0e-8,maximumFraction); bool allSame = true; double lastValue = 0.0; for (iRow = 0; iRow < numberRows_; iRow++) { double lo = abcLower_[iRow]; double up = abcUpper_[iRow]; if (lo && lo > -1.0e10) { numberNonZero++; lo = fabs(lo); if (!lastValue) lastValue = lo; else if (fabs(lo - lastValue) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { numberNonZero++; up = fabs(up); if (!lastValue) lastValue = up; else if (fabs(up - lastValue) > 1.0e-7) allSame = false; } } double lastValue2 = 0.0; for (int iColumn = maximumAbcNumberRows_; iColumn < numberTotal_; iColumn++) { double lo = abcLower_[iColumn]; double up = abcUpper_[iColumn]; if (lo < up) { double value = fabs(abcCost_[iColumn]); perturbation = CoinMax(perturbation, value); if (value) { smallestNonZero = CoinMin(smallestNonZero, value); } } if (lo && lo > -1.0e10) { //numberNonZero++; lo = fabs(lo); if (!lastValue2) lastValue2 = lo; else if (fabs(lo - lastValue2) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { //numberNonZero++; up = fabs(up); if (!lastValue2) lastValue2 = up; else if (fabs(up - lastValue2) > 1.0e-7) allSame = false; } } if (allSame) { // Check elements double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); if (smallestNegative == largestNegative && smallestPositive == largestPositive) { // Really hit perturbation double adjust = CoinMin(100.0 * maximumFraction, 1.0e-3 * CoinMax(lastValue, lastValue2)); maximumFraction = CoinMax(adjust, maximumFraction); } } perturbation = CoinMin(perturbation, smallestNonZero / maximumFraction); } double largestZero = 0.0; double largest = 0.0; double largestPerCent = 0.0; // modify costs bool printOut = (handler_->logLevel() == 63); printOut = false; // more its but faster double weight[]={1.0e-4,1.0e-2,1.0e-1,1.0,2.0,10.0,100.0,200.0,400.0,600.0,1000.0}; // good its double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,2.0,5.0,10.0,20.0,30.0,40.0,100.0}; double weight[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 40.0, 100.0}; //double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,20.0,50.0,100.0,120.0,130.0,140.0,200.0}; //double extraWeight = 10.0; // Scale back if wanted double weight2[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; if (constantPerturbation < 99.0 * dualTolerance_) { perturbation *= 0.1; //extraWeight = 0.5; memcpy(weight, weight2, sizeof(weight2)); } // adjust weights if all columns long double factor = 1.0; if (maxLength) { factor = 3.0 / static_cast (minLength); } // Make variables with more elements more expensive const double m1 = 0.5; double smallestAllowed = CoinMin(1.0e-2 * dualTolerance_, maximumFraction); double largestAllowed = CoinMax(1.0e3 * dualTolerance_, maximumFraction * averageCost); // smaller if in BAB //if (inCbcOrOther) //largestAllowed=CoinMin(largestAllowed,1.0e-5); //smallestAllowed = CoinMin(smallestAllowed,0.1*largestAllowed); for (int iColumn = maximumAbcNumberRows_; iColumn < numberTotal_; iColumn++) { if (abcLower_[iColumn] < abcUpper_[iColumn] && getInternalStatus(iColumn) != basic) { double value = perturbation; double currentValue = abcCost_[iColumn]; value = CoinMin(value, constantPerturbation + maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-8)); //value = CoinMin(value,constantPerturbation;+maximumFraction*fabs(currentValue)); double value2 = constantPerturbation + 1.0e-1 * smallestNonZero; if (uniformChange) { value = maximumFraction; value2 = maximumFraction; } if (abcLower_[iColumn] > -largeValue_) { if (fabs(abcLower_[iColumn]) < fabs(abcUpper_[iColumn])) { value *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); value2 *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); } else { //value *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); //value2 *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); value = 0.0; } } else if (abcUpper_[iColumn] < largeValue_) { value *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); value2 *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); } else { value = 0.0; } if (value) { int length = columnLength[iColumn]; if (length > 3) { length = static_cast (static_cast (length) * factor); length = CoinMax(3, length); } double multiplier; #if 1 if (length < 10) multiplier = weight[length]; else multiplier = weight[10]; #else if (length < 10) multiplier = weight[length]; else multiplier = weight[10] + extraWeight * (length - 10); multiplier *= 0.5; #endif value *= multiplier; value = CoinMin(value, value2); if (value) { // get in range if (fabs(value) <= smallestAllowed) { value *= 10.0; while (fabs(value) <= smallestAllowed) value *= 10.0; } else if (fabs(value) > largestAllowed) { value *= 0.1; while (fabs(value) > largestAllowed) value *= 0.1; } } if (currentValue) { largest = CoinMax(largest, fabs(value)); if (fabs(value) > fabs(currentValue)*largestPerCent) largestPerCent = fabs(value / currentValue); } else { largestZero = CoinMax(largestZero, fabs(value)); } // but negative if at ub if (getInternalStatus(iColumn) == atUpperBound) value = -value; if (printOut) printf("col %d cost %g change %g\n", iColumn, objectiveWork_[iColumn], value); abcCost_[iColumn] += value; } } } #endif #ifdef PERT_STATISTICS { double averageCost = 0.0; int numberNonZero = 0; double * COIN_RESTRICT sort = new double[numberColumns_]; for (int i = 0; i < numberColumns_; i++) { double value = fabs(abcCost_[i+maximumAbcNumberRows_]); sort[i] = value; averageCost += value; if (value) numberNonZero++; } if (numberNonZero) averageCost /= static_cast (numberNonZero); else averageCost = 1.0; std::sort(sort, sort + numberColumns_); int number = 1; double last = sort[0]; for (int i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } delete [] sort; #if ABC_NORMAL_DEBUG>0 printf("nnz %d percent %d", number, (number * 100) / numberColumns_); breakdown("Objective after perturbation", numberColumns_, abcCost_+numberRows_); #endif } #endif perturbation_=100; // copy cost to perturbation #ifdef CLEANUP_DJS CoinAbcMemcpy(abcPerturbation_,abcCost_,numberTotal_); #endif handler_->message(CLP_SIMPLEX_PERTURB, messages_) << 100.0 * maximumFraction << perturbation << largest << 100.0 * largestPerCent << largestZero << CoinMessageEol; } /* Does something about fake tolerances -1 initializes 1 might be optimal (back to original costs) 2 after change currentDualBound 3 might be optimal BUT change currentDualBound */ int AbcSimplexDual::bounceTolerances(int type) { // for now turn off if (type==-1) { if (!perturbationFactor_) perturbationFactor_=0.001; CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_); if (!perturbationFactor_) { //currentDualBound_=CoinMin(dualBound_,1.0e11); //CoinAbcMultiplyAdd(perturbationSaved_,numberTotal_,currentDualTolerance_, // abcPerturbation_,0.0); } else { //currentDualBound_=CoinMin(dualBound_,1.0e11); double factor=currentDualTolerance_*perturbationFactor_; perturbB(factor,0); } #if ABC_NORMAL_DEBUG>0 //printf("new dual bound %g (bounceTolerances)\n",currentDualBound_); #endif } else { if (stateDualColumn_==-2) { double newTolerance=CoinMin(1.0e-1,dualTolerance_*100.0); #if ABC_NORMAL_DEBUG>0 printf("After %d iterations reducing dual tolerance from %g to %g\n", numberIterations_,currentDualTolerance_,newTolerance); #endif currentDualTolerance_=newTolerance; stateDualColumn_=-1; } else if (stateDualColumn_==-1) { #if ABC_NORMAL_DEBUG>0 printf("changing dual tolerance from %g to %g (vaguely optimal)\n", currentDualTolerance_,dualTolerance_); #endif currentDualTolerance_=dualTolerance_; stateDualColumn_=0; } else { if (stateDualColumn_>1) { normalDualColumnIteration_ = numberIterations_+CoinMax(10,numberRows_/4); #if ABC_NORMAL_DEBUG>0 printf("no cost modification until iteration %d\n",normalDualColumnIteration_); #endif } } resetFakeBounds(0); CoinAbcMemcpy(abcCost_,abcPerturbation_,numberTotal_); numberChanged_ = 0; // Number of variables with changed costs moveToBasic(); if (type!=1) return 0; // save status and solution CoinAbcMemcpy(status_,internalStatus_,numberTotal_); CoinAbcMemcpy(solutionSaved_,abcSolution_,numberTotal_); #if ABC_NORMAL_DEBUG>0 printf("A sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif gutsOfSolution(3); #if ABC_NORMAL_DEBUG>0 printf("B sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif double saveSum1=sumPrimalInfeasibilities_; double saveSumD1=sumDualInfeasibilities_; bool goToPrimal=false; if (!sumOfRelaxedDualInfeasibilities_) { if (perturbation_<101) { // try going back to original costs CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_); perturbation_=101; numberChanged_ = 0; // Number of variables with changed costs moveToBasic(); gutsOfSolution(3); #if ABC_NORMAL_DEBUG>0 printf("B2 sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif saveSumD1=sumDualInfeasibilities_; } if (sumOfRelaxedDualInfeasibilities_) { makeNonFreeVariablesDualFeasible(); moveToBasic(); abcProgress_.reset(); gutsOfSolution(3); #if ABC_NORMAL_DEBUG>0 printf("C sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif if (sumPrimalInfeasibilities_>1.0e2*saveSum1+currentDualBound_*0.2 /*|| sumOfRelaxedDualInfeasibilities_<1.0e-4*sumPrimalInfeasibilities_*/) { numberDisasters_++; if (numberDisasters_>2) goToPrimal=true; } } else { numberDualInfeasibilities_=0; sumDualInfeasibilities_=0.0; } } else { // carry on makeNonFreeVariablesDualFeasible(); moveToBasic(); abcProgress_.reset(); gutsOfSolution(3); #if ABC_NORMAL_DEBUG>0 printf("C2 sumDual %g sumPrimal %g\n",sumDualInfeasibilities_,sumPrimalInfeasibilities_); #endif numberDisasters_++; if (sumPrimalInfeasibilities_>1.0e2*saveSum1+currentDualBound_*0.2 ||(saveSumD1<1.0e-4*sumPrimalInfeasibilities_&&saveSumD1<1.0)) { numberDisasters_++; if (numberDisasters_>2||saveSumD1<1.0e-10*sumPrimalInfeasibilities_) goToPrimal=true; } } if (goToPrimal) { // go to primal CoinAbcMemcpy(internalStatus_,status_,numberTotal_); CoinAbcMemcpy(abcSolution_,solutionSaved_,numberTotal_); int * COIN_RESTRICT abcPivotVariable = abcPivotVariable_; // redo pivotVariable int numberBasic=0; for (int i=0;i0 printf("D sumPrimal %g\n",sumPrimalInfeasibilities_); #endif return 1; } } CoinAbcGatherFrom(abcCost_,costBasic_,abcPivotVariable_,numberRows_); return 0; } #if ABC_NORMAL_DEBUG>0 extern int cilk_conflict; #endif int AbcSimplexDual::noPivotRow() { #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() & 32) printf("** no row pivot\n"); #endif int numberPivots = abcFactorization_->pivots(); bool specialCase; int useNumberFake; int returnCode = 0; if (numberPivots <= CoinMax(dontFactorizePivots_, 20) && (specialOptions_ & 2048) != 0 && currentDualBound_ >= 1.0e8) { specialCase = true; // as dual bound high - should be okay useNumberFake = 0; } else { specialCase = false; useNumberFake = numberAtFakeBound(); } if (!numberPivots || specialCase) { // may have crept through - so may be optimal // check any flagged variables if (numberFlagged_ && numberPivots) { // try factorization returnCode = -2; } if (useNumberFake || numberDualInfeasibilities_) { // may be dual infeasible if ((specialOptions_ & 1024) == 0) problemStatus_ = -5; else if (!useNumberFake && numberPrimalInfeasibilities_ && !numberPivots) problemStatus_ = 1; } else { if (numberFlagged_) { #if ABC_NORMAL_DEBUG>3 std::cout << "Flagged variables at end - infeasible?" << std::endl; printf("Probably infeasible - pivot was %g\n", alpha_); #endif #if ABC_NORMAL_DEBUG>3 abort(); #endif problemStatus_ = -5; } else { problemStatus_ = 0; #ifndef CLP_CHECK_NUMBER_PIVOTS #define CLP_CHECK_NUMBER_PIVOTS 10 #endif #if CLP_CHECK_NUMBER_PIVOTS < 20 if (numberPivots > CLP_CHECK_NUMBER_PIVOTS) { gutsOfSolution(2); rawObjectiveValue_ +=sumNonBasicCosts_; setClpSimplexObjectiveValue(); if (numberPrimalInfeasibilities_) { problemStatus_ = -1; returnCode = -2; } } #endif if (!problemStatus_) { // make it look OK numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; if (numberChanged_) { numberChanged_ = 0; // Number of variables with changed costs CoinAbcMemcpy(abcCost_,abcCost_+maximumNumberTotal_,numberTotal_); CoinAbcGatherFrom(abcCost_,costBasic_,abcPivotVariable_,numberRows_); // make sure duals are current gutsOfSolution(1); setClpSimplexObjectiveValue(); abcProgress_.modifyObjective(-COIN_DBL_MAX); if (numberDualInfeasibilities_) { problemStatus_ = 10; // was -3; numberTimesOptimal_++; } else { computeObjectiveValue(true); } } else if (numberPivots) { computeObjectiveValue(true); } sumPrimalInfeasibilities_ = 0.0; } if ((specialOptions_&(1024 + 16384)) != 0 && !problemStatus_&&abcFactorization_->pivots()) { CoinIndexedVector * arrayVector = &usefulArray_[arrayForFtran_]; double * rhs = arrayVector->denseVector(); arrayVector->clear(); CoinAbcScatterTo(solutionBasic_,abcSolution_,abcPivotVariable_,numberRows_); abcMatrix_->timesModifyExcludingSlacks(-1.0, abcSolution_,rhs); //#define CHECK_ACCURACY #ifdef CHECK_ACCURACY bool bad = false; #endif bool bad2 = false; int i; for ( i = 0; i < numberRows_; i++) { if (rhs[i] < abcLower_[i] - primalTolerance_ || rhs[i] > abcUpper_[i] + primalTolerance_) { bad2 = true; #ifdef CHECK_ACCURACY printf("row %d out of bounds %g, %g correct %g bad %g\n", i, abcLower_[i], abcUpper_[i], rhs[i], abcSolution_[i]); #endif } else if (fabs(rhs[i] - abcSolution_[i]) > 1.0e-3) { #ifdef CHECK_ACCURACY bad = true; printf("row %d correct %g bad %g\n", i, rhs[i], abcSolution_[i]); #endif } rhs[i] = 0.0; } for (int i = 0; i < numberTotal_; i++) { if (abcSolution_[i] < abcLower_[i] - primalTolerance_ || abcSolution_[i] > abcUpper_[i] + primalTolerance_) { bad2 = true; #ifdef CHECK_ACCURACY printf("column %d out of bounds %g, %g value %g\n", i, abcLower_[i], abcUpper_[i], abcSolution_[i]); #endif } } if (bad2) { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = abcFactorization_->pivots(); if (forceFactorization_<0) forceFactorization_=100000; forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } } } } } else { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = abcFactorization_->pivots(); if (forceFactorization_<0) forceFactorization_=100000; forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } return returnCode; } void AbcSimplexDual::dualPivotColumn() { double saveAcceptable=acceptablePivot_; if (largestPrimalError_>1.0e-5||largestDualError_>1.0e-5) { //if ((largestPrimalError_>1.0e-5||largestDualError_>1.0e-5)&&false) { if (!abcFactorization_->pivots()) acceptablePivot_*=1.0e2; else if (abcFactorization_->pivots()<5) acceptablePivot_*=1.0e1; } dualColumn2(); if (sequenceIn_<0&&acceptablePivot_>saveAcceptable) { acceptablePivot_=saveAcceptable; #if ABC_NORMAL_DEBUG>0 printf("No pivot!!!\n"); #endif // try again dualColumn1(true); dualColumn2(); } else { acceptablePivot_=saveAcceptable; } if ((stateOfProblem_&VALUES_PASS)!=0) { // check no flips assert (!usefulArray_[arrayForFlipBounds_].getNumElements()); // If no pivot - then try other way if plausible if (sequenceIn_<0) { // could use fake primal basic values if ((directionOut_<0&&lowerOut_>-1.0e30)|| (directionOut_>0&&upperOut_<1.30)) { directionOut_=-directionOut_; if (directionOut_<0&&abcDj_[sequenceOut_]<0.0) upperTheta_=-abcDj_[sequenceOut_]; else if (directionOut_>0&&abcDj_[sequenceOut_]>0.0) upperTheta_=abcDj_[sequenceOut_]; else upperTheta_=1.0e30; CoinPartitionedVector & tableauRow = usefulArray_[arrayForTableauRow_]; CoinPartitionedVector & candidateList = usefulArray_[arrayForDualColumn_]; assert (!candidateList.getNumElements()); tableauRow.compact(); candidateList.compact(); // redo candidate list int * COIN_RESTRICT index = tableauRow.getIndices(); double * COIN_RESTRICT array = tableauRow.denseVector(); double * COIN_RESTRICT arrayCandidate=candidateList.denseVector(); int * COIN_RESTRICT indexCandidate = candidateList.getIndices(); const double * COIN_RESTRICT abcDj = abcDj_; const unsigned char * COIN_RESTRICT internalStatus = internalStatus_; // do first pass to get possibles double bestPossible = 0.0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; // try with this much smaller as guess double acceptablePivot = currentAcceptablePivot_; double dualT=-currentDualTolerance_; // fixed will have been taken out by now const double multiplier[] = { 1.0, -1.0}; int freeSequence=-1; double freeAlpha=0.0; int numberNonZero=tableauRow.getNumElements(); int numberRemaining=0; if (ordinaryVariables()) { for (int i = 0; i < numberNonZero; i++) { int iSequence = index[i]; double tableauValue=array[i]; unsigned char iStatus=internalStatus[iSequence]&7; double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta_ * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta_ = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } } else { double badFree = 0.0; freeAlpha = currentAcceptablePivot_; double currentDualTolerance = currentDualTolerance_; for (int i = 0; i < numberNonZero; i++) { int iSequence = index[i]; double tableauValue=array[i]; unsigned char iStatus=internalStatus[iSequence]&7; if ((iStatus&4)==0) { double mult = multiplier[iStatus]; double alpha = tableauValue * mult; double oldValue = abcDj[iSequence] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta_ * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta_ = (oldValue - dualT) / alpha; } // add to list arrayCandidate[numberRemaining] = alpha; indexCandidate[numberRemaining++] = iSequence; } } else { bool keep; bestPossible = CoinMax(bestPossible, fabs(tableauValue)); double oldValue = abcDj[iSequence]; // If free has to be very large - should come in via dualRow //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3) //break; if (oldValue > currentDualTolerance) { keep = true; } else if (oldValue < -currentDualTolerance) { keep = true; } else { if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(tableauValue)); } } if (keep) { // free - choose largest if (fabs(tableauValue) > fabs(freeAlpha)) { freeAlpha = tableauValue; freeSequence = iSequence; } } } } } candidateList.setNumElements(numberRemaining); if (freeSequence>=0) { sequenceIn_=freeSequence; } else if (fabs(upperTheta_-fabs(abcDj_[sequenceOut_]))= 0&&upperTheta_==COIN_DBL_MAX) { lowerIn_ = abcLower_[sequenceIn_]; upperIn_ = abcUpper_[sequenceIn_]; valueIn_ = abcSolution_[sequenceIn_]; dualIn_ = abcDj_[sequenceIn_]; if (valueIn_upperIn_-primalTolerance_) { directionIn_ = -1; } else { if (alpha_ < 0.0) { // as if from upper bound directionIn_ = -1; //assert(upperIn_ == valueIn_); } else { // as if from lower bound directionIn_ = 1; //assert(lowerIn_ == valueIn_); } } } #if ABC_DEBUG checkArrays(4); #endif #if CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)!=0) theta_=0.0; #endif movement_=0.0; objectiveChange_=0.0; /* 0 - take iteration 1 - don't take but continue 2 - don't take and break */ btranAlpha_ = -alpha_ * directionOut_; // for check } void AbcSimplexDual::getTableauColumnPart2() { #if ABC_PARALLEL if (parallelMode_!=0) { abcFactorization_->updateColumnFTPart2(usefulArray_[arrayForFtran_]); // pivot element alpha_ = usefulArray_[arrayForFtran_].denseVector()[pivotRow_]; } #endif } void AbcSimplexDual::replaceColumnPart3() { abcFactorization_->replaceColumnPart3(this, &usefulArray_[arrayForReplaceColumn_], &usefulArray_[arrayForFtran_], lastPivotRow_, ftAlpha_?ftAlpha_:alpha_); } void AbcSimplexDual::checkReplacePart1() { //abcFactorization_->checkReplacePart1a(&usefulArray_[arrayForReplaceColumn_],pivotRow_); //usefulArray_[arrayForReplaceColumn_].print(); ftAlpha_=abcFactorization_->checkReplacePart1(&usefulArray_[arrayForReplaceColumn_],pivotRow_); } #if 0 void AbcSimplexDual::checkReplacePart1a() { abcFactorization_->checkReplacePart1a(&usefulArray_[arrayForReplaceColumn_],pivotRow_); } void AbcSimplexDual::checkReplacePart1b() { //usefulArray_[arrayForReplaceColumn_].print(); ftAlpha_=abcFactorization_->checkReplacePart1b(&usefulArray_[arrayForReplaceColumn_],pivotRow_); } #endif /* returns 0 - OK 1 - take iteration then re-factorize 2 - flag something and skip 3 - break and re-factorize 5 - take iteration then re-factorize because of memory */ int AbcSimplexDual::checkReplace() { int returnCode=0; if (!stateOfIteration_) { int saveStatus=problemStatus_; // check update #if MOVE_REPLACE_PART1A < 0 checkReplacePart1(); #endif int updateStatus=abcFactorization_->checkReplacePart2(pivotRow_,btranAlpha_,alpha_,ftAlpha_); #if ABC_DEBUG checkArrays(); #endif // If looks like bad pivot - refactorize if (fabs(dualOut_) > 1.0e50) updateStatus = 2; // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && !abcFactorization_->pivots() && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (abcFactorization_->pivots() > 5 || updateStatus == 4) { problemStatus_ = -2; // factorize now returnCode = -3; } } else if (updateStatus == 2) { // major error // later we may need to unwind more e.g. fake bounds if (abcFactorization_->pivots() && ((moreSpecialOptions_ & 16) == 0 || abcFactorization_->pivots() > 4)) { problemStatus_ = -2; // factorize now returnCode = -2; moreSpecialOptions_ |= 16; stateOfIteration_=2; } else { assert (sequenceOut_>=0); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>0 printf("BAD flag b %g pivotRow %d (seqout %d) sequenceIn %d\n", alpha_,pivotRow_, sequenceOut_,sequenceIn_); #endif setFlagged(sequenceOut_); // so can't happen immediately again sequenceOut_=-1; //abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious //clearArrays(-1); //if(primalSolutionUpdated) //gutsOfSolution(2); stateOfIteration_=1; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (abcFactorization_->pivots() < 0.5 * abcFactorization_->maximumPivots() && abcFactorization_->pivots() < 200) abcFactorization_->areaFactor( abcFactorization_->areaFactor() * 1.1); problemStatus_ = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } if (theta_ < 0.0) { #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() & 32) printf("negative theta %g\n", theta_); #endif theta_ = 0.0; } //printf("check pstatus %d ustatus %d returncode %d nels %d\n", // problemStatus_,updateStatus,returnCode,usefulArray_[arrayForReplaceColumn_].getNumElements()); if (saveStatus!=-1) problemStatus_=saveStatus; } return returnCode; } int AbcSimplexDual::noPivotColumn() { // no incoming column is valid int returnCode=0; if (abcFactorization_->pivots() < 5 && acceptablePivot_ > 1.0e-8) acceptablePivot_ = 1.0e-8; returnCode = 1; #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (abcFactorization_->pivots() <=dontFactorizePivots_ && acceptablePivot_ <= 1.0e-8 && lastFirstFree_<0) { // If not in branch and bound etc save ray delete [] ray_; if ((specialOptions_&(1024 | 4096)) == 0 || (specialOptions_ & 32) != 0) { // create ray anyway ray_ = new double [ numberRows_]; setUsedArray(0); usefulArray_[arrayForBtran_].createOneUnpackedElement(pivotRow_, -directionOut_); abcFactorization_->updateColumnTranspose(usefulArray_[arrayForBtran_]); CoinMemcpyN(usefulArray_[arrayForBtran_].denseVector(), numberRows_, ray_); clearArrays(0); } else { ray_ = NULL; } // If we have just factorized and infeasibility reasonable say infeas double dualTest = ((specialOptions_ & 4096) != 0) ? 1.0e8 : 1.0e13; if (largestGap_) dualTest=CoinMin(largestGap_,dualTest); // but ignore if none at fake bound if (currentDualBound_= dualTest) { double testValue = 1.0e-4; if (!abcFactorization_->pivots() && numberPrimalInfeasibilities_ == 1) testValue = 1.0e-6; if (valueOut_ > upperOut_ + testValue || valueOut_ < lowerOut_ - testValue || (specialOptions_ & 64) == 0) { // say infeasible problemStatus_ = 1; // unless primal feasible!!!! //#define TEST_CLP_NODE #ifndef TEST_CLP_NODE // Should be correct - but ... int numberFake = numberAtFakeBound(); double sumPrimal = (!numberFake) ? 2.0e5 : sumPrimalInfeasibilities_; if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-5 || (sumPrimal < 1.0e5 && (specialOptions_ & 1024) != 0 && abcFactorization_->pivots())) { if (sumPrimal > 50.0 && abcFactorization_->pivots() > 2) { problemStatus_ = -4; } else { problemStatus_ = 10; // Get rid of objective if ((specialOptions_ & 16384) == 0) objective_ = new ClpLinearObjective(NULL, numberColumns_); } } #else if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-6) { if ((specialOptions_ & 1024) != 0 && abcFactorization_->pivots()) { problemStatus_ = 10; // Get rid of objective if ((specialOptions_ & 16384) == 0) objective_ = new ClpLinearObjective(NULL, numberColumns_); } } #endif returnCode = 1; stateOfIteration_=2; } } if (abcFactorization_->pivots() != 0) { // If special option set - put off as long as possible if ((specialOptions_ & 64) == 0 || (moreSpecialOptions_ & 64) != 0) { if (numberTimesOptimal_<3&&abcFactorization_->pivots()>dontFactorizePivots_) problemStatus_ = -4; //say looks infeasible else problemStatus_ = 1; //say looks really infeasible } else { assert (sequenceOut_>=0); // flag char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #if ABC_NORMAL_DEBUG>3 printf("flag c\n"); #endif setFlagged(sequenceOut_); lastBadIteration_ = numberIterations_; // say be more cautious // so can't happen immediately again sequenceOut_=-1; if (!abcFactorization_->pivots()) { stateOfIteration_=1; } } } } pivotRow_ = -1; lastPivotRow_=-1; return returnCode; } #if 0 #include "CoinTime.hpp" // Timed wait in nanoseconds - if negative then seconds static int timedWait(AbcSimplexDual * dual,int time, int which) { pthread_mutex_lock(dual->mutexPointer(which)); struct timespec absTime; clock_gettime(CLOCK_REALTIME, &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; } int rc = 0; while (! dual->threadInfoPointer()->status && rc == 0) { printf("waiting for signal on %d\n",which); rc = pthread_cond_timedwait(dual->conditionPointer(which), dual->mutexPointer(which), &absTime); } if (rc == 0) rc=dual->threadInfoPointer()->status; printf("got signal %d on %d\n",rc,which); //pthread_mutex_unlock(dual->mutexPointer(which)); return rc; } #endif #if ABC_PARALLEL==1 void * abc_parallelManager(void * simplex) { AbcSimplexDual * dual = reinterpret_cast(simplex); int whichThread=dual->whichThread(); CoinAbcThreadInfo * threadInfo = dual->threadInfoPointer(whichThread); pthread_mutex_lock(dual->mutexPointer(2,whichThread)); pthread_barrier_wait(dual->barrierPointer()); #if 0 int status=-1; while (status!=100) status=timedWait(dual,1000,2); pthread_cond_signal(dual->conditionPointer(1)); pthread_mutex_unlock(dual->mutexPointer(1,whichThread)); #endif // so now mutex_ is locked int whichLocked=0; while (true) { pthread_mutex_t * mutexPointer = dual->mutexPointer(whichLocked,whichThread); // wait //printf("Child waiting for %d - status %d %d %d\n", // whichLocked,lockedX[0],lockedX[1],lockedX[2]); pthread_mutex_lock (mutexPointer); whichLocked++; if (whichLocked==3) whichLocked=0; int unLock=whichLocked+1; if (unLock==3) unLock=0; //printf("child pointer %x status %d\n",threadInfo,threadInfo->status); assert(threadInfo->status>=0); if (threadInfo->status==1000) pthread_exit(NULL); int type=threadInfo->status; int * which = threadInfo->stuff; int & returnCode=which[0]; CoinIndexedVector * array; double dummy; switch(type) { // dummy case 0: break; case 1: returnCode=computeDualsAndCheck(dual,which); break; case 2: array=dual->usefulArray(dual->arrayForBtran()); // assuming not big overlap dual->dualRowPivot()->updateWeightsOnly(*array); //array->checkClean(); break; case 3: //dual->replaceColumnPart3(); dual->updateDualsInDual(); break; case 4: which[2]=-1; dual->abcMatrix()->dualColumn1Part(which[1],which[2],threadInfo->result, *dual->usefulArray(dual->arrayForBtran()), *dual->usefulArray(dual->arrayForTableauRow()), *dual->usefulArray(dual->arrayForDualColumn())); break; case 5: which[2]=-1; threadInfo->result= dual->abcMatrix()->dualColumn1Row(which[1],COIN_DBL_MAX,which[2], *dual->usefulArray(dual->arrayForBtran()), *dual->usefulArray(dual->arrayForTableauRow()), *dual->usefulArray(dual->arrayForDualColumn())); break; case 6:// not used dual->getTableauColumnPart2(); break; case 7: dual->checkReplacePart1(); //dual->checkReplacePart1a(); //dual->checkReplacePart1b(); break; case 8: which[2] = dual->flipBounds(); break; case 9: dual->replaceColumnPart3(); break; case 100: // initialization break; } threadInfo->status=-1; pthread_mutex_unlock (dual->mutexPointer(unLock,whichThread)); } } void AbcSimplex::startParallelStuff(int type) { /* first time 0,1 owned by main 2 by child at end of cycle should be 1,2 by main 0 by child then 2,0 by main 1 by child */ int iStart=1; for (int i=0;i=3) locked-=3; pthread_mutex_lock(&mutex_[locked+i*3]); locked_[i]++; if (locked_[i]==3) locked_[i]=0; } iStop = iStop<<1; } return threadInfo_[0].stuff[0]; } #endif //#define PRINT_WEIGHTS_FREQUENCY #ifdef PRINT_WEIGHTS_FREQUENCY extern int xweights1; extern int xweights2; extern int xweights3; #endif //static int whichModel=0; int AbcSimplexDual::dual() { //handler_->setLogLevel(63); #if 0 whichModel++; printf("STARTing dual %d rows - model %d\n",numberRows_,whichModel); char modelName[20]; sprintf(modelName,"model%d.mps",whichModel); writeMps(modelName,2); sprintf(modelName,"model%d.bas",whichModel); writeBasis(modelName,true,2); #endif bestObjectiveValue_ = -COIN_DBL_MAX; algorithm_ = -1; moreSpecialOptions_ &= ~16; // clear check replaceColumn accuracy normalDualColumnIteration_=0; problemStatus_=-1; numberIterations_=baseIteration_; //baseIteration_=0; if (!lastDualBound_) { dualTolerance_ = dblParam_[ClpDualTolerance]; primalTolerance_ = dblParam_[ClpPrimalTolerance]; int tryType=moreSpecialOptions_/65536; if (tryType<5) { currentDualBound_=1.0e8; } else { currentDualBound_=1.0e4; tryType -=5; } currentDualBound_=CoinMin(currentDualBound_,dualBound_); #if ABC_NORMAL_DEBUG>0 printf("dual bound %g (initialize)\n",currentDualBound_); #endif switch(tryType) { default: currentDualTolerance_=dualTolerance_; stateDualColumn_=0; break; case 1: currentDualTolerance_=CoinMin(1.0e-1,dualTolerance_*10.0); stateDualColumn_=-1; break; case 2: currentDualTolerance_=CoinMin(1.0e-1,dualTolerance_*100.0); stateDualColumn_=-1; break; case 3: currentDualTolerance_=CoinMin(1.0e-1,dualTolerance_*10000.0); stateDualColumn_=-1; // was -2 but that doesn't seem to work break; case 4: currentDualTolerance_=CoinMin(1.0e-1,dualTolerance_*1000000.0); stateDualColumn_=-1; // was -2 but that doesn't seem to work break; } } else { // done before currentDualBound_=1.1*lastDualBound_; currentDualTolerance_=dualTolerance_; #if ABC_NORMAL_DEBUG>0 printf("new dual bound %g (resolve)\n",currentDualBound_); #endif } // save data saveData_ = saveData(); // initialize copyFromSaved(); // temp if (fabs(primalTolerance()-1.001e-6)<1.0e-12&&false) { printf("trying idiot idea - need scaled matrix\n"); primalTolerance_=1.0e-6; //for (int i=0;itransposeTimesAll(cost_,abcCost_); delete [] cost_; cost_=NULL; CoinAbcMemcpy(costSaved_,abcCost_,numberTotal_); CoinAbcMemcpy(abcDj_,abcCost_,numberTotal_); static_cast (this)->makeNonFreeVariablesDualFeasible(); const double multiplier[] = { 1.0, -1.0}; double dualT = - currentDualTolerance_; double * COIN_RESTRICT solution = abcSolution_; double * COIN_RESTRICT lower = abcLower_; double * COIN_RESTRICT upper = abcUpper_; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { int iStatus = internalStatus_[iSequence] & 7; if (iStatus<4) { double lowerValue=lower[iSequence]; double upperValue=upper[iSequence]; if (lowerValue>-1.0e10||upperValue<1.0e10) { double mult = multiplier[iStatus]; double dj = abcDj_[iSequence] * mult; if (dj < dualT) iStatus=1-iStatus; if (lowerValue<=-1.0e10) iStatus=1; else if (upperValue>=1.0e10) iStatus=0; if (iStatus==0) { setInternalStatus(iSequence, atLowerBound); solution[iSequence] = lower[iSequence]; } else { setInternalStatus(iSequence, atUpperBound); solution[iSequence] = upper[iSequence]; } } assert (fabs(solution[iSequence])<1.0e10); } } CoinAbcMemcpy(solutionSaved_,abcSolution_,numberTotal_); } numberFlagged_=0; #ifndef NDEBUG for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; assert (!flagged(iPivot)); } #endif #if ABC_PARALLEL==1 // redo to test on parallelMode_ if (parallelMode_!=0) { // For waking up thread memset(mutex_,0,sizeof(mutex_)); for (int iThread=0;iThread(this)); } pthread_barrier_wait(&barrier_); pthread_barrier_destroy(&barrier_); for (int iThread=0;iThreadsetParallelMode(parallelMode_); #endif static_cast(this)->bounceTolerances(-1); int saveDont = dontFactorizePivots_; if ((specialOptions_ & 2048) == 0) dontFactorizePivots_ = 0; else if(!dontFactorizePivots_) dontFactorizePivots_ = 20; if (alphaAccuracy_ != -1.0) alphaAccuracy_ = 1.0; startupSolve(); lastPivotRow_=-1; pivotRow_=-1; // Save so can see if doing after primal swappedAlgorithm_ = (problemStatus_==10) ? 10 : 0; if (problemStatus_) { #ifdef PRINT_WEIGHTS_FREQUENCY xweights1=0; xweights2=0; xweights3=0; #endif numberFreeNonBasic_=0; gutsOfDual(); #ifdef PRINT_WEIGHTS_FREQUENCY if (dynamic_cast(abcDualRowPivot_)) { printf("ZZZZ %d iterations weights updated %d times\n",numberIterations_,xweights1+xweights2+xweights3); assert(numberIterations_==xweights1+xweights2+xweights3); } #endif } if (!problemStatus_) { // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if(fabs(limit) < 1.0e30 && minimizationObjectiveValue() > limit + 1.0e-7 + 1.0e-8 * fabs(limit)) { // actually infeasible on objective problemStatus_ = 1; secondaryStatus_ = 1; } } // If infeasible but primal errors - try dual if (problemStatus_==1 && numberPrimalInfeasibilities_) { bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; double factor = (!inCbcOrOther) ? 1.0 : 0.3; double averageInfeasibility = sumPrimalInfeasibilities_/ static_cast(numberPrimalInfeasibilities_); if (averageInfeasibility #include #include "ClpModel.hpp" #include "ClpMatrixBase.hpp" #include "ClpSolve.hpp" #include "CoinDenseVector.hpp" class ClpLsqr; class ClpPdcoBase; /// ******** DATA to be moved into protected section of ClpInterior typedef struct { double atolmin; double r3norm; double LSdamp; double* deltay; } Info; /// ******** DATA to be moved into protected section of ClpInterior typedef struct { double atolold; double atolnew; double r3ratio; int istop; int itncg; } Outfo; /// ******** DATA to be moved into protected section of ClpInterior typedef struct { double gamma; double delta; int MaxIter; double FeaTol; double OptTol; double StepTol; double x0min; double z0min; double mu0; int LSmethod; // 1=Cholesky 2=QR 3=LSQR int LSproblem; // See below int LSQRMaxIter; double LSQRatol1; // Initial atol double LSQRatol2; // Smallest atol (unless atol1 is smaller) double LSQRconlim; int wait; } Options; class Lsqr; class ClpCholeskyBase; // ***** END /** This solves LPs using interior point methods It inherits from ClpModel and all its arrays are created at algorithm time. */ class ClpInterior : public ClpModel { friend void ClpInteriorUnitTest(const std::string & mpsDir, const std::string & netlibDir); public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpInterior ( ); /// Copy constructor. ClpInterior(const ClpInterior &); /// Copy constructor from model. ClpInterior(const ClpModel &); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped */ ClpInterior (const ClpModel * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true); /// Assignment operator. This copies the data ClpInterior & operator=(const ClpInterior & rhs); /// Destructor ~ClpInterior ( ); // Ones below are just ClpModel with some changes /** Loads a problem (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
*/ void loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); void loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /** Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ 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, const double * rowObjective = NULL); /// This one is for after presolve to save memory void loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int * length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /// Read an mps file from the given filename int readMps(const char *filename, bool keepNames = false, bool ignoreErrors = false); /** Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm. This is same as ClpModel one. */ void borrowModel(ClpModel & otherModel); /** Return model - updates any scalars */ void returnModel(ClpModel & otherModel); //@} /**@name Functions most useful to user */ //@{ /** Pdco algorithm - see ClpPdco.hpp for method */ int pdco(); // ** Temporary version int pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo); /// Primal-Dual Predictor-Corrector barrier int primalDual(); //@} /**@name most useful gets and sets */ //@{ /// If problem is primal feasible inline bool primalFeasible() const { return (sumPrimalInfeasibilities_ <= 1.0e-5); } /// If problem is dual feasible inline bool dualFeasible() const { return (sumDualInfeasibilities_ <= 1.0e-5); } /// Current (or last) algorithm inline int algorithm() const { return algorithm_; } /// Set algorithm inline void setAlgorithm(int value) { algorithm_ = value; } /// Sum of dual infeasibilities inline CoinWorkDouble sumDualInfeasibilities() const { return sumDualInfeasibilities_; } /// Sum of primal infeasibilities inline CoinWorkDouble sumPrimalInfeasibilities() const { return sumPrimalInfeasibilities_; } /// dualObjective. inline CoinWorkDouble dualObjective() const { return dualObjective_; } /// primalObjective. inline CoinWorkDouble primalObjective() const { return primalObjective_; } /// diagonalNorm inline CoinWorkDouble diagonalNorm() const { return diagonalNorm_; } /// linearPerturbation inline CoinWorkDouble linearPerturbation() const { return linearPerturbation_; } inline void setLinearPerturbation(CoinWorkDouble value) { linearPerturbation_ = value; } /// projectionTolerance inline CoinWorkDouble projectionTolerance() const { return projectionTolerance_; } inline void setProjectionTolerance(CoinWorkDouble value) { projectionTolerance_ = value; } /// diagonalPerturbation inline CoinWorkDouble diagonalPerturbation() const { return diagonalPerturbation_; } inline void setDiagonalPerturbation(CoinWorkDouble value) { diagonalPerturbation_ = value; } /// gamma inline CoinWorkDouble gamma() const { return gamma_; } inline void setGamma(CoinWorkDouble value) { gamma_ = value; } /// delta inline CoinWorkDouble delta() const { return delta_; } inline void setDelta(CoinWorkDouble value) { delta_ = value; } /// ComplementarityGap inline CoinWorkDouble complementarityGap() const { return complementarityGap_; } //@} /**@name most useful gets and sets */ //@{ /// Largest error on Ax-b inline CoinWorkDouble largestPrimalError() const { return largestPrimalError_; } /// Largest error on basic duals inline CoinWorkDouble largestDualError() const { return largestDualError_; } /// Maximum iterations inline int maximumBarrierIterations() const { return maximumBarrierIterations_; } inline void setMaximumBarrierIterations(int value) { maximumBarrierIterations_ = value; } /// Set cholesky (and delete present one) void setCholesky(ClpCholeskyBase * cholesky); /// Return number fixed to see if worth presolving int numberFixed() const; /** fix variables interior says should be. If reallyFix false then just set values to exact bounds */ void fixFixed(bool reallyFix = true); /// Primal erturbation vector inline CoinWorkDouble * primalR() const { return primalR_; } /// Dual erturbation vector inline CoinWorkDouble * dualR() const { return dualR_; } //@} protected: /**@name protected methods */ //@{ /// Does most of deletion void gutsOfDelete(); /// Does most of copying void gutsOfCopy(const ClpInterior & rhs); /// Returns true if data looks okay, false if not bool createWorkingData(); void deleteWorkingData(); /// Sanity check on input rim data bool sanityCheck(); /// This does housekeeping int housekeeping(); //@} public: /**@name public methods */ //@{ /// Raw objective value (so always minimize) inline CoinWorkDouble rawObjectiveValue() const { return objectiveValue_; } /// Returns 1 if sequence indicates column inline int isColumn(int sequence) const { return sequence < numberColumns_ ? 1 : 0; } /// Returns sequence number within section inline int sequenceWithin(int sequence) const { return sequence < numberColumns_ ? sequence : sequence - numberColumns_; } /// Checks solution void checkSolution(); /** Modifies djs to allow for quadratic. returns quadratic offset */ CoinWorkDouble quadraticDjs(CoinWorkDouble * djRegion, const CoinWorkDouble * solution, CoinWorkDouble scaleFactor); /// To say a variable is fixed inline void setFixed( int sequence) { status_[sequence] = static_cast(status_[sequence] | 1) ; } inline void clearFixed( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~1) ; } inline bool fixed(int sequence) const { return ((status_[sequence] & 1) != 0); } /// To flag a variable inline void setFlagged( int sequence) { status_[sequence] = static_cast(status_[sequence] | 2) ; } inline void clearFlagged( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~2) ; } inline bool flagged(int sequence) const { return ((status_[sequence] & 2) != 0); } /// To say a variable is fixed OR free inline void setFixedOrFree( int sequence) { status_[sequence] = static_cast(status_[sequence] | 4) ; } inline void clearFixedOrFree( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~4) ; } inline bool fixedOrFree(int sequence) const { return ((status_[sequence] & 4) != 0); } /// To say a variable has lower bound inline void setLowerBound( int sequence) { status_[sequence] = static_cast(status_[sequence] | 8) ; } inline void clearLowerBound( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~8) ; } inline bool lowerBound(int sequence) const { return ((status_[sequence] & 8) != 0); } /// To say a variable has upper bound inline void setUpperBound( int sequence) { status_[sequence] = static_cast(status_[sequence] | 16) ; } inline void clearUpperBound( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~16) ; } inline bool upperBound(int sequence) const { return ((status_[sequence] & 16) != 0); } /// To say a variable has fake lower bound inline void setFakeLower( int sequence) { status_[sequence] = static_cast(status_[sequence] | 32) ; } inline void clearFakeLower( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~32) ; } inline bool fakeLower(int sequence) const { return ((status_[sequence] & 32) != 0); } /// To say a variable has fake upper bound inline void setFakeUpper( int sequence) { status_[sequence] = static_cast(status_[sequence] | 64) ; } inline void clearFakeUpper( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~64) ; } inline bool fakeUpper(int sequence) const { return ((status_[sequence] & 64) != 0); } //@} ////////////////// data ////////////////// protected: /**@name data. Many arrays have a row part and a column part. There is a single array with both - columns then rows and then normally two arrays pointing to rows and columns. The single array is the owner of memory */ //@{ /// Largest error on Ax-b CoinWorkDouble largestPrimalError_; /// Largest error on basic duals CoinWorkDouble largestDualError_; /// Sum of dual infeasibilities CoinWorkDouble sumDualInfeasibilities_; /// Sum of primal infeasibilities CoinWorkDouble sumPrimalInfeasibilities_; /// Worst complementarity CoinWorkDouble worstComplementarity_; /// public: CoinWorkDouble xsize_; CoinWorkDouble zsize_; protected: /// Working copy of lower bounds (Owner of arrays below) CoinWorkDouble * lower_; /// Row lower bounds - working copy CoinWorkDouble * rowLowerWork_; /// Column lower bounds - working copy CoinWorkDouble * columnLowerWork_; /// Working copy of upper bounds (Owner of arrays below) CoinWorkDouble * upper_; /// Row upper bounds - working copy CoinWorkDouble * rowUpperWork_; /// Column upper bounds - working copy CoinWorkDouble * columnUpperWork_; /// Working copy of objective CoinWorkDouble * cost_; public: /// Rhs CoinWorkDouble * rhs_; CoinWorkDouble * x_; CoinWorkDouble * y_; CoinWorkDouble * dj_; protected: /// Pointer to Lsqr object ClpLsqr * lsqrObject_; /// Pointer to stuff ClpPdcoBase * pdcoStuff_; /// Below here is standard barrier stuff /// mu. CoinWorkDouble mu_; /// objectiveNorm. CoinWorkDouble objectiveNorm_; /// rhsNorm. CoinWorkDouble rhsNorm_; /// solutionNorm. CoinWorkDouble solutionNorm_; /// dualObjective. CoinWorkDouble dualObjective_; /// primalObjective. CoinWorkDouble primalObjective_; /// diagonalNorm. CoinWorkDouble diagonalNorm_; /// stepLength CoinWorkDouble stepLength_; /// linearPerturbation CoinWorkDouble linearPerturbation_; /// diagonalPerturbation CoinWorkDouble diagonalPerturbation_; // gamma from Saunders and Tomlin regularized CoinWorkDouble gamma_; // delta from Saunders and Tomlin regularized CoinWorkDouble delta_; /// targetGap CoinWorkDouble targetGap_; /// projectionTolerance CoinWorkDouble projectionTolerance_; /// maximumRHSError. maximum Ax CoinWorkDouble maximumRHSError_; /// maximumBoundInfeasibility. CoinWorkDouble maximumBoundInfeasibility_; /// maximumDualError. CoinWorkDouble maximumDualError_; /// diagonalScaleFactor. CoinWorkDouble diagonalScaleFactor_; /// scaleFactor. For scaling objective CoinWorkDouble scaleFactor_; /// actualPrimalStep CoinWorkDouble actualPrimalStep_; /// actualDualStep CoinWorkDouble actualDualStep_; /// smallestInfeasibility CoinWorkDouble smallestInfeasibility_; /// historyInfeasibility. #define LENGTH_HISTORY 5 CoinWorkDouble historyInfeasibility_[LENGTH_HISTORY]; /// complementarityGap. CoinWorkDouble complementarityGap_; /// baseObjectiveNorm CoinWorkDouble baseObjectiveNorm_; /// worstDirectionAccuracy CoinWorkDouble worstDirectionAccuracy_; /// maximumRHSChange CoinWorkDouble maximumRHSChange_; /// errorRegion. i.e. Ax CoinWorkDouble * errorRegion_; /// rhsFixRegion. CoinWorkDouble * rhsFixRegion_; /// upperSlack CoinWorkDouble * upperSlack_; /// lowerSlack CoinWorkDouble * lowerSlack_; /// diagonal CoinWorkDouble * diagonal_; /// solution CoinWorkDouble * solution_; /// work array CoinWorkDouble * workArray_; /// delta X CoinWorkDouble * deltaX_; /// delta Y CoinWorkDouble * deltaY_; /// deltaZ. CoinWorkDouble * deltaZ_; /// deltaW. CoinWorkDouble * deltaW_; /// deltaS. CoinWorkDouble * deltaSU_; CoinWorkDouble * deltaSL_; /// Primal regularization array CoinWorkDouble * primalR_; /// Dual regularization array CoinWorkDouble * dualR_; /// rhs B CoinWorkDouble * rhsB_; /// rhsU. CoinWorkDouble * rhsU_; /// rhsL. CoinWorkDouble * rhsL_; /// rhsZ. CoinWorkDouble * rhsZ_; /// rhsW. CoinWorkDouble * rhsW_; /// rhs C CoinWorkDouble * rhsC_; /// zVec CoinWorkDouble * zVec_; /// wVec CoinWorkDouble * wVec_; /// cholesky. ClpCholeskyBase * cholesky_; /// numberComplementarityPairs i.e. ones with lower and/or upper bounds (not fixed) int numberComplementarityPairs_; /// numberComplementarityItems_ i.e. number of active bounds int numberComplementarityItems_; /// Maximum iterations int maximumBarrierIterations_; /// gonePrimalFeasible. bool gonePrimalFeasible_; /// goneDualFeasible. bool goneDualFeasible_; /// Which algorithm being used int algorithm_; //@} }; //############################################################################# /** A function that tests the methods in the ClpInterior class. The only reason for it not to be a member method is that this way it doesn't have to be compiled into the library. And that's a gain, because the library should be compiled with optimization on, but this method should be compiled with debugging. It also does some testing of ClpFactorization class */ void ClpInteriorUnitTest(const std::string & mpsDir, const std::string & netlibDir); #endif Clp-1.15.10/src/ClpSolve.cpp0000644000076600007660000067113612252354371014117 0ustar coincoin/* $Id: ClpSolve.cpp 2006 2013-12-12 15:40:41Z forrest $ */ // 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). // This file has higher level solve functions #include "CoinPragma.hpp" #include "ClpConfig.h" // check already here if COIN_HAS_GLPK is defined, since we do not want to get confused by a COIN_HAS_GLPK in config_coinutils.h #if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK) #define UFL_BARRIER #endif #include #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "CoinSort.hpp" #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #include "ClpSimplexDual.hpp" #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" #include "ClpInterior.hpp" #include "ClpCholeskyDense.hpp" #include "ClpCholeskyBase.hpp" #include "ClpPlusMinusOneMatrix.hpp" #include "ClpNetworkMatrix.hpp" #endif #include "ClpEventHandler.hpp" #include "ClpLinearObjective.hpp" #include "ClpSolve.hpp" #include "ClpPackedMatrix.hpp" #include "ClpMessage.hpp" #include "CoinTime.hpp" #if CLP_HAS_ABC #include "CoinAbcCommon.hpp" #endif #ifdef ABC_INHERIT #include "AbcSimplex.hpp" #include "AbcSimplexFactorization.hpp" #endif double zz_slack_value=0.0; #include "ClpPresolve.hpp" #ifndef SLIM_CLP #include "Idiot.hpp" #ifdef COIN_HAS_WSMP #include "ClpCholeskyWssmp.hpp" #include "ClpCholeskyWssmpKKT.hpp" #endif #include "ClpCholeskyUfl.hpp" #ifdef TAUCS_BARRIER #include "ClpCholeskyTaucs.hpp" #endif #include "ClpCholeskyMumps.hpp" #ifdef COIN_HAS_VOL #include "VolVolume.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedMatrix.hpp" #include "CoinMpsIO.hpp" //############################################################################# class lpHook : public VOL_user_hooks { private: lpHook(const lpHook&); lpHook& operator=(const lpHook&); private: /// Pointer to dense vector of structural variable upper bounds double *colupper_; /// Pointer to dense vector of structural variable lower bounds double *collower_; /// Pointer to dense vector of objective coefficients double *objcoeffs_; /// Pointer to dense vector of right hand sides double *rhs_; /// Pointer to dense vector of senses char *sense_; /// The problem matrix in a row ordered form CoinPackedMatrix rowMatrix_; /// The problem matrix in a column ordered form CoinPackedMatrix colMatrix_; public: lpHook(double* clb, double* cub, double* obj, double* rhs, char* sense, const CoinPackedMatrix& mat); virtual ~lpHook(); public: // for all hooks: return value of -1 means that volume should quit /** compute reduced costs @param u (IN) the dual variables @param rc (OUT) the reduced cost with respect to the dual values */ virtual int compute_rc(const VOL_dvector& u, VOL_dvector& rc); /** Solve the subproblem for the subgradient step. @param dual (IN) the dual variables @param rc (IN) the reduced cost with respect to the dual values @param lcost (OUT) the lagrangean cost with respect to the dual values @param x (OUT) the primal result of solving the subproblem @param v (OUT) b-Ax for the relaxed constraints @param pcost (OUT) the primal objective value of x */ virtual int solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc, double& lcost, VOL_dvector& x, VOL_dvector& v, double& pcost); /** Starting from the primal vector x, run a heuristic to produce an integer solution @param x (IN) the primal vector @param heur_val (OUT) the value of the integer solution (return DBL_MAX here if no feas sol was found */ virtual int heuristics(const VOL_problem& p, const VOL_dvector& x, double& heur_val) { return 0; } }; //############################################################################# lpHook::lpHook(double* clb, double* cub, double* obj, double* rhs, char* sense, const CoinPackedMatrix& mat) { colupper_ = cub; collower_ = clb; objcoeffs_ = obj; rhs_ = rhs; sense_ = sense; assert (mat.isColOrdered()); colMatrix_.copyOf(mat); rowMatrix_.reverseOrderedCopyOf(mat); } //----------------------------------------------------------------------------- lpHook::~lpHook() { } //############################################################################# int lpHook::compute_rc(const VOL_dvector& u, VOL_dvector& rc) { rowMatrix_.transposeTimes(u.v, rc.v); const int psize = rowMatrix_.getNumCols(); for (int i = 0; i < psize; ++i) rc[i] = objcoeffs_[i] - rc[i]; return 0; } //----------------------------------------------------------------------------- int lpHook::solve_subproblem(const VOL_dvector& dual, const VOL_dvector& rc, double& lcost, VOL_dvector& x, VOL_dvector& v, double& pcost) { int i; const int psize = x.size(); const int dsize = v.size(); // compute the lagrangean solution corresponding to the reduced costs for (i = 0; i < psize; ++i) x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i]; // compute the lagrangean value (rhs*dual + primal*rc) lcost = 0; for (i = 0; i < dsize; ++i) lcost += rhs_[i] * dual[i]; for (i = 0; i < psize; ++i) lcost += x[i] * rc[i]; // compute the rhs - lhs colMatrix_.times(x.v, v.v); for (i = 0; i < dsize; ++i) v[i] = rhs_[i] - v[i]; // compute the lagrangean primal objective pcost = 0; for (i = 0; i < psize; ++i) pcost += x[i] * objcoeffs_[i]; return 0; } //############################################################################# /** A quick inlined function to convert from lb/ub style constraint definition to sense/rhs/range style */ inline void convertBoundToSense(const double lower, const double upper, char& sense, double& right, double& range) { range = 0.0; if (lower > -1.0e20) { if (upper < 1.0e20) { right = upper; if (upper == lower) { sense = 'E'; } else { sense = 'R'; range = upper - lower; } } else { sense = 'G'; right = lower; } } else { if (upper < 1.0e20) { sense = 'L'; right = upper; } else { sense = 'N'; right = 0.0; } } } static int solveWithVolume(ClpSimplex * model, int numberPasses, int doIdiot) { VOL_problem volprob; volprob.parm.gap_rel_precision = 0.00001; volprob.parm.maxsgriters = 3000; if(numberPasses > 3000) { volprob.parm.maxsgriters = numberPasses; volprob.parm.primal_abs_precision = 0.0; volprob.parm.minimum_rel_ascent = 0.00001; } else if (doIdiot > 0) { volprob.parm.maxsgriters = doIdiot; } if (model->logLevel() < 2) volprob.parm.printflag = 0; else volprob.parm.printflag = 3; const CoinPackedMatrix* mat = model->matrix(); int psize = model->numberColumns(); int dsize = model->numberRows(); char * sense = new char[dsize]; double * rhs = new double [dsize]; // Set the lb/ub on the duals volprob.dsize = dsize; volprob.psize = psize; volprob.dual_lb.allocate(dsize); volprob.dual_ub.allocate(dsize); int i; const double * rowLower = model->rowLower(); const double * rowUpper = model->rowUpper(); for (i = 0; i < dsize; ++i) { double range; convertBoundToSense(rowLower[i], rowUpper[i], sense[i], rhs[i], range); switch (sense[i]) { case 'E': volprob.dual_lb[i] = -1.0e31; volprob.dual_ub[i] = 1.0e31; break; case 'L': volprob.dual_lb[i] = -1.0e31; volprob.dual_ub[i] = 0.0; break; case 'G': volprob.dual_lb[i] = 0.0; volprob.dual_ub[i] = 1.0e31; break; default: printf("Volume Algorithm can't work if there is a non ELG row\n"); return 1; } } // Check bounds double * saveLower = model->columnLower(); double * saveUpper = model->columnUpper(); bool good = true; for (i = 0; i < psize; i++) { if (saveLower[i] < -1.0e20 || saveUpper[i] > 1.0e20) { good = false; break; } } if (!good) { saveLower = CoinCopyOfArray(model->columnLower(), psize); saveUpper = CoinCopyOfArray(model->columnUpper(), psize); for (i = 0; i < psize; i++) { if (saveLower[i] < -1.0e20) saveLower[i] = -1.0e20; if(saveUpper[i] > 1.0e20) saveUpper[i] = 1.0e20; } } lpHook myHook(saveLower, saveUpper, model->objective(), rhs, sense, *mat); volprob.solve(myHook, false /* no warmstart */); if (saveLower != model->columnLower()) { delete [] saveLower; delete [] saveUpper; } //------------- extract the solution --------------------------- //printf("Best lagrangean value: %f\n", volprob.value); double avg = 0; for (i = 0; i < dsize; ++i) { switch (sense[i]) { case 'E': avg += CoinAbs(volprob.viol[i]); break; case 'L': if (volprob.viol[i] < 0) avg += (-volprob.viol[i]); break; case 'G': if (volprob.viol[i] > 0) avg += volprob.viol[i]; break; } } //printf("Average primal constraint violation: %f\n", avg/dsize); // volprob.dsol contains the dual solution (dual feasible) // volprob.psol contains the primal solution // (NOT necessarily primal feasible) CoinMemcpyN(volprob.dsol.v, dsize, model->dualRowSolution()); CoinMemcpyN(volprob.psol.v, psize, model->primalColumnSolution()); return 0; } #endif static ClpInterior * currentModel2 = NULL; #endif //############################################################################# // Allow for interrupts // But is this threadsafe ? (so switched off by option) #include "CoinSignal.hpp" static ClpSimplex * currentModel = NULL; #ifdef ABC_INHERIT static AbcSimplex * currentAbcModel = NULL; #endif extern "C" { static void #if defined(_MSC_VER) __cdecl #endif // _MSC_VER signal_handler(int /*whichSignal*/) { if (currentModel != NULL) currentModel->setMaximumIterations(0); // stop at next iterations #ifdef ABC_INHERIT if (currentAbcModel != NULL) currentAbcModel->setMaximumIterations(0); // stop at next iterations #endif #ifndef SLIM_CLP if (currentModel2 != NULL) currentModel2->setMaximumBarrierIterations(0); // stop at next iterations #endif return; } } #if ABC_INSTRUMENT>1 int abcPricing[20]; int abcPricingDense[20]; static int trueNumberRows; static int numberTypes; #define MAX_TYPES 25 #define MAX_COUNT 20 #define MAX_FRACTION 101 static char * types[MAX_TYPES]; static double counts[MAX_TYPES][MAX_COUNT]; static double countsFraction[MAX_TYPES][MAX_FRACTION]; static double * currentCounts; static double * currentCountsFraction; static int currentType; static double workMultiplier[MAX_TYPES]; static double work[MAX_TYPES]; static double currentWork; static double otherWork[MAX_TYPES]; static int timesCalled[MAX_TYPES]; static int timesStarted[MAX_TYPES]; static int fractionDivider; void instrument_initialize(int numberRows) { trueNumberRows=numberRows; numberTypes=0; memset(counts,0,sizeof(counts)); currentCounts=NULL; memset(countsFraction,0,sizeof(countsFraction)); currentCountsFraction=NULL; memset(workMultiplier,0,sizeof(workMultiplier)); memset(work,0,sizeof(work)); memset(otherWork,0,sizeof(otherWork)); memset(timesCalled,0,sizeof(timesCalled)); memset(timesStarted,0,sizeof(timesStarted)); currentType=-1; fractionDivider=(numberRows+MAX_FRACTION-2)/(MAX_FRACTION-1); } void instrument_start(const char * type,int numberRowsEtc) { if (currentType>=0) instrument_end(); currentType=-1; currentWork=0.0; for (int i=0;i(numberRowsEtc)/static_cast(trueNumberRows); } void instrument_add(int count) { assert (currentType>=0); currentWork+=count; timesCalled[currentType]++; if (count=0&&count/fractionDivider=%d els,%.0f times) ",MAX_COUNT-1,currentCounts[MAX_COUNT-1]); } printf("\n"); int largestFraction; int nBig=0; for (largestFraction=MAX_FRACTION-1;largestFraction>=10;largestFraction--) { double count = currentCountsFraction[largestFraction]; if (count&&largestFraction>10) nBig++; if (nBig>4) break; } int chunk=(largestFraction+5)/10; int lo=0; for (int iChunk=0;iChunk #endif #endif #ifdef ABC_INHERIT void ClpSimplex::dealWithAbc(int solveType, int startUp, bool interrupt) { if (!this->abcState()||!numberRows_||!numberColumns_) { if (!solveType) this->dual(0); else this->primal(startUp ? 1 : 0); } else { AbcSimplex * abcModel2=new AbcSimplex(*this); if (interrupt) currentAbcModel = abcModel2; //if (abcSimplex_) { // move factorization stuff abcModel2->factorization()->synchronize(this->factorization(),abcModel2); //} //abcModel2->startPermanentArrays(); int crashState=abcModel2->abcState()&(256+512+1024); abcModel2->setAbcState(CLP_ABC_WANTED|crashState); int ifValuesPass=startUp ? 1 : 0; // temp if (fabs(this->primalTolerance()-1.001e-6)<0.999e-9) { int type=1; double diff=this->primalTolerance()-1.001e-6; printf("Diff %g\n",diff); if (fabs(diff-1.0e-10)<1.0e-13) type=2; else if (fabs(diff-1.0e-11)<1.0e-13) type=3; #if 0 ClpSimplex * thisModel = static_cast (this)->dualOfModel(1.0,1.0); if (thisModel) { printf("Dual of model has %d rows and %d columns\n", thisModel->numberRows(), thisModel->numberColumns()); thisModel->setOptimizationDirection(1.0); Idiot info(*thisModel); info.setStrategy(512 | info.getStrategy()); // Allow for scaling info.setStrategy(32 | info.getStrategy()); info.setStartingWeight(1.0e3); info.setReduceIterations(6); info.crash(50, this->messageHandler(), this->messagesPointer(),false); // make sure later that primal solution in correct place // and has correct sign abcModel2->setupDualValuesPass(thisModel->primalColumnSolution(), thisModel->dualRowSolution(),type); //thisModel->dual(); delete thisModel; } #else if (!solveType) { this->dual(0); abcModel2->setupDualValuesPass(this->dualRowSolution(), this->primalColumnSolution(),type); } else { ifValuesPass=1; abcModel2->setStateOfProblem(abcModel2->stateOfProblem() | VALUES_PASS); Idiot info(*abcModel2); info.setStrategy(512 | info.getStrategy()); // Allow for scaling info.setStrategy(32 | info.getStrategy()); info.setStartingWeight(1.0e3); info.setReduceIterations(6); info.crash(200, abcModel2->messageHandler(), abcModel2->messagesPointer(),false); //memcpy(abcModel2->primalColumnSolution(),this->primalColumnSolution(), // this->numberColumns()*sizeof(double)); } #endif } char line[200]; #if ABC_PARALLEL #if ABC_PARALLEL==2 #ifndef FAKE_CILK if (!number_cilk_workers) { number_cilk_workers=__cilkrts_get_nworkers(); sprintf(line,"%d cilk workers",number_cilk_workers); handler_->message(CLP_GENERAL, messages_) << line << CoinMessageEol; } #endif #endif int numberCpu=this->abcState()&15; if (numberCpu==9) { numberCpu=1; #if ABC_PARALLEL==2 #ifndef FAKE_CILK if (number_cilk_workers>1) numberCpu=CoinMin(2*number_cilk_workers,8); #endif #endif } else if (numberCpu==10) { // maximum numberCpu=4; } else if (numberCpu==10) { // decide if (abcModel2->getNumElements()<5000) numberCpu=1; #if ABC_PARALLEL==2 #ifndef FAKE_CILK else if (number_cilk_workers>1) numberCpu=CoinMin(2*number_cilk_workers,8); #endif #endif else numberCpu=1; } else { #if ABC_PARALLEL==2 #if 0 //ndef FAKE_CILK char temp[3]; sprintf(temp,"%d",numberCpu); __cilkrts_set_param("nworkers",temp); #endif #endif } abcModel2->setParallelMode(numberCpu-1); #endif //if (abcState()==3||abcState()==4) { //abcModel2->setMoreSpecialOptions((65536*2)|abcModel2->moreSpecialOptions()); //} //if (processTune>0&&processTune<8) //abcModel2->setMoreSpecialOptions(abcModel2->moreSpecialOptions()|65536*processTune); #if ABC_INSTRUMENT double startTimeCpu=CoinCpuTime(); double startTimeElapsed=CoinGetTimeOfDay(); #if ABC_INSTRUMENT>1 memset(abcPricing,0,sizeof(abcPricing)); memset(abcPricingDense,0,sizeof(abcPricing)); instrument_initialize(abcModel2->numberRows()); #endif #endif if (!solveType) { abcModel2->ClpSimplex::doAbcDual(); } else { int saveOptions=abcModel2->specialOptions(); if (startUp==2) abcModel2->setSpecialOptions(8192|saveOptions); abcModel2->ClpSimplex::doAbcPrimal(ifValuesPass); abcModel2->setSpecialOptions(saveOptions); } #if ABC_INSTRUMENT double timeCpu=CoinCpuTime()-startTimeCpu; double timeElapsed=CoinGetTimeOfDay()-startTimeElapsed; sprintf(line,"Cpu time for %s (%d rows, %d columns %d elements) %g elapsed %g ratio %g - %d iterations", this->problemName().c_str(),this->numberRows(),this->numberColumns(), this->getNumElements(), timeCpu,timeElapsed,timeElapsed ? timeCpu/timeElapsed : 1.0,abcModel2->numberIterations()); handler_->message(CLP_GENERAL, messages_) << line << CoinMessageEol; #if ABC_INSTRUMENT>1 { int n; n=0; for (int i=0;i<20;i++) n+= abcPricing[i]; printf("CCSparse pricing done %d times",n); int n2=0; for (int i=0;i<20;i++) n2+= abcPricingDense[i]; if (n2) printf(" and dense pricing done %d times\n",n2); else printf("\n"); n=0; printf ("CCS"); for (int i=0;i<19;i++) { if (abcPricing[i]) { if (n==5) { n=0; printf("\nCCS"); } n++; printf("(%d els,%d times) ",i,abcPricing[i]); } } if (abcPricing[19]) { if (n==5) { n=0; printf("\nCCS"); } n++; printf("(>=19 els,%d times) ",abcPricing[19]); } if (n2) { printf ("CCD"); for (int i=0;i<19;i++) { if (abcPricingDense[i]) { if (n==5) { n=0; printf("\nCCD"); } n++; int k1=(numberRows_/16)*i;; int k2=CoinMin(numberRows_,k1+(numberRows_/16)-1); printf("(%d-%d els,%d times) ",k1,k2,abcPricingDense[i]); } } } printf("\n"); } instrument_print(); #endif #endif abcModel2->moveStatusToClp(this); //ClpModel::stopPermanentArrays(); this->setSpecialOptions(this->specialOptions()&~65536); #if 0 this->writeBasis("a.bas",true); for (int i=0;inumberRows();i++) printf("%d %g\n",i,this->dualRowSolution()[i]); this->dual(); this->writeBasis("b.bas",true); for (int i=0;inumberRows();i++) printf("%d %g\n",i,this->dualRowSolution()[i]); #endif // switch off initialSolve flag moreSpecialOptions_ &= ~16384; //this->setNumberIterations(abcModel2->numberIterations()+this->numberIterations()); delete abcModel2; } } #endif /** General solve algorithm which can do presolve special options (bits) 1 - do not perturb 2 - do not scale 4 - use crash (default allslack in dual, idiot in primal) 8 - all slack basis in primal 16 - switch off interrupt handling 32 - do not try and make plus minus one matrix 64 - do not use sprint even if problem looks good */ int ClpSimplex::initialSolve(ClpSolve & options) { ClpSolve::SolveType method = options.getSolveType(); //ClpSolve::SolveType originalMethod=method; ClpSolve::PresolveType presolve = options.getPresolveType(); int saveMaxIterations = maximumIterations(); int finalStatus = -1; int numberIterations = 0; double time1 = CoinCpuTime(); double timeX = time1; double time2; ClpMatrixBase * saveMatrix = NULL; ClpObjective * savedObjective = NULL; if (!objective_ || !matrix_) { // totally empty handler_->message(CLP_EMPTY_PROBLEM, messages_) << 0 << 0 << 0 << CoinMessageEol; return -1; } else if (!numberRows_ || !numberColumns_ || !getNumElements()) { presolve = ClpSolve::presolveOff; } if (objective_->type() >= 2 && optimizationDirection_ == 0) { // pretend linear savedObjective = objective_; // make up objective double * obj = new double[numberColumns_]; for (int i = 0; i < numberColumns_; i++) { double l = fabs(columnLower_[i]); double u = fabs(columnUpper_[i]); obj[i] = 0.0; if (CoinMin(l, u) < 1.0e20) { if (l < u) obj[i] = 1.0 + randomNumberGenerator_.randomDouble() * 1.0e-2; else obj[i] = -1.0 - randomNumberGenerator_.randomDouble() * 1.0e-2; } } objective_ = new ClpLinearObjective(obj, numberColumns_); delete [] obj; } ClpSimplex * model2 = this; bool interrupt = (options.getSpecialOption(2) == 0); CoinSighandler_t saveSignal = static_cast (0); if (interrupt) { currentModel = model2; // register signal handler saveSignal = signal(SIGINT, signal_handler); } // If no status array - set up basis if (!status_) allSlackBasis(); ClpPresolve * pinfo = new ClpPresolve(); pinfo->setSubstitution(options.substitution()); int presolveOptions = options.presolveActions(); bool presolveToFile = (presolveOptions & 0x40000000) != 0; presolveOptions &= ~0x40000000; if ((presolveOptions & 0xffff) != 0) pinfo->setPresolveActions(presolveOptions); // switch off singletons to slacks //pinfo->setDoSingletonColumn(false); // done by bits int printOptions = options.getSpecialOption(5); if ((printOptions & 1) != 0) pinfo->statistics(); double timePresolve = 0.0; double timeIdiot = 0.0; double timeCore = 0.0; eventHandler()->event(ClpEventHandler::presolveStart); int savePerturbation = perturbation_; int saveScaling = scalingFlag_; #ifndef SLIM_CLP #ifndef NO_RTTI if (dynamic_cast< ClpNetworkMatrix*>(matrix_)) { // network - switch off stuff presolve = ClpSolve::presolveOff; } #else if (matrix_->type() == 11) { // network - switch off stuff presolve = ClpSolve::presolveOff; } #endif #endif if (presolve != ClpSolve::presolveOff) { bool costedSlacks = false; #ifdef ABC_INHERIT int numberPasses = 20; #else int numberPasses = 5; #endif if (presolve == ClpSolve::presolveNumber) { numberPasses = options.getPresolvePasses(); presolve = ClpSolve::presolveOn; } else if (presolve == ClpSolve::presolveNumberCost) { numberPasses = options.getPresolvePasses(); presolve = ClpSolve::presolveOn; costedSlacks = true; // switch on singletons to slacks pinfo->setDoSingletonColumn(true); // gub stuff for testing //pinfo->setDoGubrow(true); } #ifndef CLP_NO_STD if (presolveToFile) { // PreSolve to file - not fully tested printf("Presolving to file - presolve.save\n"); pinfo->presolvedModelToFile(*this, "presolve.save", dblParam_[ClpPresolveTolerance], false, numberPasses); model2 = this; } else { #endif model2 = pinfo->presolvedModel(*this, dblParam_[ClpPresolveTolerance], false, numberPasses, true, costedSlacks); #ifndef CLP_NO_STD } #endif time2 = CoinCpuTime(); timePresolve = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Presolve" << timePresolve << time2 - time1 << CoinMessageEol; timeX = time2; if (!model2) { handler_->message(CLP_INFEASIBLE, messages_) << CoinMessageEol; model2 = this; eventHandler()->event(ClpEventHandler::presolveInfeasible); problemStatus_ = pinfo->presolveStatus(); if (options.infeasibleReturn() || (moreSpecialOptions_ & 1) != 0) { delete pinfo; return -1; } presolve = ClpSolve::presolveOff; } else { #if 0 //def ABC_INHERIT { AbcSimplex * abcModel2=new AbcSimplex(*model2); delete model2; model2=abcModel2; pinfo->setPresolvedModel(model2); } #else //ClpModel::stopPermanentArrays(); //setSpecialOptions(specialOptions()&~65536); #endif model2->eventHandler()->setSimplex(model2); int rcode=model2->eventHandler()->event(ClpEventHandler::presolveSize); // see if too big or small if (rcode==2) { delete model2; delete pinfo; return -2; } else if (rcode==3) { delete model2; delete pinfo; return -3; } } model2->setMoreSpecialOptions(model2->moreSpecialOptions()&(~1024)); model2->eventHandler()->setSimplex(model2); // We may be better off using original (but if dual leave because of bounds) if (presolve != ClpSolve::presolveOff && numberRows_ < 1.01 * model2->numberRows_ && numberColumns_ < 1.01 * model2->numberColumns_ && model2 != this) { if(method != ClpSolve::useDual || (numberRows_ == model2->numberRows_ && numberColumns_ == model2->numberColumns_)) { delete model2; model2 = this; presolve = ClpSolve::presolveOff; } } } if (interrupt) currentModel = model2; // For below >0 overrides // 0 means no, -1 means maybe int doIdiot = 0; int doCrash = 0; int doSprint = 0; int doSlp = 0; int primalStartup = 1; model2->eventHandler()->event(ClpEventHandler::presolveBeforeSolve); bool tryItSave = false; // switch to primal from automatic if just one cost entry if (method == ClpSolve::automatic && model2->numberColumns() > 5000 && (specialOptions_ & 1024) != 0) { int numberColumns = model2->numberColumns(); int numberRows = model2->numberRows(); const double * obj = model2->objective(); int nNon = 0; for (int i = 0; i < numberColumns; i++) { if (obj[i]) nNon++; } if (nNon == 1) { #ifdef COIN_DEVELOP printf("Forcing primal\n"); #endif method = ClpSolve::usePrimal; tryItSave = numberRows > 200 && numberColumns > 2000 && (numberColumns > 2 * numberRows || (specialOptions_ & 1024) != 0); } } if (method != ClpSolve::useDual && method != ClpSolve::useBarrier && method != ClpSolve::useBarrierNoCross) { switch (options.getSpecialOption(1)) { case 0: doIdiot = -1; doCrash = -1; doSprint = -1; break; case 1: doIdiot = 0; doCrash = 1; if (options.getExtraInfo(1) > 0) doCrash = options.getExtraInfo(1); doSprint = 0; break; case 2: doIdiot = 1; if (options.getExtraInfo(1) > 0) doIdiot = options.getExtraInfo(1); doCrash = 0; doSprint = 0; break; case 3: doIdiot = 0; doCrash = 0; doSprint = 1; break; case 4: doIdiot = 0; doCrash = 0; doSprint = 0; break; case 5: doIdiot = 0; doCrash = -1; doSprint = -1; break; case 6: doIdiot = -1; doCrash = -1; doSprint = 0; break; case 7: doIdiot = -1; doCrash = 0; doSprint = -1; break; case 8: doIdiot = -1; doCrash = 0; doSprint = 0; break; case 9: doIdiot = 0; doCrash = 0; doSprint = -1; break; case 10: doIdiot = 0; doCrash = 0; doSprint = 0; if (options.getExtraInfo(1) > 0) doSlp = options.getExtraInfo(1); break; case 11: doIdiot = 0; doCrash = 0; doSprint = 0; primalStartup = 0; break; default: abort(); } } else { // Dual switch (options.getSpecialOption(0)) { case 0: doIdiot = 0; doCrash = 0; doSprint = 0; break; case 1: doIdiot = 0; doCrash = 1; if (options.getExtraInfo(0) > 0) doCrash = options.getExtraInfo(0); doSprint = 0; break; case 2: doIdiot = -1; if (options.getExtraInfo(0) > 0) doIdiot = options.getExtraInfo(0); doCrash = 0; doSprint = 0; break; default: abort(); } } #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objectiveAsObject())); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif // If quadratic then primal or barrier or slp if (quadraticObj) { doSprint = 0; doIdiot = 0; // off if (method == ClpSolve::useBarrier) method = ClpSolve::useBarrierNoCross; else if (method != ClpSolve::useBarrierNoCross) method = ClpSolve::usePrimal; } #ifdef COIN_HAS_VOL // Save number of idiot int saveDoIdiot = doIdiot; #endif // Just do this number of passes in Sprint int maxSprintPass = 100; // See if worth trying +- one matrix bool plusMinus = false; int numberElements = model2->getNumElements(); #ifndef SLIM_CLP #ifndef NO_RTTI if (dynamic_cast< ClpNetworkMatrix*>(matrix_)) { // network - switch off stuff doIdiot = 0; if (doSprint < 0) doSprint = 0; } #else if (matrix_->type() == 11) { // network - switch off stuff doIdiot = 0; //doSprint=0; } #endif #endif int numberColumns = model2->numberColumns(); int numberRows = model2->numberRows(); // If not all slack basis - switch off all except sprint int numberRowsBasic = 0; int iRow; for (iRow = 0; iRow < numberRows; iRow++) if (model2->getRowStatus(iRow) == basic) numberRowsBasic++; if (numberRowsBasic < numberRows) { doIdiot = 0; doCrash = 0; //doSprint=0; } if (options.getSpecialOption(3) == 0) { if(numberElements > 100000) plusMinus = true; if(numberElements > 10000 && (doIdiot || doSprint)) plusMinus = true; } else if ((specialOptions_ & 1024) != 0) { plusMinus = true; } #ifndef SLIM_CLP // Statistics (+1,-1, other) - used to decide on strategy if not +-1 CoinBigIndex statistics[3] = { -1, 0, 0}; if (plusMinus) { saveMatrix = model2->clpMatrix(); #ifndef NO_RTTI ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(saveMatrix); #else ClpPackedMatrix* clpMatrix = NULL; if (saveMatrix->type() == 1) clpMatrix = static_cast< ClpPackedMatrix*>(saveMatrix); #endif if (clpMatrix) { ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix())); if (newMatrix->getIndices()) { // CHECKME This test of specialOptions and the one above // don't seem compatible. #ifndef ABC_INHERIT if ((specialOptions_ & 1024) == 0) { model2->replaceMatrix(newMatrix); } else { #endif // in integer (or abc) - just use for sprint/idiot saveMatrix = NULL; delete newMatrix; #ifndef ABC_INHERIT } #endif } else { handler_->message(CLP_MATRIX_CHANGE, messages_) << "+- 1" << CoinMessageEol; CoinMemcpyN(newMatrix->startPositive(), 3, statistics); saveMatrix = NULL; plusMinus = false; delete newMatrix; } } else { saveMatrix = NULL; plusMinus = false; } } #endif if (this->factorizationFrequency() == 200) { // User did not touch preset model2->defaultFactorizationFrequency(); } else if (model2 != this) { // make sure model2 has correct value model2->setFactorizationFrequency(this->factorizationFrequency()); } if (method == ClpSolve::automatic) { if (doSprint == 0 && doIdiot == 0) { // off method = ClpSolve::useDual; } else { // only do primal if sprint or idiot if (doSprint > 0) { method = ClpSolve::usePrimalorSprint; } else if (doIdiot > 0) { method = ClpSolve::usePrimal; } else { if (numberElements < 500000) { // Small problem if(numberRows * 10 > numberColumns || numberColumns < 6000 || (numberRows * 20 > numberColumns && !plusMinus)) doSprint = 0; // switch off sprint } else { // larger problem if(numberRows * 8 > numberColumns) doSprint = 0; // switch off sprint } // switch off idiot or sprint if any free variable // switch off sprint if very few with costs int iColumn; const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); const double * objective = model2->objective(); int nObj=0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] < -1.0e10 && columnUpper[iColumn] > 1.0e10) { doSprint = 0; doIdiot = 0; break; } else if (objective[iColumn]) { nObj++; } } if (nObj*10rowLower_[iRow]; if (value1 && value1 > -1.0e31) { largest = CoinMax(largest, fabs(value1)); smallest = CoinMin(smallest, fabs(value1)); if (fabs(value1 - floor(value1 + 0.5)) > 1.0e-8) { notInteger = true; break; } } double value2 = model2->rowUpper_[iRow]; if (value2 && value2 < 1.0e31) { largest = CoinMax(largest, fabs(value2)); smallest = CoinMin(smallest, fabs(value2)); if (fabs(value2 - floor(value2 + 0.5)) > 1.0e-8) { notInteger = true; break; } } // CHECKME This next bit can't be right... if (value2 > value1) { numberNotE++; //if (value2 > 1.0e31 || value1 < -1.0e31) // largestGap = COIN_DBL_MAX; //else // largestGap = value2 - value1; } } bool tryIt = numberRows > 200 && numberColumns > 2000 && (numberColumns > 2 * numberRows || (method != ClpSolve::useDual && (specialOptions_ & 1024) != 0)); tryItSave = tryIt; if (numberRows < 1000 && numberColumns < 3000) tryIt = false; if (notInteger) tryIt = false; if (largest / smallest > 10 || (largest / smallest > 2.0 && largest > 50)) tryIt = false; if (tryIt) { if (largest / smallest > 2.0) { nPasses = 10 + numberColumns / 100000; nPasses = CoinMin(nPasses, 50); nPasses = CoinMax(nPasses, 15); if (numberRows > 20000 && nPasses > 5) { // Might as well go for it nPasses = CoinMax(nPasses, 71); } else if (numberRows > 2000 && nPasses > 5) { nPasses = CoinMax(nPasses, 50); } else if (numberElements < 3 * numberColumns) { nPasses = CoinMin(nPasses, 10); // probably not worh it } } else if (largest / smallest > 1.01 || numberElements <= 3 * numberColumns) { nPasses = 10 + numberColumns / 1000; nPasses = CoinMin(nPasses, 100); nPasses = CoinMax(nPasses, 30); if (numberRows > 25000) { // Might as well go for it nPasses = CoinMax(nPasses, 71); } if (!largestGap) nPasses *= 2; } else { nPasses = 10 + numberColumns / 1000; nPasses = CoinMin(nPasses, 200); nPasses = CoinMax(nPasses, 100); if (!largestGap) nPasses *= 2; } } //printf("%d rows %d cols plus %c tryIt %c largest %g smallest %g largestGap %g npasses %d sprint %c\n", // numberRows,numberColumns,plusMinus ? 'Y' : 'N', // tryIt ? 'Y' :'N',largest,smallest,largestGap,nPasses,doSprint ? 'Y' :'N'); //exit(0); if (!tryIt || nPasses <= 5) doIdiot = 0; if (doSprint) { method = ClpSolve::usePrimalorSprint; } else if (doIdiot) { method = ClpSolve::usePrimal; } else { method = ClpSolve::useDual; } } } } if (method == ClpSolve::usePrimalorSprint) { if (doSprint < 0) { if (numberElements < 500000) { // Small problem if(numberRows * 10 > numberColumns || numberColumns < 6000 || (numberRows * 20 > numberColumns && !plusMinus)) method = ClpSolve::usePrimal; // switch off sprint } else { // larger problem if(numberRows * 8 > numberColumns) method = ClpSolve::usePrimal; // switch off sprint // but make lightweight if(numberRows * 10 > numberColumns || numberColumns < 6000 || (numberRows * 20 > numberColumns && !plusMinus)) maxSprintPass = 10; } } else if (doSprint == 0) { method = ClpSolve::usePrimal; // switch off sprint } } if (method == ClpSolve::useDual) { double * saveLower = NULL; double * saveUpper = NULL; if (presolve == ClpSolve::presolveOn) { int numberInfeasibilities = model2->tightenPrimalBounds(0.0, 0); if (numberInfeasibilities) { handler_->message(CLP_INFEASIBLE, messages_) << CoinMessageEol; delete model2; model2 = this; presolve = ClpSolve::presolveOff; } } else if (numberRows_ + numberColumns_ > 5000) { // do anyway saveLower = new double[numberRows_+numberColumns_]; CoinMemcpyN(model2->columnLower(), numberColumns_, saveLower); CoinMemcpyN(model2->rowLower(), numberRows_, saveLower + numberColumns_); saveUpper = new double[numberRows_+numberColumns_]; CoinMemcpyN(model2->columnUpper(), numberColumns_, saveUpper); CoinMemcpyN(model2->rowUpper(), numberRows_, saveUpper + numberColumns_); int numberInfeasibilities = model2->tightenPrimalBounds(); if (numberInfeasibilities) { handler_->message(CLP_INFEASIBLE, messages_) << CoinMessageEol; CoinMemcpyN(saveLower, numberColumns_, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns_, numberRows_, model2->rowLower()); delete [] saveLower; saveLower = NULL; CoinMemcpyN(saveUpper, numberColumns_, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns_, numberRows_, model2->rowUpper()); delete [] saveUpper; saveUpper = NULL; } } #ifndef COIN_HAS_VOL // switch off idiot and volume for now doIdiot = 0; #endif // pick up number passes int nPasses = 0; int numberNotE = 0; #ifndef SLIM_CLP if ((doIdiot < 0 && plusMinus) || doIdiot > 0) { // See if candidate for idiot nPasses = 0; Idiot info(*model2); // Get average number of elements per column double ratio = static_cast (numberElements) / static_cast (numberColumns); // look at rhs int iRow; double largest = 0.0; double smallest = 1.0e30; for (iRow = 0; iRow < numberRows; iRow++) { double value1 = model2->rowLower_[iRow]; if (value1 && value1 > -1.0e31) { largest = CoinMax(largest, fabs(value1)); smallest = CoinMin(smallest, fabs(value1)); } double value2 = model2->rowUpper_[iRow]; if (value2 && value2 < 1.0e31) { largest = CoinMax(largest, fabs(value2)); smallest = CoinMin(smallest, fabs(value2)); } if (value2 > value1) { numberNotE++; } } if (doIdiot < 0) { if (numberRows > 200 && numberColumns > 5000 && ratio >= 3.0 && largest / smallest < 1.1 && !numberNotE) { nPasses = 71; } } if (doIdiot > 0) { nPasses = CoinMax(nPasses, doIdiot); if (nPasses > 70) { info.setStartingWeight(1.0e3); info.setDropEnoughFeasibility(0.01); } } if (nPasses > 20) { #ifdef COIN_HAS_VOL int returnCode = solveWithVolume(model2, nPasses, saveDoIdiot); if (!returnCode) { time2 = CoinCpuTime(); timeIdiot = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Idiot Crash" << timeIdiot << time2 - time1 << CoinMessageEol; timeX = time2; } else { nPasses = 0; } #else nPasses = 0; #endif } else { nPasses = 0; } } #endif if (doCrash) { #ifdef ABC_INHERIT if (!model2->abcState()) { #endif switch(doCrash) { // standard case 1: model2->crash(1000, 1); break; // As in paper by Solow and Halim (approx) case 2: case 3: model2->crash(model2->dualBound(), 0); break; // Just put free in basis case 4: model2->crash(0.0, 3); break; } #ifdef ABC_INHERIT } else if (doCrash>=0) { model2->setAbcState(model2->abcState()|256*doCrash); } #endif } if (!nPasses) { int saveOptions = model2->specialOptions(); if (model2->numberRows() > 100) model2->setSpecialOptions(saveOptions | 64); // go as far as possible //int numberRows = model2->numberRows(); //int numberColumns = model2->numberColumns(); if (dynamic_cast< ClpPackedMatrix*>(matrix_)) { // See if original wanted vector ClpPackedMatrix * clpMatrixO = dynamic_cast< ClpPackedMatrix*>(matrix_); ClpMatrixBase * matrix = model2->clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix) && clpMatrixO->wantsSpecialColumnCopy()) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); //model2->setSpecialOptions(model2->specialOptions()|256); // to say no row copy for comparisons model2->dual(0); clpMatrix->releaseSpecialColumnCopy(); } else { #ifndef ABC_INHERIT model2->dual(0); #else model2->dealWithAbc(0,0,interrupt); #endif } } else { model2->dual(0); } } else if (!numberNotE && 0) { // E so we can do in another way double * pi = model2->dualRowSolution(); int i; int numberColumns = model2->numberColumns(); int numberRows = model2->numberRows(); double * saveObj = new double[numberColumns]; CoinMemcpyN(model2->objective(), numberColumns, saveObj); CoinMemcpyN(model2->objective(), numberColumns, model2->dualColumnSolution()); model2->clpMatrix()->transposeTimes(-1.0, pi, model2->dualColumnSolution()); CoinMemcpyN(model2->dualColumnSolution(), numberColumns, model2->objective()); const double * rowsol = model2->primalRowSolution(); double offset = 0.0; for (i = 0; i < numberRows; i++) { offset += pi[i] * rowsol[i]; } double value2; model2->getDblParam(ClpObjOffset, value2); //printf("Offset %g %g\n",offset,value2); model2->setDblParam(ClpObjOffset, value2 - offset); model2->setPerturbation(51); //model2->setRowObjective(pi); // zero out pi //memset(pi,0,numberRows*sizeof(double)); // Could put some in basis - only partially tested model2->allSlackBasis(); //model2->factorization()->maximumPivots(200); //model2->setLogLevel(63); // solve model2->dual(0); model2->setDblParam(ClpObjOffset, value2); CoinMemcpyN(saveObj, numberColumns, model2->objective()); // zero out pi //memset(pi,0,numberRows*sizeof(double)); //model2->setRowObjective(pi); delete [] saveObj; //model2->dual(0); model2->setPerturbation(50); model2->primal(); } else { // solve model2->setPerturbation(100); model2->dual(2); model2->setPerturbation(50); model2->dual(0); } if (saveLower) { CoinMemcpyN(saveLower, numberColumns_, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns_, numberRows_, model2->rowLower()); delete [] saveLower; saveLower = NULL; CoinMemcpyN(saveUpper, numberColumns_, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns_, numberRows_, model2->rowUpper()); delete [] saveUpper; saveUpper = NULL; } time2 = CoinCpuTime(); timeCore = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Dual" << timeCore << time2 - time1 << CoinMessageEol; timeX = time2; } else if (method == ClpSolve::usePrimal) { #ifndef SLIM_CLP if (doIdiot) { int nPasses = 0; Idiot info(*model2); // Get average number of elements per column double ratio = static_cast (numberElements) / static_cast (numberColumns); // look at rhs int iRow; double largest = 0.0; double smallest = 1.0e30; double largestGap = 0.0; int numberNotE = 0; for (iRow = 0; iRow < numberRows; iRow++) { double value1 = model2->rowLower_[iRow]; if (value1 && value1 > -1.0e31) { largest = CoinMax(largest, fabs(value1)); smallest = CoinMin(smallest, fabs(value1)); } double value2 = model2->rowUpper_[iRow]; if (value2 && value2 < 1.0e31) { largest = CoinMax(largest, fabs(value2)); smallest = CoinMin(smallest, fabs(value2)); } if (value2 > value1) { numberNotE++; if (value2 > 1.0e31 || value1 < -1.0e31) largestGap = COIN_DBL_MAX; else largestGap = value2 - value1; } } bool increaseSprint = plusMinus; if ((specialOptions_ & 1024) != 0) increaseSprint = false; if (!plusMinus) { // If 90% +- 1 then go for sprint if (statistics[0] >= 0 && 10 * statistics[2] < statistics[0] + statistics[1]) increaseSprint = true; } bool tryIt = tryItSave; if (numberRows < 1000 && numberColumns < 3000) tryIt = false; if (tryIt) { if (increaseSprint) { info.setStartingWeight(1.0e3); info.setReduceIterations(6); // also be more lenient on infeasibilities info.setDropEnoughFeasibility(0.5 * info.getDropEnoughFeasibility()); info.setDropEnoughWeighted(-2.0); if (largest / smallest > 2.0) { nPasses = 10 + numberColumns / 100000; nPasses = CoinMin(nPasses, 50); nPasses = CoinMax(nPasses, 15); if (numberRows > 20000 && nPasses > 5) { // Might as well go for it nPasses = CoinMax(nPasses, 71); } else if (numberRows > 2000 && nPasses > 5) { nPasses = CoinMax(nPasses, 50); } else if (numberElements < 3 * numberColumns) { nPasses = CoinMin(nPasses, 10); // probably not worh it if (doIdiot < 0) info.setLightweight(1); // say lightweight idiot } else { if (doIdiot < 0) info.setLightweight(1); // say lightweight idiot } } else if (largest / smallest > 1.01 || numberElements <= 3 * numberColumns) { nPasses = 10 + numberColumns / 1000; nPasses = CoinMin(nPasses, 100); nPasses = CoinMax(nPasses, 30); if (numberRows > 25000) { // Might as well go for it nPasses = CoinMax(nPasses, 71); } if (!largestGap) nPasses *= 2; } else { nPasses = 10 + numberColumns / 1000; nPasses = CoinMin(nPasses, 200); nPasses = CoinMax(nPasses, 100); info.setStartingWeight(1.0e-1); info.setReduceIterations(6); if (!largestGap) nPasses *= 2; //info.setFeasibilityTolerance(1.0e-7); } // If few passes - don't bother if (nPasses <= 5 && !plusMinus) nPasses = 0; } else { if (doIdiot < 0) info.setLightweight(1); // say lightweight idiot if (largest / smallest > 1.01 || numberNotE || statistics[2] > statistics[0] + statistics[1]) { if (numberRows > 25000 || numberColumns > 5 * numberRows) { nPasses = 50; } else if (numberColumns > 4 * numberRows) { nPasses = 20; } else { nPasses = 5; } } else { if (numberRows > 25000 || numberColumns > 5 * numberRows) { nPasses = 50; info.setLightweight(0); // say not lightweight idiot } else if (numberColumns > 4 * numberRows) { nPasses = 20; } else { nPasses = 15; } } if (ratio < 3.0) { nPasses = static_cast (ratio * static_cast (nPasses) / 4.0); // probably not worth it } else { nPasses = CoinMax(nPasses, 5); } if (numberRows > 25000 && nPasses > 5) { // Might as well go for it nPasses = CoinMax(nPasses, 71); } else if (increaseSprint) { nPasses *= 2; nPasses = CoinMin(nPasses, 71); } else if (nPasses == 5 && ratio > 5.0) { nPasses = static_cast (static_cast (nPasses) * (ratio / 5.0)); // increase if lots of elements per column } if (nPasses <= 5 && !plusMinus) nPasses = 0; //info.setStartingWeight(1.0e-1); } } if (doIdiot > 0) { // pick up number passes nPasses = options.getExtraInfo(1) % 1000000; #ifdef COIN_HAS_VOL int returnCode = solveWithVolume(model2, nPasses, saveDoIdiot); nPasses=0; if (!returnCode) { time2 = CoinCpuTime(); timeIdiot = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Idiot Crash" << timeIdiot << time2 - time1 << CoinMessageEol; timeX = time2; } #endif if (nPasses > 70) { info.setStartingWeight(1.0e3); info.setReduceIterations(6); //if (nPasses > 200) //info.setFeasibilityTolerance(1.0e-9); //if (nPasses > 1900) //info.setWeightFactor(0.93); if (nPasses > 900) { double reductions=nPasses/6.0; if (nPasses<5000) { reductions /= 12.0; } else { reductions /= 13.0; info.setStartingWeight(1.0e4); } double ratio=1.0/std::pow(10.0,(1.0/reductions)); printf("%d passes reduction factor %g\n",nPasses,ratio); info.setWeightFactor(ratio); } else if (nPasses > 500) { info.setWeightFactor(0.7); } else if (nPasses > 200) { info.setWeightFactor(0.5); } if (maximumIterations()setMaximumIterations(COIN_INT_MAX); } if (nPasses >= 10000&&nPasses<100000) { int k = nPasses % 100; nPasses /= 200; info.setReduceIterations(3); if (k) info.setStartingWeight(1.0e2); } // also be more lenient on infeasibilities info.setDropEnoughFeasibility(0.5 * info.getDropEnoughFeasibility()); info.setDropEnoughWeighted(-2.0); } else if (nPasses >= 50) { info.setStartingWeight(1.0e3); //info.setReduceIterations(6); } // For experimenting if (nPasses < 70 && (nPasses % 10) > 0 && (nPasses % 10) < 4) { info.setStartingWeight(1.0e3); info.setLightweight(nPasses % 10); // special testing #ifdef COIN_DEVELOP printf("warning - odd lightweight %d\n", nPasses % 10); //info.setReduceIterations(6); #endif } } if (options.getExtraInfo(1) > 1000000) nPasses += 1000000; if (nPasses) { doCrash = 0; #if 0 double * solution = model2->primalColumnSolution(); int iColumn; double * saveLower = new double[numberColumns]; CoinMemcpyN(model2->columnLower(), numberColumns, saveLower); double * saveUpper = new double[numberColumns]; CoinMemcpyN(model2->columnUpper(), numberColumns, saveUpper); printf("doing tighten before idiot\n"); model2->tightenPrimalBounds(); // Move solution double * columnLower = model2->columnLower(); double * columnUpper = model2->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLower[iColumn] > 0.0) solution[iColumn] = columnLower[iColumn]; else if (columnUpper[iColumn] < 0.0) solution[iColumn] = columnUpper[iColumn]; else solution[iColumn] = 0.0; } CoinMemcpyN(saveLower, numberColumns, columnLower); CoinMemcpyN(saveUpper, numberColumns, columnUpper); delete [] saveLower; delete [] saveUpper; #else // Allow for crossover //#define LACI_TRY #ifndef LACI_TRY //if (doIdiot>0) #ifdef ABC_INHERIT if (!model2->abcState()) #endif info.setStrategy(512 | info.getStrategy()); #endif // Allow for scaling info.setStrategy(32 | info.getStrategy()); info.crash(nPasses, model2->messageHandler(), model2->messagesPointer()); #endif time2 = CoinCpuTime(); timeIdiot = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Idiot Crash" << timeIdiot << time2 - time1 << CoinMessageEol; timeX = time2; if (nPasses>100000&&nPasses<100500) { // make sure no status left model2->createStatus(); // solve if (model2->factorizationFrequency() == 200) { // User did not touch preset model2->defaultFactorizationFrequency(); } //int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); // save duals //double * saveDuals = CoinCopyOfArray(model2->dualRowSolution(),numberRows); // for moment this only works on nug etc (i.e. all ==) // needs row objective double * saveObj = CoinCopyOfArray(model2->objective(),numberColumns); double * pi = model2->dualRowSolution(); model2->clpMatrix()->transposeTimes(-1.0, pi, model2->objective()); // just primal values pass double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->writeMps("xx.mps"); double * solution = model2->primalColumnSolution(); double * upper = model2->columnUpper(); for (int i=0;isetProblemStatus(-1); model2->setObjectiveScale(saveScale); #ifdef ABC_INHERIT AbcSimplex * abcModel2=new AbcSimplex(*model2); if (interrupt) currentAbcModel = abcModel2; if (abcSimplex_) { // move factorization stuff abcModel2->factorization()->synchronize(model2->factorization(),abcModel2); } abcModel2->startPermanentArrays(); abcModel2->setAbcState(CLP_ABC_WANTED); #if ABC_PARALLEL int parallelMode=1; printf("Parallel mode %d\n",parallelMode); abcModel2->setParallelMode(parallelMode); #endif //if (processTune>0&&processTune<8) //abcModel2->setMoreSpecialOptions(abcModel2->moreSpecialOptions()|65536*processTune); abcModel2->doAbcDual(); abcModel2->moveStatusToClp(model2); //ClpModel::stopPermanentArrays(); model2->setSpecialOptions(model2->specialOptions()&~65536); //model2->dual(); //model2->setNumberIterations(abcModel2->numberIterations()+model2->numberIterations()); delete abcModel2; #endif memcpy(model2->objective(),saveObj,numberColumns*sizeof(double)); //delete [] saveDuals; delete [] saveObj; model2->dual(2); } // end dubious idiot } } #endif // ? if (doCrash) { switch(doCrash) { // standard case 1: model2->crash(1000, 1); break; // As in paper by Solow and Halim (approx) case 2: model2->crash(model2->dualBound(), 0); break; // My take on it case 3: model2->crash(model2->dualBound(), -1); break; // Just put free in basis case 4: model2->crash(0.0, 3); break; } } #ifndef SLIM_CLP if (doSlp > 0 && objective_->type() == 2) { model2->nonlinearSLP(doSlp, 1.0e-5); } #endif #ifndef LACI_TRY if (options.getSpecialOption(1) != 2 || options.getExtraInfo(1) < 1000000) { if (dynamic_cast< ClpPackedMatrix*>(matrix_)) { // See if original wanted vector ClpPackedMatrix * clpMatrixO = dynamic_cast< ClpPackedMatrix*>(matrix_); ClpMatrixBase * matrix = model2->clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix) && clpMatrixO->wantsSpecialColumnCopy()) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); //model2->setSpecialOptions(model2->specialOptions()|256); // to say no row copy for comparisons model2->primal(primalStartup); clpMatrix->releaseSpecialColumnCopy(); } else { #ifndef ABC_INHERIT model2->primal(primalStartup); #else model2->dealWithAbc(1,primalStartup,interrupt); #endif } } else { #ifndef ABC_INHERIT model2->primal(primalStartup); #else model2->dealWithAbc(1,primalStartup,interrupt); #endif } } #endif time2 = CoinCpuTime(); timeCore = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Primal" << timeCore << time2 - time1 << CoinMessageEol; timeX = time2; } else if (method == ClpSolve::usePrimalorSprint) { // Sprint /* This driver implements what I called Sprint when I introduced the idea many years ago. Cplex calls it "sifting" which I think is just as silly. When I thought of this trivial idea it reminded me of an LP code of the 60's called sprint which after every factorization took a subset of the matrix into memory (all 64K words!) and then iterated very fast on that subset. On the problems of those days it did not work very well, but it worked very well on aircrew scheduling problems where there were very large numbers of columns all with the same flavor. */ /* The idea works best if you can get feasible easily. To make it more general we can add in costed slacks */ int originalNumberColumns = model2->numberColumns(); int numberRows = model2->numberRows(); ClpSimplex * originalModel2 = model2; // We will need arrays to choose variables. These are too big but .. double * weight = new double [numberRows+originalNumberColumns]; int * sort = new int [numberRows+originalNumberColumns]; int numberSort = 0; // We are going to add slacks to get feasible. // initial list will just be artificials int iColumn; const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); double * columnSolution = model2->primalColumnSolution(); // See if we have costed slacks int * negSlack = new int[numberRows]; int * posSlack = new int[numberRows]; int iRow; for (iRow = 0; iRow < numberRows; iRow++) { negSlack[iRow] = -1; posSlack[iRow] = -1; } const double * element = model2->matrix()->getElements(); const int * row = model2->matrix()->getIndices(); const CoinBigIndex * columnStart = model2->matrix()->getVectorStarts(); const int * columnLength = model2->matrix()->getVectorLengths(); //bool allSlack = (numberRowsBasic==numberRows); for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { if (!columnSolution[iColumn] || fabs(columnSolution[iColumn]) > 1.0e20) { double value = 0.0; if (columnLower[iColumn] > 0.0) value = columnLower[iColumn]; else if (columnUpper[iColumn] < 0.0) value = columnUpper[iColumn]; columnSolution[iColumn] = value; } if (columnLength[iColumn] == 1) { int jRow = row[columnStart[iColumn]]; if (!columnLower[iColumn]) { if (element[columnStart[iColumn]] > 0.0 && posSlack[jRow] < 0) posSlack[jRow] = iColumn; else if (element[columnStart[iColumn]] < 0.0 && negSlack[jRow] < 0) negSlack[jRow] = iColumn; } else if (!columnUpper[iColumn]) { if (element[columnStart[iColumn]] < 0.0 && posSlack[jRow] < 0) posSlack[jRow] = iColumn; else if (element[columnStart[iColumn]] > 0.0 && negSlack[jRow] < 0) negSlack[jRow] = iColumn; } } } // now see what that does to row solution double * rowSolution = model2->primalRowSolution(); CoinZeroN (rowSolution, numberRows); model2->clpMatrix()->times(1.0, columnSolution, rowSolution); // See if we can adjust using costed slacks double penalty = CoinMax(1.0e5, CoinMin(infeasibilityCost_ * 0.01, 1.0e10)) * optimizationDirection_; const double * lower = model2->rowLower(); const double * upper = model2->rowUpper(); for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > rowSolution[iRow] + 1.0e-8) { int jColumn = posSlack[iRow]; if (jColumn >= 0) { if (columnSolution[jColumn]) continue; double difference = lower[iRow] - rowSolution[iRow]; double elementValue = element[columnStart[jColumn]]; if (elementValue > 0.0) { double movement = CoinMin(difference / elementValue, columnUpper[jColumn]); columnSolution[jColumn] = movement; rowSolution[iRow] += movement * elementValue; } else { double movement = CoinMax(difference / elementValue, columnLower[jColumn]); columnSolution[jColumn] = movement; rowSolution[iRow] += movement * elementValue; } } } else if (upper[iRow] < rowSolution[iRow] - 1.0e-8) { int jColumn = negSlack[iRow]; if (jColumn >= 0) { if (columnSolution[jColumn]) continue; double difference = upper[iRow] - rowSolution[iRow]; double elementValue = element[columnStart[jColumn]]; if (elementValue < 0.0) { double movement = CoinMin(difference / elementValue, columnUpper[jColumn]); columnSolution[jColumn] = movement; rowSolution[iRow] += movement * elementValue; } else { double movement = CoinMax(difference / elementValue, columnLower[jColumn]); columnSolution[jColumn] = movement; rowSolution[iRow] += movement * elementValue; } } } } delete [] negSlack; delete [] posSlack; int nRow = numberRows; bool network = false; if (dynamic_cast< ClpNetworkMatrix*>(matrix_)) { network = true; nRow *= 2; } int * addStarts = new int [nRow+1]; int * addRow = new int[nRow]; double * addElement = new double[nRow]; addStarts[0] = 0; int numberArtificials = 0; int numberAdd = 0; double * addCost = new double [numberRows]; for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > rowSolution[iRow] + 1.0e-8) { addRow[numberAdd] = iRow; addElement[numberAdd++] = 1.0; if (network) { addRow[numberAdd] = numberRows; addElement[numberAdd++] = -1.0; } addCost[numberArtificials] = penalty; numberArtificials++; addStarts[numberArtificials] = numberAdd; } else if (upper[iRow] < rowSolution[iRow] - 1.0e-8) { addRow[numberAdd] = iRow; addElement[numberAdd++] = -1.0; if (network) { addRow[numberAdd] = numberRows; addElement[numberAdd++] = 1.0; } addCost[numberArtificials] = penalty; numberArtificials++; addStarts[numberArtificials] = numberAdd; } } if (numberArtificials) { // need copy so as not to disturb original model2 = new ClpSimplex(*model2); if (network) { // network - add a null row model2->addRow(0, NULL, NULL, -COIN_DBL_MAX, COIN_DBL_MAX); numberRows++; } model2->addColumns(numberArtificials, NULL, NULL, addCost, addStarts, addRow, addElement); } delete [] addStarts; delete [] addRow; delete [] addElement; delete [] addCost; // look at rhs to see if to perturb double largest = 0.0; double smallest = 1.0e30; for (iRow = 0; iRow < numberRows; iRow++) { double value; value = fabs(model2->rowLower_[iRow]); if (value && value < 1.0e30) { largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } value = fabs(model2->rowUpper_[iRow]); if (value && value < 1.0e30) { largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } double * saveLower = NULL; double * saveUpper = NULL; if (largest < 2.01 * smallest) { // perturb - so switch off standard model2->setPerturbation(100); saveLower = new double[numberRows]; CoinMemcpyN(model2->rowLower_, numberRows, saveLower); saveUpper = new double[numberRows]; CoinMemcpyN(model2->rowUpper_, numberRows, saveUpper); double * lower = model2->rowLower(); double * upper = model2->rowUpper(); for (iRow = 0; iRow < numberRows; iRow++) { double lowerValue = lower[iRow], upperValue = upper[iRow]; double value = randomNumberGenerator_.randomDouble(); if (upperValue > lowerValue + primalTolerance_) { if (lowerValue > -1.0e20 && lowerValue) lowerValue -= value * 1.0e-4 * fabs(lowerValue); if (upperValue < 1.0e20 && upperValue) upperValue += value * 1.0e-4 * fabs(upperValue); } else if (upperValue > 0.0) { upperValue -= value * 1.0e-4 * fabs(lowerValue); lowerValue -= value * 1.0e-4 * fabs(lowerValue); } else if (upperValue < 0.0) { upperValue += value * 1.0e-4 * fabs(lowerValue); lowerValue += value * 1.0e-4 * fabs(lowerValue); } else { } lower[iRow] = lowerValue; upper[iRow] = upperValue; } } int i; // Just do this number of passes in Sprint if (doSprint > 0) maxSprintPass = options.getExtraInfo(1); // but if big use to get ratio double ratio = 3; if (maxSprintPass > 1000) { ratio = static_cast (maxSprintPass) * 0.0001; ratio = CoinMax(ratio, 1.1); maxSprintPass = maxSprintPass % 1000; #ifdef COIN_DEVELOP printf("%d passes wanted with ratio of %g\n", maxSprintPass, ratio); #endif } // Just take this number of columns in small problem int smallNumberColumns = static_cast (CoinMin(ratio * numberRows, static_cast (numberColumns))); smallNumberColumns = CoinMax(smallNumberColumns, 3000); smallNumberColumns = CoinMin(smallNumberColumns, numberColumns); //int smallNumberColumns = CoinMin(12*numberRows/10,numberColumns); //smallNumberColumns = CoinMax(smallNumberColumns,3000); //smallNumberColumns = CoinMax(smallNumberColumns,numberRows+1000); // redo as may have changed columnLower = model2->columnLower(); columnUpper = model2->columnUpper(); columnSolution = model2->primalColumnSolution(); // Set up initial list numberSort = 0; if (numberArtificials) { numberSort = numberArtificials; for (i = 0; i < numberSort; i++) sort[i] = i + originalNumberColumns; } // maybe a solution there already for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { if (model2->getColumnStatus(iColumn) == basic) sort[numberSort++] = iColumn; } for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) { if (model2->getColumnStatus(iColumn) != basic) { if (columnSolution[iColumn] > columnLower[iColumn] && columnSolution[iColumn] < columnUpper[iColumn] && columnSolution[iColumn]) sort[numberSort++] = iColumn; } } numberSort = CoinMin(numberSort, smallNumberColumns); int numberColumns = model2->numberColumns(); double * fullSolution = model2->primalColumnSolution(); int iPass; double lastObjective[] = {1.0e31,1.0e31}; // It will be safe to allow dense model2->setInitialDenseFactorization(true); // We will be using all rows int * whichRows = new int [numberRows]; for (iRow = 0; iRow < numberRows; iRow++) whichRows[iRow] = iRow; double originalOffset; model2->getDblParam(ClpObjOffset, originalOffset); int totalIterations = 0; double lastSumArtificials = COIN_DBL_MAX; int originalMaxSprintPass = maxSprintPass; maxSprintPass = 20; // so we do that many if infeasible for (iPass = 0; iPass < maxSprintPass; iPass++) { //printf("Bug until submodel new version\n"); //CoinSort_2(sort,sort+numberSort,weight); // Create small problem ClpSimplex small(model2, numberRows, whichRows, numberSort, sort); small.setPerturbation(model2->perturbation()); small.setInfeasibilityCost(model2->infeasibilityCost()); if (model2->factorizationFrequency() == 200) { // User did not touch preset small.defaultFactorizationFrequency(); } // now see what variables left out do to row solution double * rowSolution = model2->primalRowSolution(); double * sumFixed = new double[numberRows]; CoinZeroN (sumFixed, numberRows); int iRow, iColumn; // zero out ones in small problem for (iColumn = 0; iColumn < numberSort; iColumn++) { int kColumn = sort[iColumn]; fullSolution[kColumn] = 0.0; } // Get objective offset const double * objective = model2->objective(); double offset = 0.0; for (iColumn = 0; iColumn < originalNumberColumns; iColumn++) offset += fullSolution[iColumn] * objective[iColumn]; #if 0 // Set artificials to zero if first time close to zero for (iColumn = originalNumberColumns; iColumn < numberColumns; iColumn++) { if (fullSolution[iColumn]objective()[iColumn]=2.0*penalty; fullSolution[iColumn]=0.0; } } #endif small.setDblParam(ClpObjOffset, originalOffset - offset); model2->clpMatrix()->times(1.0, fullSolution, sumFixed); double * lower = small.rowLower(); double * upper = small.rowUpper(); for (iRow = 0; iRow < numberRows; iRow++) { if (lower[iRow] > -1.0e50) lower[iRow] -= sumFixed[iRow]; if (upper[iRow] < 1.0e50) upper[iRow] -= sumFixed[iRow]; rowSolution[iRow] -= sumFixed[iRow]; } delete [] sumFixed; // Solve if (interrupt) currentModel = &small; small.defaultFactorizationFrequency(); if (dynamic_cast< ClpPackedMatrix*>(matrix_)) { // See if original wanted vector ClpPackedMatrix * clpMatrixO = dynamic_cast< ClpPackedMatrix*>(matrix_); ClpMatrixBase * matrix = small.clpMatrix(); if (dynamic_cast< ClpPackedMatrix*>(matrix) && clpMatrixO->wantsSpecialColumnCopy()) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); small.primal(1); clpMatrix->releaseSpecialColumnCopy(); } else { #if 1 #ifdef ABC_INHERIT //small.writeMps("try.mps"); if (iPass||!numberArtificials) small.dealWithAbc(1,1); else small.dealWithAbc(0,0); #else if (iPass||!numberArtificials) small.primal(1); else small.dual(0); #endif if (small.problemStatus()) small.dual(0); #else int numberColumns = small.numberColumns(); int numberRows = small.numberRows(); // Use dual region double * rhs = small.dualRowSolution(); int * whichRow = new int[3*numberRows]; int * whichColumn = new int[2*numberColumns]; int nBound; ClpSimplex * small2 = ((ClpSimplexOther *) (&small))->crunch(rhs, whichRow, whichColumn, nBound, false, false); if (small2) { #ifdef ABC_INHERIT small2->dealWithAbc(1,1); #else small.primal(1); #endif if (small2->problemStatus() == 0) { small.setProblemStatus(0); ((ClpSimplexOther *) (&small))->afterCrunch(*small2, whichRow, whichColumn, nBound); } else { #ifdef ABC_INHERIT small2->dealWithAbc(1,1); #else small.primal(1); #endif if (small2->problemStatus()) small.primal(1); } delete small2; } else { small.primal(1); } delete [] whichRow; delete [] whichColumn; #endif } } else { small.primal(1); } totalIterations += small.numberIterations(); // move solution back const double * solution = small.primalColumnSolution(); for (iColumn = 0; iColumn < numberSort; iColumn++) { int kColumn = sort[iColumn]; model2->setColumnStatus(kColumn, small.getColumnStatus(iColumn)); fullSolution[kColumn] = solution[iColumn]; } for (iRow = 0; iRow < numberRows; iRow++) model2->setRowStatus(iRow, small.getRowStatus(iRow)); CoinMemcpyN(small.primalRowSolution(), numberRows, model2->primalRowSolution()); double sumArtificials = 0.0; for (i = 0; i < numberArtificials; i++) sumArtificials += fullSolution[i + originalNumberColumns]; if (sumArtificials && iPass > 5 && sumArtificials >= lastSumArtificials) { // increase costs double * cost = model2->objective() + originalNumberColumns; double newCost = CoinMin(1.0e10, cost[0] * 1.5); for (i = 0; i < numberArtificials; i++) cost[i] = newCost; } lastSumArtificials = sumArtificials; // get reduced cost for large problem double * djs = model2->dualColumnSolution(); CoinMemcpyN(model2->objective(), numberColumns, djs); model2->clpMatrix()->transposeTimes(-1.0, small.dualRowSolution(), djs); int numberNegative = 0; double sumNegative = 0.0; // now massage weight so all basic in plus good djs // first count and do basic numberSort = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = djs[iColumn] * optimizationDirection_; double value = fullSolution[iColumn]; if (model2->getColumnStatus(iColumn) == ClpSimplex::basic) { sort[numberSort++] = iColumn; } else if (dj < -dualTolerance_ && value < columnUpper[iColumn]) { numberNegative++; sumNegative -= dj; } else if (dj > dualTolerance_ && value > columnLower[iColumn]) { numberNegative++; sumNegative += dj; } } handler_->message(CLP_SPRINT, messages_) << iPass + 1 << small.numberIterations() << small.objectiveValue() << sumNegative << numberNegative << CoinMessageEol; if (sumArtificials < 1.0e-8 && originalMaxSprintPass >= 0) { maxSprintPass = iPass + originalMaxSprintPass; originalMaxSprintPass = -1; } if (iPass > 20) sumArtificials = 0.0; if ((small.objectiveValue()*optimizationDirection_ > lastObjective[1] - 1.0e-7 && iPass > 5 && sumArtificials < 1.0e-8) || (!small.numberIterations() && iPass) || iPass == maxSprintPass - 1 || small.status() == 3) { break; // finished } else { lastObjective[1] = lastObjective[0]; lastObjective[0] = small.objectiveValue() * optimizationDirection_; double tolerance; double averageNegDj = sumNegative / static_cast (numberNegative + 1); if (numberNegative + numberSort > smallNumberColumns) tolerance = -dualTolerance_; else tolerance = 10.0 * averageNegDj; int saveN = numberSort; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = djs[iColumn] * optimizationDirection_; double value = fullSolution[iColumn]; if (model2->getColumnStatus(iColumn) != ClpSimplex::basic) { if (dj < -dualTolerance_ && value < columnUpper[iColumn]) dj = dj; else if (dj > dualTolerance_ && value > columnLower[iColumn]) dj = -dj; else if (columnUpper[iColumn] > columnLower[iColumn]) dj = fabs(dj); else dj = 1.0e50; if (dj < tolerance) { weight[numberSort] = dj; sort[numberSort++] = iColumn; } } } // sort CoinSort_2(weight + saveN, weight + numberSort, sort + saveN); numberSort = CoinMin(smallNumberColumns, numberSort); } } if (interrupt) currentModel = model2; for (i = 0; i < numberArtificials; i++) sort[i] = i + originalNumberColumns; model2->deleteColumns(numberArtificials, sort); if (network) { int iRow = numberRows - 1; model2->deleteRows(1, &iRow); } delete [] weight; delete [] sort; delete [] whichRows; if (saveLower) { // unperturb and clean for (iRow = 0; iRow < numberRows; iRow++) { double diffLower = saveLower[iRow] - model2->rowLower_[iRow]; double diffUpper = saveUpper[iRow] - model2->rowUpper_[iRow]; model2->rowLower_[iRow] = saveLower[iRow]; model2->rowUpper_[iRow] = saveUpper[iRow]; if (diffLower) assert (!diffUpper || fabs(diffLower - diffUpper) < 1.0e-5); else diffLower = diffUpper; model2->rowActivity_[iRow] += diffLower; } delete [] saveLower; delete [] saveUpper; } #ifdef ABC_INHERIT model2->dealWithAbc(1,1); #else model2->primal(1); #endif model2->setPerturbation(savePerturbation); if (model2 != originalModel2) { originalModel2->moveInfo(*model2); delete model2; model2 = originalModel2; } time2 = CoinCpuTime(); timeCore = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Sprint" << timeCore << time2 - time1 << CoinMessageEol; timeX = time2; model2->setNumberIterations(model2->numberIterations() + totalIterations); } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) { #ifndef SLIM_CLP //printf("***** experimental pretty crude barrier\n"); //#define SAVEIT 2 #ifndef SAVEIT #define BORROW #endif #ifdef BORROW ClpInterior barrier; barrier.borrowModel(*model2); #else ClpInterior barrier(*model2); #endif if (interrupt) currentModel2 = &barrier; if (barrier.numberRows()+barrier.numberColumns()>10000) barrier.setMaximumBarrierIterations(1000); int barrierOptions = options.getSpecialOption(4); int aggressiveGamma = 0; bool presolveInCrossover = false; bool scale = false; bool doKKT = false; bool forceFixing = false; int speed = 0; if (barrierOptions & 16) { barrierOptions &= ~16; doKKT = true; } if (barrierOptions&(32 + 64 + 128)) { aggressiveGamma = (barrierOptions & (32 + 64 + 128)) >> 5; barrierOptions &= ~(32 + 64 + 128); } if (barrierOptions & 256) { barrierOptions &= ~256; presolveInCrossover = true; } if (barrierOptions & 512) { barrierOptions &= ~512; forceFixing = true; } if (barrierOptions & 1024) { barrierOptions &= ~1024; barrier.setProjectionTolerance(1.0e-9); } if (barrierOptions&(2048 | 4096)) { speed = (barrierOptions & (2048 | 4096)) >> 11; barrierOptions &= ~(2048 | 4096); } if (barrierOptions & 8) { barrierOptions &= ~8; scale = true; } // If quadratic force KKT if (quadraticObj) { doKKT = true; } switch (barrierOptions) { case 0: default: if (!doKKT) { ClpCholeskyBase * cholesky = new ClpCholeskyBase(options.getExtraInfo(1)); cholesky->setIntegerParameter(0, speed); barrier.setCholesky(cholesky); } else { ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } break; case 1: if (!doKKT) { ClpCholeskyDense * cholesky = new ClpCholeskyDense(); barrier.setCholesky(cholesky); } else { ClpCholeskyDense * cholesky = new ClpCholeskyDense(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } break; #ifdef COIN_HAS_WSMP case 2: { ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(CoinMax(100, model2->numberRows() / 10)); barrier.setCholesky(cholesky); assert (!doKKT); } break; case 3: if (!doKKT) { ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(); barrier.setCholesky(cholesky); } else { ClpCholeskyWssmpKKT * cholesky = new ClpCholeskyWssmpKKT(CoinMax(100, model2->numberRows() / 10)); barrier.setCholesky(cholesky); } break; #endif #ifdef UFL_BARRIER case 4: if (!doKKT) { ClpCholeskyUfl * cholesky = new ClpCholeskyUfl(); barrier.setCholesky(cholesky); } else { ClpCholeskyUfl * cholesky = new ClpCholeskyUfl(); cholesky->setKKT(true); barrier.setCholesky(cholesky); } break; #endif #ifdef TAUCS_BARRIER case 5: { ClpCholeskyTaucs * cholesky = new ClpCholeskyTaucs(); barrier.setCholesky(cholesky); assert (!doKKT); } break; #endif #ifdef COIN_HAS_MUMPS case 6: { ClpCholeskyMumps * cholesky = new ClpCholeskyMumps(); barrier.setCholesky(cholesky); assert (!doKKT); } break; #endif } int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); int saveMaxIts = model2->maximumIterations(); if (saveMaxIts < 1000) { barrier.setMaximumBarrierIterations(saveMaxIts); model2->setMaximumIterations(10000000); } #ifndef SAVEIT //barrier.setDiagonalPerturbation(1.0e-25); if (aggressiveGamma) { switch (aggressiveGamma) { case 1: barrier.setGamma(1.0e-5); barrier.setDelta(1.0e-5); break; case 2: barrier.setGamma(1.0e-7); break; case 3: barrier.setDelta(1.0e-5); break; case 4: barrier.setGamma(1.0e-3); barrier.setDelta(1.0e-3); break; case 5: barrier.setGamma(1.0e-3); break; case 6: barrier.setDelta(1.0e-3); break; } } if (scale) barrier.scaling(1); else barrier.scaling(0); barrier.primalDual(); #elif SAVEIT==1 barrier.primalDual(); #else model2->restoreModel("xx.save"); // move solutions CoinMemcpyN(model2->primalRowSolution(), numberRows, barrier.primalRowSolution()); CoinMemcpyN(model2->dualRowSolution(), numberRows, barrier.dualRowSolution()); CoinMemcpyN(model2->primalColumnSolution(), numberColumns, barrier.primalColumnSolution()); CoinMemcpyN(model2->dualColumnSolution(), numberColumns, barrier.dualColumnSolution()); #endif time2 = CoinCpuTime(); timeCore = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Barrier" << timeCore << time2 - time1 << CoinMessageEol; timeX = time2; int maxIts = barrier.maximumBarrierIterations(); int barrierStatus = barrier.status(); double gap = barrier.complementarityGap(); // get which variables are fixed double * saveLower = NULL; double * saveUpper = NULL; ClpPresolve pinfo2; ClpSimplex * saveModel2 = NULL; bool extraPresolve = false; int numberFixed = barrier.numberFixed(); if (numberFixed) { int numberRows = barrier.numberRows(); int numberColumns = barrier.numberColumns(); int numberTotal = numberRows + numberColumns; saveLower = new double [numberTotal]; saveUpper = new double [numberTotal]; CoinMemcpyN(barrier.columnLower(), numberColumns, saveLower); CoinMemcpyN(barrier.rowLower(), numberRows, saveLower + numberColumns); CoinMemcpyN(barrier.columnUpper(), numberColumns, saveUpper); CoinMemcpyN(barrier.rowUpper(), numberRows, saveUpper + numberColumns); } if (((numberFixed * 20 > barrier.numberRows() && numberFixed > 5000) || forceFixing) && presolveInCrossover) { // may as well do presolve if (!forceFixing) { barrier.fixFixed(); } else { // Fix int n = barrier.numberColumns(); double * lower = barrier.columnLower(); double * upper = barrier.columnUpper(); double * solution = barrier.primalColumnSolution(); int nFix = 0; for (int i = 0; i < n; i++) { if (barrier.fixedOrFree(i) && lower[i] < upper[i]) { double value = solution[i]; if (value < lower[i] + 1.0e-6 && value - lower[i] < upper[i] - value) { solution[i] = lower[i]; upper[i] = lower[i]; nFix++; } else if (value > upper[i] - 1.0e-6 && value - lower[i] > upper[i] - value) { solution[i] = upper[i]; lower[i] = upper[i]; nFix++; } } } #ifdef CLP_INVESTIGATE printf("%d columns fixed\n", nFix); #endif int nr = barrier.numberRows(); lower = barrier.rowLower(); upper = barrier.rowUpper(); solution = barrier.primalRowSolution(); nFix = 0; for (int i = 0; i < nr; i++) { if (barrier.fixedOrFree(i + n) && lower[i] < upper[i]) { double value = solution[i]; if (value < lower[i] + 1.0e-6 && value - lower[i] < upper[i] - value) { solution[i] = lower[i]; upper[i] = lower[i]; nFix++; } else if (value > upper[i] - 1.0e-6 && value - lower[i] > upper[i] - value) { solution[i] = upper[i]; lower[i] = upper[i]; nFix++; } } } #ifdef CLP_INVESTIGATE printf("%d row slacks fixed\n", nFix); #endif } saveModel2 = model2; extraPresolve = true; } else if (numberFixed) { // Set fixed to bounds (may have restored earlier solution) if (!forceFixing) { barrier.fixFixed(false); } else { // Fix int n = barrier.numberColumns(); double * lower = barrier.columnLower(); double * upper = barrier.columnUpper(); double * solution = barrier.primalColumnSolution(); int nFix = 0; for (int i = 0; i < n; i++) { if (barrier.fixedOrFree(i) && lower[i] < upper[i]) { double value = solution[i]; if (value < lower[i] + 1.0e-8 && value - lower[i] < upper[i] - value) { solution[i] = lower[i]; upper[i] = lower[i]; nFix++; } else if (value > upper[i] - 1.0e-8 && value - lower[i] > upper[i] - value) { solution[i] = upper[i]; lower[i] = upper[i]; nFix++; } else { //printf("fixcol %d %g <= %g <= %g\n", // i,lower[i],solution[i],upper[i]); } } } #ifdef CLP_INVESTIGATE printf("%d columns fixed\n", nFix); #endif int nr = barrier.numberRows(); lower = barrier.rowLower(); upper = barrier.rowUpper(); solution = barrier.primalRowSolution(); nFix = 0; for (int i = 0; i < nr; i++) { if (barrier.fixedOrFree(i + n) && lower[i] < upper[i]) { double value = solution[i]; if (value < lower[i] + 1.0e-5 && value - lower[i] < upper[i] - value) { solution[i] = lower[i]; upper[i] = lower[i]; nFix++; } else if (value > upper[i] - 1.0e-5 && value - lower[i] > upper[i] - value) { solution[i] = upper[i]; lower[i] = upper[i]; nFix++; } else { //printf("fixrow %d %g <= %g <= %g\n", // i,lower[i],solution[i],upper[i]); } } } #ifdef CLP_INVESTIGATE printf("%d row slacks fixed\n", nFix); #endif } } #ifdef BORROW int saveNumberIterations = barrier.numberIterations(); barrier.returnModel(*model2); double * rowPrimal = new double [numberRows]; double * columnPrimal = new double [numberColumns]; double * rowDual = new double [numberRows]; double * columnDual = new double [numberColumns]; // move solutions other way CoinMemcpyN(model2->primalRowSolution(), numberRows, rowPrimal); CoinMemcpyN(model2->dualRowSolution(), numberRows, rowDual); CoinMemcpyN(model2->primalColumnSolution(), numberColumns, columnPrimal); CoinMemcpyN(model2->dualColumnSolution(), numberColumns, columnDual); #else double * rowPrimal = barrier.primalRowSolution(); double * columnPrimal = barrier.primalColumnSolution(); double * rowDual = barrier.dualRowSolution(); double * columnDual = barrier.dualColumnSolution(); // move solutions CoinMemcpyN(rowPrimal, numberRows, model2->primalRowSolution()); CoinMemcpyN(rowDual, numberRows, model2->dualRowSolution()); CoinMemcpyN(columnPrimal, numberColumns, model2->primalColumnSolution()); CoinMemcpyN(columnDual, numberColumns, model2->dualColumnSolution()); #endif if (saveModel2) { // do presolve model2 = pinfo2.presolvedModel(*model2, dblParam_[ClpPresolveTolerance], false, 5, true); if (!model2) { model2 = saveModel2; saveModel2 = NULL; int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); CoinMemcpyN(saveLower, numberColumns, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower()); delete [] saveLower; CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper()); delete [] saveUpper; saveLower = NULL; saveUpper = NULL; } } if (method == ClpSolve::useBarrier || barrierStatus < 0) { if (maxIts && barrierStatus < 4 && !quadraticObj) { //printf("***** crossover - needs more thought on difficult models\n"); #if SAVEIT==1 model2->ClpSimplex::saveModel("xx.save"); #endif // make sure no status left model2->createStatus(); // solve if (!forceFixing) model2->setPerturbation(100); if (model2->factorizationFrequency() == 200) { // User did not touch preset model2->defaultFactorizationFrequency(); } #if 1 //ndef ABC_INHERIT //#if 1 // throw some into basis if(!forceFixing) { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); double * dsort = new double[numberColumns]; int * sort = new int[numberColumns]; int n = 0; const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); double * primalSolution = model2->primalColumnSolution(); const double * dualSolution = model2->dualColumnSolution(); double tolerance = 10.0 * primalTolerance_; int i; for ( i = 0; i < numberRows; i++) model2->setRowStatus(i, superBasic); for ( i = 0; i < numberColumns; i++) { double distance = CoinMin(columnUpper[i] - primalSolution[i], primalSolution[i] - columnLower[i]); if (distance > tolerance) { if (fabs(dualSolution[i]) < 1.0e-5) distance *= 100.0; dsort[n] = -distance; sort[n++] = i; model2->setStatus(i, superBasic); } else if (distance > primalTolerance_) { model2->setStatus(i, superBasic); } else if (primalSolution[i] <= columnLower[i] + primalTolerance_) { model2->setStatus(i, atLowerBound); primalSolution[i] = columnLower[i]; } else { model2->setStatus(i, atUpperBound); primalSolution[i] = columnUpper[i]; } } CoinSort_2(dsort, dsort + n, sort); n = CoinMin(numberRows, n); for ( i = 0; i < n; i++) { int iColumn = sort[i]; model2->setStatus(iColumn, basic); } delete [] sort; delete [] dsort; // model2->allSlackBasis(); if (gap < 1.0e-3 * static_cast (numberRows + numberColumns)) { if (saveUpper) { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); CoinMemcpyN(saveLower, numberColumns, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower()); CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper()); delete [] saveLower; delete [] saveUpper; saveLower = NULL; saveUpper = NULL; } int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); #ifdef ABC_INHERIT model2->checkSolution(0); printf("%d primal infeasibilities summing to %g\n", model2->numberPrimalInfeasibilities(), model2->sumPrimalInfeasibilities()); model2->dealWithAbc(1,1); } } #else // just primal values pass double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); // save primal solution and copy back dual CoinMemcpyN(model2->primalRowSolution(), numberRows, rowPrimal); CoinMemcpyN(rowDual, numberRows, model2->dualRowSolution()); CoinMemcpyN(model2->primalColumnSolution(), numberColumns, columnPrimal); CoinMemcpyN(columnDual, numberColumns, model2->dualColumnSolution()); //model2->primal(1); // clean up reduced costs and flag variables { double * dj = model2->dualColumnSolution(); double * cost = model2->objective(); double * saveCost = new double[numberColumns]; CoinMemcpyN(cost, numberColumns, saveCost); double * saveLower = new double[numberColumns]; double * lower = model2->columnLower(); CoinMemcpyN(lower, numberColumns, saveLower); double * saveUpper = new double[numberColumns]; double * upper = model2->columnUpper(); CoinMemcpyN(upper, numberColumns, saveUpper); int i; double tolerance = 10.0 * dualTolerance_; for ( i = 0; i < numberColumns; i++) { if (model2->getStatus(i) == basic) { dj[i] = 0.0; } else if (model2->getStatus(i) == atLowerBound) { if (optimizationDirection_ * dj[i] < tolerance) { if (optimizationDirection_ * dj[i] < 0.0) { //if (dj[i]<-1.0e-3) //printf("bad dj at lb %d %g\n",i,dj[i]); cost[i] -= dj[i]; dj[i] = 0.0; } } else { upper[i] = lower[i]; } } else if (model2->getStatus(i) == atUpperBound) { if (optimizationDirection_ * dj[i] > tolerance) { if (optimizationDirection_ * dj[i] > 0.0) { //if (dj[i]>1.0e-3) //printf("bad dj at ub %d %g\n",i,dj[i]); cost[i] -= dj[i]; dj[i] = 0.0; } } else { lower[i] = upper[i]; } } } // just dual values pass //model2->setLogLevel(63); //model2->setFactorizationFrequency(1); model2->dual(2); CoinMemcpyN(saveCost, numberColumns, cost); delete [] saveCost; CoinMemcpyN(saveLower, numberColumns, lower); delete [] saveLower; CoinMemcpyN(saveUpper, numberColumns, upper); delete [] saveUpper; } } // and finish // move solutions CoinMemcpyN(rowPrimal, numberRows, model2->primalRowSolution()); CoinMemcpyN(columnPrimal, numberColumns, model2->primalColumnSolution()); } double saveScale = model2->objectiveScale(); model2->setObjectiveScale(1.0e-3); model2->primal(2); model2->setObjectiveScale(saveScale); model2->primal(1); #endif #else // just primal #ifdef ABC_INHERIT model2->checkSolution(0); printf("%d primal infeasibilities summing to %g\n", model2->numberPrimalInfeasibilities(), model2->sumPrimalInfeasibilities()); model2->dealWithAbc(1,1); #else model2->primal(1); #endif //model2->primal(1); #endif } else if (barrierStatus == 4) { // memory problems model2->setPerturbation(savePerturbation); model2->createStatus(); model2->dual(); } else if (maxIts && quadraticObj) { // make sure no status left model2->createStatus(); // solve model2->setPerturbation(100); model2->reducedGradient(1); } } //model2->setMaximumIterations(saveMaxIts); #ifdef BORROW model2->setNumberIterations(model2->numberIterations()+saveNumberIterations); delete [] rowPrimal; delete [] columnPrimal; delete [] rowDual; delete [] columnDual; #endif if (extraPresolve) { pinfo2.postsolve(true); delete model2; model2 = saveModel2; } if (saveUpper) { if (!forceFixing) { int numberRows = model2->numberRows(); int numberColumns = model2->numberColumns(); CoinMemcpyN(saveLower, numberColumns, model2->columnLower()); CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower()); CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper()); CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper()); } delete [] saveLower; delete [] saveUpper; saveLower = NULL; saveUpper = NULL; if (method != ClpSolve::useBarrierNoCross) model2->primal(1); } model2->setPerturbation(savePerturbation); time2 = CoinCpuTime(); timeCore = time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Crossover" << timeCore << time2 - time1 << CoinMessageEol; timeX = time2; #else abort(); #endif } else { assert (method != ClpSolve::automatic); // later time2 = 0.0; } if (saveMatrix) { if (model2 == this) { // delete and replace delete model2->clpMatrix(); model2->replaceMatrix(saveMatrix); } else { delete saveMatrix; } } numberIterations = model2->numberIterations(); finalStatus = model2->status(); int finalSecondaryStatus = model2->secondaryStatus(); if (presolve == ClpSolve::presolveOn) { int saveLevel = logLevel(); if ((specialOptions_ & 1024) == 0) setLogLevel(CoinMin(1, saveLevel)); else setLogLevel(CoinMin(0, saveLevel)); pinfo->postsolve(true); numberIterations_ = 0; delete pinfo; pinfo = NULL; factorization_->areaFactor(model2->factorization()->adjustedAreaFactor()); time2 = CoinCpuTime(); timePresolve += time2 - timeX; handler_->message(CLP_INTERVAL_TIMING, messages_) << "Postsolve" << time2 - timeX << time2 - time1 << CoinMessageEol; timeX = time2; if (!presolveToFile) { #if 1 //ndef ABC_INHERIT delete model2; #else if (model2->abcSimplex()) delete model2->abcSimplex(); else delete model2; #endif } if (interrupt) currentModel = this; // checkSolution(); already done by postSolve setLogLevel(saveLevel); int oldStatus=problemStatus_; setProblemStatus(finalStatus); setSecondaryStatus(finalSecondaryStatus); int rcode=eventHandler()->event(ClpEventHandler::presolveAfterFirstSolve); if (finalStatus != 3 && rcode < 0 && (finalStatus || oldStatus == -1)) { int savePerturbation = perturbation(); if (!finalStatus || (moreSpecialOptions_ & 2) == 0 || fabs(sumDualInfeasibilities_)+ fabs(sumPrimalInfeasibilities_)<1.0e-3) { if (finalStatus == 2) { // unbounded - get feasible first double save = optimizationDirection_; optimizationDirection_ = 0.0; primal(1); optimizationDirection_ = save; primal(1); } else if (finalStatus == 1) { dual(); } else { if ((moreSpecialOptions_&65536)==0) { if (numberRows_<10000) setPerturbation(100); // probably better to perturb after n its else if (savePerturbation<100) setPerturbation(51); // probably better to perturb after n its } #ifndef ABC_INHERIT primal(1); #else dealWithAbc(1,2,interrupt); #endif } } else { // just set status problemStatus_ = finalStatus; } setPerturbation(savePerturbation); numberIterations += numberIterations_; numberIterations_ = numberIterations; finalStatus = status(); time2 = CoinCpuTime(); handler_->message(CLP_INTERVAL_TIMING, messages_) << "Cleanup" << time2 - timeX << time2 - time1 << CoinMessageEol; timeX = time2; } else if (rcode >= 0) { #ifdef ABC_INHERIT dealWithAbc(1,2,true); #else primal(1); #endif } else { secondaryStatus_ = finalSecondaryStatus; } } else if (model2 != this) { // not presolved - but different model used (sprint probably) CoinMemcpyN(model2->primalRowSolution(), numberRows_, this->primalRowSolution()); CoinMemcpyN(model2->dualRowSolution(), numberRows_, this->dualRowSolution()); CoinMemcpyN(model2->primalColumnSolution(), numberColumns_, this->primalColumnSolution()); CoinMemcpyN(model2->dualColumnSolution(), numberColumns_, this->dualColumnSolution()); CoinMemcpyN(model2->statusArray(), numberColumns_ + numberRows_, this->statusArray()); objectiveValue_ = model2->objectiveValue_; numberIterations_ = model2->numberIterations_; problemStatus_ = model2->problemStatus_; secondaryStatus_ = model2->secondaryStatus_; delete model2; } if (method != ClpSolve::useBarrierNoCross && method != ClpSolve::useBarrier) setMaximumIterations(saveMaxIterations); std::string statusMessage[] = {"Unknown", "Optimal", "PrimalInfeasible", "DualInfeasible", "Stopped", "Errors", "User stopped" }; assert (finalStatus >= -1 && finalStatus <= 5); numberIterations_ = numberIterations; handler_->message(CLP_TIMING, messages_) << statusMessage[finalStatus+1] << objectiveValue() << numberIterations << time2 - time1; handler_->printing(presolve == ClpSolve::presolveOn) << timePresolve; handler_->printing(timeIdiot != 0.0) << timeIdiot; handler_->message() << CoinMessageEol; if (interrupt) signal(SIGINT, saveSignal); perturbation_ = savePerturbation; scalingFlag_ = saveScaling; // If faking objective - put back correct one if (savedObjective) { delete objective_; objective_ = savedObjective; } if (options.getSpecialOption(1) == 2 && options.getExtraInfo(1) > 1000000) { ClpObjective * savedObjective = objective_; // make up zero objective double * obj = new double[numberColumns_]; for (int i = 0; i < numberColumns_; i++) obj[i] = 0.0; objective_ = new ClpLinearObjective(obj, numberColumns_); delete [] obj; primal(1); delete objective_; objective_ = savedObjective; finalStatus = status(); } eventHandler()->event(ClpEventHandler::presolveEnd); delete pinfo; return finalStatus; } // General solve int ClpSimplex::initialSolve() { // Default so use dual ClpSolve options; return initialSolve(options); } // General dual solve int ClpSimplex::initialDualSolve() { ClpSolve options; // Use dual options.setSolveType(ClpSolve::useDual); return initialSolve(options); } // General primal solve int ClpSimplex::initialPrimalSolve() { ClpSolve options; // Use primal options.setSolveType(ClpSolve::usePrimal); return initialSolve(options); } // barrier solve, not to be followed by crossover int ClpSimplex::initialBarrierNoCrossSolve() { ClpSolve options; // Use primal options.setSolveType(ClpSolve::useBarrierNoCross); return initialSolve(options); } // General barrier solve int ClpSimplex::initialBarrierSolve() { ClpSolve options; // Use primal options.setSolveType(ClpSolve::useBarrier); return initialSolve(options); } // Default constructor ClpSolve::ClpSolve ( ) { method_ = automatic; presolveType_ = presolveOn; numberPasses_ = 5; int i; for (i = 0; i < 7; i++) options_[i] = 0; // say no +-1 matrix options_[3] = 1; for (i = 0; i < 7; i++) extraInfo_[i] = -1; independentOptions_[0] = 0; // But switch off slacks independentOptions_[1] = 512; // Substitute up to 3 independentOptions_[2] = 3; } // Constructor when you really know what you are doing ClpSolve::ClpSolve ( SolveType method, PresolveType presolveType, int numberPasses, int options[6], int extraInfo[6], int independentOptions[3]) { method_ = method; presolveType_ = presolveType; numberPasses_ = numberPasses; int i; for (i = 0; i < 6; i++) options_[i] = options[i]; options_[6] = 0; for (i = 0; i < 6; i++) extraInfo_[i] = extraInfo[i]; extraInfo_[6] = 0; for (i = 0; i < 3; i++) independentOptions_[i] = independentOptions[i]; } // Copy constructor. ClpSolve::ClpSolve(const ClpSolve & rhs) { method_ = rhs.method_; presolveType_ = rhs.presolveType_; numberPasses_ = rhs.numberPasses_; int i; for ( i = 0; i < 7; i++) options_[i] = rhs.options_[i]; for ( i = 0; i < 7; i++) extraInfo_[i] = rhs.extraInfo_[i]; for (i = 0; i < 3; i++) independentOptions_[i] = rhs.independentOptions_[i]; } // Assignment operator. This copies the data ClpSolve & ClpSolve::operator=(const ClpSolve & rhs) { if (this != &rhs) { method_ = rhs.method_; presolveType_ = rhs.presolveType_; numberPasses_ = rhs.numberPasses_; int i; for (i = 0; i < 7; i++) options_[i] = rhs.options_[i]; for (i = 0; i < 7; i++) extraInfo_[i] = rhs.extraInfo_[i]; for (i = 0; i < 3; i++) independentOptions_[i] = rhs.independentOptions_[i]; } return *this; } // Destructor ClpSolve::~ClpSolve ( ) { } // See header file for details void ClpSolve::setSpecialOption(int which, int value, int extraInfo) { options_[which] = value; extraInfo_[which] = extraInfo; } int ClpSolve::getSpecialOption(int which) const { return options_[which]; } // Solve types void ClpSolve::setSolveType(SolveType method, int /*extraInfo*/) { method_ = method; } ClpSolve::SolveType ClpSolve::getSolveType() { return method_; } // Presolve types void ClpSolve::setPresolveType(PresolveType amount, int extraInfo) { presolveType_ = amount; numberPasses_ = extraInfo; } ClpSolve::PresolveType ClpSolve::getPresolveType() { return presolveType_; } // Extra info for idiot (or sprint) int ClpSolve::getExtraInfo(int which) const { return extraInfo_[which]; } int ClpSolve::getPresolvePasses() const { return numberPasses_; } /* Say to return at once if infeasible, default is to solve */ void ClpSolve::setInfeasibleReturn(bool trueFalse) { independentOptions_[0] = trueFalse ? 1 : 0; } #include // Generates code for above constructor void ClpSolve::generateCpp(FILE * fp) { std::string solveType[] = { "ClpSolve::useDual", "ClpSolve::usePrimal", "ClpSolve::usePrimalorSprint", "ClpSolve::useBarrier", "ClpSolve::useBarrierNoCross", "ClpSolve::automatic", "ClpSolve::notImplemented" }; std::string presolveType[] = { "ClpSolve::presolveOn", "ClpSolve::presolveOff", "ClpSolve::presolveNumber", "ClpSolve::presolveNumberCost" }; fprintf(fp, "3 ClpSolve::SolveType method = %s;\n", solveType[method_].c_str()); fprintf(fp, "3 ClpSolve::PresolveType presolveType = %s;\n", presolveType[presolveType_].c_str()); fprintf(fp, "3 int numberPasses = %d;\n", numberPasses_); fprintf(fp, "3 int options[] = {%d,%d,%d,%d,%d,%d};\n", options_[0], options_[1], options_[2], options_[3], options_[4], options_[5]); fprintf(fp, "3 int extraInfo[] = {%d,%d,%d,%d,%d,%d};\n", extraInfo_[0], extraInfo_[1], extraInfo_[2], extraInfo_[3], extraInfo_[4], extraInfo_[5]); fprintf(fp, "3 int independentOptions[] = {%d,%d,%d};\n", independentOptions_[0], independentOptions_[1], independentOptions_[2]); fprintf(fp, "3 ClpSolve clpSolve(method,presolveType,numberPasses,\n"); fprintf(fp, "3 options,extraInfo,independentOptions);\n"); } //############################################################################# #include "ClpNonLinearCost.hpp" ClpSimplexProgress::ClpSimplexProgress () { int i; for (i = 0; i < CLP_PROGRESS; i++) { objective_[i] = COIN_DBL_MAX; infeasibility_[i] = -1.0; // set to an impossible value realInfeasibility_[i] = COIN_DBL_MAX; numberInfeasibilities_[i] = -1; iterationNumber_[i] = -1; } #ifdef CLP_PROGRESS_WEIGHT for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) { objectiveWeight_[i] = COIN_DBL_MAX; infeasibilityWeight_[i] = -1.0; // set to an impossible value realInfeasibilityWeight_[i] = COIN_DBL_MAX; numberInfeasibilitiesWeight_[i] = -1; iterationNumberWeight_[i] = -1; } drop_ = 0.0; best_ = 0.0; #endif initialWeight_ = 0.0; for (i = 0; i < CLP_CYCLE; i++) { //obj_[i]=COIN_DBL_MAX; in_[i] = -1; out_[i] = -1; way_[i] = 0; } numberTimes_ = 0; numberBadTimes_ = 0; numberReallyBadTimes_ = 0; numberTimesFlagged_ = 0; model_ = NULL; oddState_ = 0; } //----------------------------------------------------------------------------- ClpSimplexProgress::~ClpSimplexProgress () { } // Copy constructor. ClpSimplexProgress::ClpSimplexProgress(const ClpSimplexProgress &rhs) { int i; for (i = 0; i < CLP_PROGRESS; i++) { objective_[i] = rhs.objective_[i]; infeasibility_[i] = rhs.infeasibility_[i]; realInfeasibility_[i] = rhs.realInfeasibility_[i]; numberInfeasibilities_[i] = rhs.numberInfeasibilities_[i]; iterationNumber_[i] = rhs.iterationNumber_[i]; } #ifdef CLP_PROGRESS_WEIGHT for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) { objectiveWeight_[i] = rhs.objectiveWeight_[i]; infeasibilityWeight_[i] = rhs.infeasibilityWeight_[i]; realInfeasibilityWeight_[i] = rhs.realInfeasibilityWeight_[i]; numberInfeasibilitiesWeight_[i] = rhs.numberInfeasibilitiesWeight_[i]; iterationNumberWeight_[i] = rhs.iterationNumberWeight_[i]; } drop_ = rhs.drop_; best_ = rhs.best_; #endif initialWeight_ = rhs.initialWeight_; for (i = 0; i < CLP_CYCLE; i++) { //obj_[i]=rhs.obj_[i]; in_[i] = rhs.in_[i]; out_[i] = rhs.out_[i]; way_[i] = rhs.way_[i]; } numberTimes_ = rhs.numberTimes_; numberBadTimes_ = rhs.numberBadTimes_; numberReallyBadTimes_ = rhs.numberReallyBadTimes_; numberTimesFlagged_ = rhs.numberTimesFlagged_; model_ = rhs.model_; oddState_ = rhs.oddState_; } // Copy constructor.from model ClpSimplexProgress::ClpSimplexProgress(ClpSimplex * model) { model_ = model; reset(); initialWeight_ = 0.0; } // Fill from model void ClpSimplexProgress::fillFromModel ( ClpSimplex * model ) { model_ = model; reset(); initialWeight_ = 0.0; } // Assignment operator. This copies the data ClpSimplexProgress & ClpSimplexProgress::operator=(const ClpSimplexProgress & rhs) { if (this != &rhs) { int i; for (i = 0; i < CLP_PROGRESS; i++) { objective_[i] = rhs.objective_[i]; infeasibility_[i] = rhs.infeasibility_[i]; realInfeasibility_[i] = rhs.realInfeasibility_[i]; numberInfeasibilities_[i] = rhs.numberInfeasibilities_[i]; iterationNumber_[i] = rhs.iterationNumber_[i]; } #ifdef CLP_PROGRESS_WEIGHT for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) { objectiveWeight_[i] = rhs.objectiveWeight_[i]; infeasibilityWeight_[i] = rhs.infeasibilityWeight_[i]; realInfeasibilityWeight_[i] = rhs.realInfeasibilityWeight_[i]; numberInfeasibilitiesWeight_[i] = rhs.numberInfeasibilitiesWeight_[i]; iterationNumberWeight_[i] = rhs.iterationNumberWeight_[i]; } drop_ = rhs.drop_; best_ = rhs.best_; #endif initialWeight_ = rhs.initialWeight_; for (i = 0; i < CLP_CYCLE; i++) { //obj_[i]=rhs.obj_[i]; in_[i] = rhs.in_[i]; out_[i] = rhs.out_[i]; way_[i] = rhs.way_[i]; } numberTimes_ = rhs.numberTimes_; numberBadTimes_ = rhs.numberBadTimes_; numberReallyBadTimes_ = rhs.numberReallyBadTimes_; numberTimesFlagged_ = rhs.numberTimesFlagged_; model_ = rhs.model_; oddState_ = rhs.oddState_; } return *this; } // Seems to be something odd about exact comparison of doubles on linux static bool equalDouble(double value1, double value2) { union { double d; int i[2]; } v1, v2; v1.d = value1; v2.d = value2; if (sizeof(int) * 2 == sizeof(double)) return (v1.i[0] == v2.i[0] && v1.i[1] == v2.i[1]); else return (v1.i[0] == v2.i[0]); } int ClpSimplexProgress::looping() { if (!model_) return -1; double objective; if (model_->algorithm() < 0) { objective = model_->rawObjectiveValue(); objective -= model_->bestPossibleImprovement(); } else { objective = model_->nonLinearCost()->feasibleReportCost(); } double infeasibility; double realInfeasibility = 0.0; int numberInfeasibilities; int iterationNumber = model_->numberIterations(); //numberTimesFlagged_ = 0; if (model_->algorithm() < 0) { // dual infeasibility = model_->sumPrimalInfeasibilities(); numberInfeasibilities = model_->numberPrimalInfeasibilities(); } else { //primal infeasibility = model_->sumDualInfeasibilities(); realInfeasibility = model_->nonLinearCost()->sumInfeasibilities(); numberInfeasibilities = model_->numberDualInfeasibilities(); } int i; int numberMatched = 0; int matched = 0; int nsame = 0; for (i = 0; i < CLP_PROGRESS; i++) { bool matchedOnObjective = equalDouble(objective, objective_[i]); bool matchedOnInfeasibility = equalDouble(infeasibility, infeasibility_[i]); bool matchedOnInfeasibilities = (numberInfeasibilities == numberInfeasibilities_[i]); if (matchedOnObjective && matchedOnInfeasibility && matchedOnInfeasibilities) { matched |= (1 << i); // Check not same iteration if (iterationNumber != iterationNumber_[i]) { numberMatched++; // here mainly to get over compiler bug? if (model_->messageHandler()->logLevel() > 10) printf("%d %d %d %d %d loop check\n", i, numberMatched, matchedOnObjective, matchedOnInfeasibility, matchedOnInfeasibilities); } else { // stuck but code should notice nsame++; } } if (i) { objective_[i-1] = objective_[i]; infeasibility_[i-1] = infeasibility_[i]; realInfeasibility_[i-1] = realInfeasibility_[i]; numberInfeasibilities_[i-1] = numberInfeasibilities_[i]; iterationNumber_[i-1] = iterationNumber_[i]; } } objective_[CLP_PROGRESS-1] = objective; infeasibility_[CLP_PROGRESS-1] = infeasibility; realInfeasibility_[CLP_PROGRESS-1] = realInfeasibility; numberInfeasibilities_[CLP_PROGRESS-1] = numberInfeasibilities; iterationNumber_[CLP_PROGRESS-1] = iterationNumber; if (nsame == CLP_PROGRESS) numberMatched = CLP_PROGRESS; // really stuck if (model_->progressFlag()) numberMatched = 0; numberTimes_++; if (numberTimes_ < 10) numberMatched = 0; // skip if just last time as may be checking something if (matched == (1 << (CLP_PROGRESS - 1))) numberMatched = 0; if (numberMatched && model_->clpMatrix()->type() < 15) { model_->messageHandler()->message(CLP_POSSIBLELOOP, model_->messages()) << numberMatched << matched << numberTimes_ << CoinMessageEol; numberBadTimes_++; if (numberBadTimes_ < 10) { // make factorize every iteration model_->forceFactorization(1); if (numberBadTimes_ < 2) { startCheck(); // clear other loop check if (model_->algorithm() < 0) { // dual - change tolerance model_->setCurrentDualTolerance(model_->currentDualTolerance() * 1.05); // if infeasible increase dual bound if (model_->dualBound() < 1.0e17) { model_->setDualBound(model_->dualBound() * 1.1); static_cast(model_)->resetFakeBounds(0); } } else { // primal - change tolerance if (numberBadTimes_ > 3) model_->setCurrentPrimalTolerance(model_->currentPrimalTolerance() * 1.05); // if infeasible increase infeasibility cost if (model_->nonLinearCost()->numberInfeasibilities() && model_->infeasibilityCost() < 1.0e17) { model_->setInfeasibilityCost(model_->infeasibilityCost() * 1.1); } } } else { // flag int iSequence; if (model_->algorithm() < 0) { // dual if (model_->dualBound() > 1.0e14) model_->setDualBound(1.0e14); iSequence = in_[CLP_CYCLE-1]; } else { // primal if (model_->infeasibilityCost() > 1.0e14) model_->setInfeasibilityCost(1.0e14); iSequence = out_[CLP_CYCLE-1]; } if (iSequence >= 0) { char x = model_->isColumn(iSequence) ? 'C' : 'R'; if (model_->messageHandler()->logLevel() >= 63) model_->messageHandler()->message(CLP_SIMPLEX_FLAG, model_->messages()) << x << model_->sequenceWithin(iSequence) << CoinMessageEol; // if Gub then needs to be sequenceIn_ int save = model_->sequenceIn(); model_->setSequenceIn(iSequence); model_->setFlagged(iSequence); model_->setSequenceIn(save); //printf("flagging %d from loop\n",iSequence); startCheck(); } else { // Give up if (model_->messageHandler()->logLevel() >= 63) printf("***** All flagged?\n"); return 4; } // reset numberBadTimes_ = 2; } return -2; } else { // look at solution and maybe declare victory if (infeasibility < 1.0e-4) { return 0; } else { model_->messageHandler()->message(CLP_LOOP, model_->messages()) << CoinMessageEol; #ifndef NDEBUG printf("debug loop ClpSimplex A\n"); abort(); #endif return 3; } } } return -1; } // Resets as much as possible void ClpSimplexProgress::reset() { int i; for (i = 0; i < CLP_PROGRESS; i++) { if (model_->algorithm() >= 0) objective_[i] = COIN_DBL_MAX; else objective_[i] = -COIN_DBL_MAX; infeasibility_[i] = -1.0; // set to an impossible value realInfeasibility_[i] = COIN_DBL_MAX; numberInfeasibilities_[i] = -1; iterationNumber_[i] = -1; } #ifdef CLP_PROGRESS_WEIGHT for (i = 0; i < CLP_PROGRESS_WEIGHT; i++) { objectiveWeight_[i] = COIN_DBL_MAX; infeasibilityWeight_[i] = -1.0; // set to an impossible value realInfeasibilityWeight_[i] = COIN_DBL_MAX; numberInfeasibilitiesWeight_[i] = -1; iterationNumberWeight_[i] = -1; } drop_ = 0.0; best_ = 0.0; #endif for (i = 0; i < CLP_CYCLE; i++) { //obj_[i]=COIN_DBL_MAX; in_[i] = -1; out_[i] = -1; way_[i] = 0; } numberTimes_ = 0; numberBadTimes_ = 0; numberReallyBadTimes_ = 0; numberTimesFlagged_ = 0; oddState_ = 0; } // Returns previous objective (if -1) - current if (0) double ClpSimplexProgress::lastObjective(int back) const { return objective_[CLP_PROGRESS-1-back]; } // Returns previous infeasibility (if -1) - current if (0) double ClpSimplexProgress::lastInfeasibility(int back) const { return realInfeasibility_[CLP_PROGRESS-1-back]; } // Sets real primal infeasibility void ClpSimplexProgress::setInfeasibility(double value) { for (int i = 1; i < CLP_PROGRESS; i++) realInfeasibility_[i-1] = realInfeasibility_[i]; realInfeasibility_[CLP_PROGRESS-1] = value; } // Modify objective e.g. if dual infeasible in dual void ClpSimplexProgress::modifyObjective(double value) { objective_[CLP_PROGRESS-1] = value; } // Returns previous iteration number (if -1) - current if (0) int ClpSimplexProgress::lastIterationNumber(int back) const { return iterationNumber_[CLP_PROGRESS-1-back]; } // clears iteration numbers (to switch off panic) void ClpSimplexProgress::clearIterationNumbers() { for (int i = 0; i < CLP_PROGRESS; i++) iterationNumber_[i] = -1; } // Start check at beginning of whileIterating void ClpSimplexProgress::startCheck() { int i; for (i = 0; i < CLP_CYCLE; i++) { //obj_[i]=COIN_DBL_MAX; in_[i] = -1; out_[i] = -1; way_[i] = 0; } } // Returns cycle length in whileIterating int ClpSimplexProgress::cycle(int in, int out, int wayIn, int wayOut) { int i; #if 0 if (model_->numberIterations() > 206571) { printf("in %d out %d\n", in, out); for (i = 0; i < CLP_CYCLE; i++) printf("cy %d in %d out %d\n", i, in_[i], out_[i]); } #endif int matched = 0; // first see if in matches any out for (i = 1; i < CLP_CYCLE; i++) { if (in == out_[i]) { // even if flip then suspicious matched = -1; break; } } #if 0 if (!matched || in_[0] < 0) { // can't be cycle for (i = 0; i < CLP_CYCLE - 1; i++) { //obj_[i]=obj_[i+1]; in_[i] = in_[i+1]; out_[i] = out_[i+1]; way_[i] = way_[i+1]; } } else { // possible cycle matched = 0; for (i = 0; i < CLP_CYCLE - 1; i++) { int k; char wayThis = way_[i]; int inThis = in_[i]; int outThis = out_[i]; //double objThis = obj_[i]; for(k = i + 1; k < CLP_CYCLE; k++) { if (inThis == in_[k] && outThis == out_[k] && wayThis == way_[k]) { int distance = k - i; if (k + distance < CLP_CYCLE) { // See if repeats int j = k + distance; if (inThis == in_[j] && outThis == out_[j] && wayThis == way_[j]) { matched = distance; break; } } else { matched = distance; break; } } } //obj_[i]=obj_[i+1]; in_[i] = in_[i+1]; out_[i] = out_[i+1]; way_[i] = way_[i+1]; } } #else if (matched && in_[0] >= 0) { // possible cycle - only check [0] against all matched = 0; int nMatched = 0; char way0 = way_[0]; int in0 = in_[0]; int out0 = out_[0]; //double obj0 = obj_[i]; for(int k = 1; k < CLP_CYCLE - 4; k++) { if (in0 == in_[k] && out0 == out_[k] && way0 == way_[k]) { nMatched++; // See if repeats int end = CLP_CYCLE - k; int j; for ( j = 1; j < end; j++) { if (in_[j+k] != in_[j] || out_[j+k] != out_[j] || way_[j+k] != way_[j]) break; } if (j == end) { matched = k; break; } } } // If three times then that is too much even if not regular if (matched <= 0 && nMatched > 1) matched = 100; } for (i = 0; i < CLP_CYCLE - 1; i++) { //obj_[i]=obj_[i+1]; in_[i] = in_[i+1]; out_[i] = out_[i+1]; way_[i] = way_[i+1]; } #endif int way = 1 - wayIn + 4 * (1 - wayOut); //obj_[i]=model_->objectiveValue(); in_[CLP_CYCLE-1] = in; out_[CLP_CYCLE-1] = out; way_[CLP_CYCLE-1] = static_cast(way); return matched; } #include "CoinStructuredModel.hpp" // Solve using structure of model and maybe in parallel int ClpSimplex::solve(CoinStructuredModel * model) { // analyze structure int numberRowBlocks = model->numberRowBlocks(); int numberColumnBlocks = model->numberColumnBlocks(); int numberElementBlocks = model->numberElementBlocks(); if (numberElementBlocks == 1) { loadProblem(*model, false); return dual(); } // For now just get top level structure CoinModelBlockInfo * blockInfo = new CoinModelBlockInfo [numberElementBlocks]; for (int i = 0; i < numberElementBlocks; i++) { CoinStructuredModel * subModel = dynamic_cast(model->block(i)); CoinModel * thisBlock; if (subModel) { thisBlock = subModel->coinModelBlock(blockInfo[i]); model->setCoinModel(thisBlock, i); } else { thisBlock = dynamic_cast(model->block(i)); assert (thisBlock); // just fill in info CoinModelBlockInfo info = CoinModelBlockInfo(); int whatsSet = thisBlock->whatIsSet(); info.matrix = static_cast(((whatsSet & 1) != 0) ? 1 : 0); info.rhs = static_cast(((whatsSet & 2) != 0) ? 1 : 0); info.rowName = static_cast(((whatsSet & 4) != 0) ? 1 : 0); info.integer = static_cast(((whatsSet & 32) != 0) ? 1 : 0); info.bounds = static_cast(((whatsSet & 8) != 0) ? 1 : 0); info.columnName = static_cast(((whatsSet & 16) != 0) ? 1 : 0); // Which block int iRowBlock = model->rowBlock(thisBlock->getRowBlock()); info.rowBlock = iRowBlock; int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock()); info.columnBlock = iColumnBlock; blockInfo[i] = info; } } int * rowCounts = new int [numberRowBlocks]; CoinZeroN(rowCounts, numberRowBlocks); int * columnCounts = new int [numberColumnBlocks+1]; CoinZeroN(columnCounts, numberColumnBlocks); int decomposeType = 0; for (int i = 0; i < numberElementBlocks; i++) { int iRowBlock = blockInfo[i].rowBlock; int iColumnBlock = blockInfo[i].columnBlock; rowCounts[iRowBlock]++; columnCounts[iColumnBlock]++; } if (numberRowBlocks == numberColumnBlocks || numberRowBlocks == numberColumnBlocks + 1) { // could be Dantzig-Wolfe int numberG1 = 0; for (int i = 0; i < numberRowBlocks; i++) { if (rowCounts[i] > 1) numberG1++; } bool masterColumns = (numberColumnBlocks == numberRowBlocks); if ((masterColumns && numberElementBlocks == 2 * numberRowBlocks - 1) || (!masterColumns && numberElementBlocks == 2 * numberRowBlocks)) { if (numberG1 < 2) decomposeType = 1; } } if (!decomposeType && (numberRowBlocks == numberColumnBlocks || numberRowBlocks == numberColumnBlocks - 1)) { // could be Benders int numberG1 = 0; for (int i = 0; i < numberColumnBlocks; i++) { if (columnCounts[i] > 1) numberG1++; } bool masterRows = (numberColumnBlocks == numberRowBlocks); if ((masterRows && numberElementBlocks == 2 * numberColumnBlocks - 1) || (!masterRows && numberElementBlocks == 2 * numberColumnBlocks)) { if (numberG1 < 2) decomposeType = 2; } } delete [] rowCounts; delete [] columnCounts; delete [] blockInfo; // decide what to do switch (decomposeType) { // No good case 0: loadProblem(*model, false); return dual(); // DW case 1: return solveDW(model); // Benders case 2: return solveBenders(model); } return 0; // to stop compiler warning } /* This loads a model from a CoinStructuredModel object - returns number of errors. If originalOrder then keep to order stored in blocks, otherwise first column/rows correspond to first block - etc. If keepSolution true and size is same as current then keeps current status and solution */ int ClpSimplex::loadProblem ( CoinStructuredModel & coinModel, bool originalOrder, bool keepSolution) { unsigned char * status = NULL; double * psol = NULL; double * dsol = NULL; int numberRows = coinModel.numberRows(); int numberColumns = coinModel.numberColumns(); int numberRowBlocks = coinModel.numberRowBlocks(); int numberColumnBlocks = coinModel.numberColumnBlocks(); int numberElementBlocks = coinModel.numberElementBlocks(); if (status_ && numberRows_ && numberRows_ == numberRows && numberColumns_ == numberColumns && keepSolution) { status = new unsigned char [numberRows_+numberColumns_]; CoinMemcpyN(status_, numberRows_ + numberColumns_, status); psol = new double [numberRows_+numberColumns_]; CoinMemcpyN(columnActivity_, numberColumns_, psol); CoinMemcpyN(rowActivity_, numberRows_, psol + numberColumns_); dsol = new double [numberRows_+numberColumns_]; CoinMemcpyN(reducedCost_, numberColumns_, dsol); CoinMemcpyN(dual_, numberRows_, dsol + numberColumns_); } int returnCode = 0; double * rowLower = new double [numberRows]; double * rowUpper = new double [numberRows]; double * columnLower = new double [numberColumns]; double * columnUpper = new double [numberColumns]; double * objective = new double [numberColumns]; int * integerType = new int [numberColumns]; CoinBigIndex numberElements = 0; // Bases for blocks int * rowBase = new int[numberRowBlocks]; CoinFillN(rowBase, numberRowBlocks, -1); // And row to put it int * whichRow = new int [numberRows]; int * columnBase = new int[numberColumnBlocks]; CoinFillN(columnBase, numberColumnBlocks, -1); // And column to put it int * whichColumn = new int [numberColumns]; for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) { CoinModel * block = coinModel.coinBlock(iBlock); numberElements += block->numberElements(); //and set up elements etc double * associated = block->associatedArray(); // If strings then do copies if (block->stringsExist()) returnCode += block->createArrays(rowLower, rowUpper, columnLower, columnUpper, objective, integerType, associated); const CoinModelBlockInfo & info = coinModel.blockType(iBlock); int iRowBlock = info.rowBlock; int iColumnBlock = info.columnBlock; if (rowBase[iRowBlock] < 0) { rowBase[iRowBlock] = block->numberRows(); // Save block number whichRow[numberRows-numberRowBlocks+iRowBlock] = iBlock; } else { assert(rowBase[iRowBlock] == block->numberRows()); } if (columnBase[iColumnBlock] < 0) { columnBase[iColumnBlock] = block->numberColumns(); // Save block number whichColumn[numberColumns-numberColumnBlocks+iColumnBlock] = iBlock; } else { assert(columnBase[iColumnBlock] == block->numberColumns()); } } // Fill arrays with defaults CoinFillN(rowLower, numberRows, -COIN_DBL_MAX); CoinFillN(rowUpper, numberRows, COIN_DBL_MAX); CoinFillN(columnLower, numberColumns, 0.0); CoinFillN(columnUpper, numberColumns, COIN_DBL_MAX); CoinFillN(objective, numberColumns, 0.0); CoinFillN(integerType, numberColumns, 0); int n = 0; for (int iBlock = 0; iBlock < numberRowBlocks; iBlock++) { int k = rowBase[iBlock]; rowBase[iBlock] = n; assert (k >= 0); // block number int jBlock = whichRow[numberRows-numberRowBlocks+iBlock]; if (originalOrder) { memcpy(whichRow + n, coinModel.coinBlock(jBlock)->originalRows(), k * sizeof(int)); } else { CoinIotaN(whichRow + n, k, n); } n += k; } assert (n == numberRows); n = 0; for (int iBlock = 0; iBlock < numberColumnBlocks; iBlock++) { int k = columnBase[iBlock]; columnBase[iBlock] = n; assert (k >= 0); if (k) { // block number int jBlock = whichColumn[numberColumns-numberColumnBlocks+iBlock]; if (originalOrder) { memcpy(whichColumn + n, coinModel.coinBlock(jBlock)->originalColumns(), k * sizeof(int)); } else { CoinIotaN(whichColumn + n, k, n); } n += k; } } assert (n == numberColumns); bool gotIntegers = false; for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) { CoinModel * block = coinModel.coinBlock(iBlock); const CoinModelBlockInfo & info = coinModel.blockType(iBlock); int iRowBlock = info.rowBlock; int iRowBase = rowBase[iRowBlock]; int iColumnBlock = info.columnBlock; int iColumnBase = columnBase[iColumnBlock]; if (info.rhs) { int nRows = block->numberRows(); const double * lower = block->rowLowerArray(); const double * upper = block->rowUpperArray(); for (int i = 0; i < nRows; i++) { int put = whichRow[i+iRowBase]; rowLower[put] = lower[i]; rowUpper[put] = upper[i]; } } if (info.bounds) { int nColumns = block->numberColumns(); const double * lower = block->columnLowerArray(); const double * upper = block->columnUpperArray(); const double * obj = block->objectiveArray(); for (int i = 0; i < nColumns; i++) { int put = whichColumn[i+iColumnBase]; columnLower[put] = lower[i]; columnUpper[put] = upper[i]; objective[put] = obj[i]; } } if (info.integer) { gotIntegers = true; int nColumns = block->numberColumns(); const int * type = block->integerTypeArray(); for (int i = 0; i < nColumns; i++) { int put = whichColumn[i+iColumnBase]; integerType[put] = type[i]; } } } gutsOfLoadModel(numberRows, numberColumns, columnLower, columnUpper, objective, rowLower, rowUpper, NULL); delete [] rowLower; delete [] rowUpper; delete [] columnLower; delete [] columnUpper; delete [] objective; // Do integers if wanted if (gotIntegers) { for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) setInteger(iColumn); } } delete [] integerType; setObjectiveOffset(coinModel.objectiveOffset()); // Space for elements int * row = new int[numberElements]; int * column = new int[numberElements]; double * element = new double[numberElements]; numberElements = 0; for (int iBlock = 0; iBlock < numberElementBlocks; iBlock++) { CoinModel * block = coinModel.coinBlock(iBlock); const CoinModelBlockInfo & info = coinModel.blockType(iBlock); int iRowBlock = info.rowBlock; int iRowBase = rowBase[iRowBlock]; int iColumnBlock = info.columnBlock; int iColumnBase = columnBase[iColumnBlock]; if (info.rowName) { int numberItems = block->rowNames()->numberItems(); assert( block->numberRows() >= numberItems); if (numberItems) { const char *const * rowNames = block->rowNames()->names(); for (int i = 0; i < numberItems; i++) { int put = whichRow[i+iRowBase]; std::string name = rowNames[i]; setRowName(put, name); } } } if (info.columnName) { int numberItems = block->columnNames()->numberItems(); assert( block->numberColumns() >= numberItems); if (numberItems) { const char *const * columnNames = block->columnNames()->names(); for (int i = 0; i < numberItems; i++) { int put = whichColumn[i+iColumnBase]; std::string name = columnNames[i]; setColumnName(put, name); } } } if (info.matrix) { CoinPackedMatrix matrix2; const CoinPackedMatrix * matrix = block->packedMatrix(); if (!matrix) { double * associated = block->associatedArray(); block->createPackedMatrix(matrix2, associated); matrix = &matrix2; } // get matrix data pointers const int * row2 = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); const int * columnLength = matrix->getVectorLengths(); int n = matrix->getNumCols(); assert (matrix->isColOrdered()); for (int iColumn = 0; iColumn < n; iColumn++) { CoinBigIndex j; int jColumn = whichColumn[iColumn+iColumnBase]; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { row[numberElements] = whichRow[row2[j] + iRowBase]; column[numberElements] = jColumn; element[numberElements++] = elementByColumn[j]; } } } } delete [] whichRow; delete [] whichColumn; delete [] rowBase; delete [] columnBase; CoinPackedMatrix * matrix = new CoinPackedMatrix (true, row, column, element, numberElements); matrix_ = new ClpPackedMatrix(matrix); matrix_->setDimensions(numberRows, numberColumns); delete [] row; delete [] column; delete [] element; createStatus(); if (status) { // copy back CoinMemcpyN(status, numberRows_ + numberColumns_, status_); CoinMemcpyN(psol, numberColumns_, columnActivity_); CoinMemcpyN(psol + numberColumns_, numberRows_, rowActivity_); CoinMemcpyN(dsol, numberColumns_, reducedCost_); CoinMemcpyN(dsol + numberColumns_, numberRows_, dual_); delete [] status; delete [] psol; delete [] dsol; } optimizationDirection_ = coinModel.optimizationDirection(); return returnCode; } /* If input negative scales objective so maximum <= -value and returns scale factor used. If positive unscales and also redoes dual stuff */ double ClpSimplex::scaleObjective(double value) { double * obj = objective(); double largest = 0.0; if (value < 0.0) { value = - value; for (int i = 0; i < numberColumns_; i++) { largest = CoinMax(largest, fabs(obj[i])); } if (largest > value) { double scaleFactor = value / largest; for (int i = 0; i < numberColumns_; i++) { obj[i] *= scaleFactor; reducedCost_[i] *= scaleFactor; } for (int i = 0; i < numberRows_; i++) { dual_[i] *= scaleFactor; } largest /= value; } else { // no need largest = 1.0; } } else { // at end if (value != 1.0) { for (int i = 0; i < numberColumns_; i++) { obj[i] *= value; reducedCost_[i] *= value; } for (int i = 0; i < numberRows_; i++) { dual_[i] *= value; } computeObjectiveValue(); } } return largest; } // Solve using Dantzig-Wolfe decomposition and maybe in parallel int ClpSimplex::solveDW(CoinStructuredModel * model) { double time1 = CoinCpuTime(); int numberColumns = model->numberColumns(); int numberRowBlocks = model->numberRowBlocks(); int numberColumnBlocks = model->numberColumnBlocks(); int numberElementBlocks = model->numberElementBlocks(); // We already have top level structure CoinModelBlockInfo * blockInfo = new CoinModelBlockInfo [numberElementBlocks]; for (int i = 0; i < numberElementBlocks; i++) { CoinModel * thisBlock = model->coinBlock(i); assert (thisBlock); // just fill in info CoinModelBlockInfo info = CoinModelBlockInfo(); int whatsSet = thisBlock->whatIsSet(); info.matrix = static_cast(((whatsSet & 1) != 0) ? 1 : 0); info.rhs = static_cast(((whatsSet & 2) != 0) ? 1 : 0); info.rowName = static_cast(((whatsSet & 4) != 0) ? 1 : 0); info.integer = static_cast(((whatsSet & 32) != 0) ? 1 : 0); info.bounds = static_cast(((whatsSet & 8) != 0) ? 1 : 0); info.columnName = static_cast(((whatsSet & 16) != 0) ? 1 : 0); // Which block int iRowBlock = model->rowBlock(thisBlock->getRowBlock()); info.rowBlock = iRowBlock; int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock()); info.columnBlock = iColumnBlock; blockInfo[i] = info; } // make up problems int numberBlocks = numberRowBlocks - 1; // Find master rows and columns int * rowCounts = new int [numberRowBlocks]; CoinZeroN(rowCounts, numberRowBlocks); int * columnCounts = new int [numberColumnBlocks+1]; CoinZeroN(columnCounts, numberColumnBlocks); int iBlock; for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) { int iRowBlock = blockInfo[iBlock].rowBlock; rowCounts[iRowBlock]++; int iColumnBlock = blockInfo[iBlock].columnBlock; columnCounts[iColumnBlock]++; } int * whichBlock = new int [numberElementBlocks]; int masterRowBlock = -1; for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) { if (rowCounts[iBlock] > 1) { if (masterRowBlock == -1) { masterRowBlock = iBlock; } else { // Can't decode masterRowBlock = -2; break; } } } int masterColumnBlock = -1; int kBlock = 0; for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) { int count = columnCounts[iBlock]; columnCounts[iBlock] = kBlock; kBlock += count; } for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) { int iColumnBlock = blockInfo[iBlock].columnBlock; whichBlock[columnCounts[iColumnBlock]] = iBlock; columnCounts[iColumnBlock]++; } for (iBlock = numberColumnBlocks - 1; iBlock >= 0; iBlock--) columnCounts[iBlock+1] = columnCounts[iBlock]; columnCounts[0] = 0; for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) { int count = columnCounts[iBlock+1] - columnCounts[iBlock]; if (count == 1) { int kBlock = whichBlock[columnCounts[iBlock]]; int iRowBlock = blockInfo[kBlock].rowBlock; if (iRowBlock == masterRowBlock) { if (masterColumnBlock == -1) { masterColumnBlock = iBlock; } else { // Can't decode masterColumnBlock = -2; break; } } } } if (masterRowBlock < 0 || masterColumnBlock == -2) { // What now abort(); } delete [] rowCounts; // create all data const CoinPackedMatrix ** top = new const CoinPackedMatrix * [numberColumnBlocks]; ClpSimplex * sub = new ClpSimplex [numberBlocks]; ClpSimplex master; // Set offset master.setObjectiveOffset(model->objectiveOffset()); kBlock = 0; int masterBlock = -1; for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) { top[kBlock] = NULL; int start = columnCounts[iBlock]; int end = columnCounts[iBlock+1]; assert (end - start <= 2); for (int j = start; j < end; j++) { int jBlock = whichBlock[j]; int iRowBlock = blockInfo[jBlock].rowBlock; int iColumnBlock = blockInfo[jBlock].columnBlock; assert (iColumnBlock == iBlock); if (iColumnBlock != masterColumnBlock && iRowBlock == masterRowBlock) { // top matrix top[kBlock] = model->coinBlock(jBlock)->packedMatrix(); } else { const CoinPackedMatrix * matrix = model->coinBlock(jBlock)->packedMatrix(); // Get pointers to arrays const double * rowLower; const double * rowUpper; const double * columnLower; const double * columnUpper; const double * objective; model->block(iRowBlock, iColumnBlock, rowLower, rowUpper, columnLower, columnUpper, objective); if (iColumnBlock != masterColumnBlock) { // diagonal block sub[kBlock].loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); if (true) { double * lower = sub[kBlock].columnLower(); double * upper = sub[kBlock].columnUpper(); int n = sub[kBlock].numberColumns(); for (int i = 0; i < n; i++) { lower[i] = CoinMax(-1.0e8, lower[i]); upper[i] = CoinMin(1.0e8, upper[i]); } } if (optimizationDirection_ < 0.0) { double * obj = sub[kBlock].objective(); int n = sub[kBlock].numberColumns(); for (int i = 0; i < n; i++) obj[i] = - obj[i]; } if (this->factorizationFrequency() == 200) { // User did not touch preset sub[kBlock].defaultFactorizationFrequency(); } else { // make sure model has correct value sub[kBlock].setFactorizationFrequency(this->factorizationFrequency()); } sub[kBlock].setPerturbation(50); // Set columnCounts to be diagonal block index for cleanup columnCounts[kBlock] = jBlock; } else { // master masterBlock = jBlock; master.loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); if (optimizationDirection_ < 0.0) { double * obj = master.objective(); int n = master.numberColumns(); for (int i = 0; i < n; i++) obj[i] = - obj[i]; } } } } if (iBlock != masterColumnBlock) kBlock++; } delete [] whichBlock; delete [] blockInfo; // For now master must have been defined (does not have to have columns) assert (master.numberRows()); assert (masterBlock >= 0); int numberMasterRows = master.numberRows(); // Overkill in terms of space int spaceNeeded = CoinMax(numberBlocks * (numberMasterRows + 1), 2 * numberMasterRows); int * rowAdd = new int[spaceNeeded]; double * elementAdd = new double[spaceNeeded]; spaceNeeded = numberBlocks; int * columnAdd = new int[spaceNeeded+1]; double * objective = new double[spaceNeeded]; // Add in costed slacks int firstArtificial = master.numberColumns(); int lastArtificial = firstArtificial; if (true) { const double * lower = master.rowLower(); const double * upper = master.rowUpper(); int kCol = 0; for (int iRow = 0; iRow < numberMasterRows; iRow++) { if (lower[iRow] > -1.0e10) { rowAdd[kCol] = iRow; elementAdd[kCol++] = 1.0; } if (upper[iRow] < 1.0e10) { rowAdd[kCol] = iRow; elementAdd[kCol++] = -1.0; } } if (kCol > spaceNeeded) { spaceNeeded = kCol; delete [] columnAdd; delete [] objective; columnAdd = new int[spaceNeeded+1]; objective = new double[spaceNeeded]; } for (int i = 0; i < kCol; i++) { columnAdd[i] = i; objective[i] = 1.0e13; } columnAdd[kCol] = kCol; master.addColumns(kCol, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); lastArtificial = master.numberColumns(); } int maxPass = 500; int iPass; double lastObjective = 1.0e31; // Create convexity rows for proposals int numberMasterColumns = master.numberColumns(); master.resize(numberMasterRows + numberBlocks, numberMasterColumns); if (this->factorizationFrequency() == 200) { // User did not touch preset master.defaultFactorizationFrequency(); } else { // make sure model has correct value master.setFactorizationFrequency(this->factorizationFrequency()); } master.setPerturbation(50); // Arrays to say which block and when created int maximumColumns = 2 * numberMasterRows + 10 * numberBlocks; whichBlock = new int[maximumColumns]; int * when = new int[maximumColumns]; int numberColumnsGenerated = numberBlocks; // fill in rhs and add in artificials { double * rowLower = master.rowLower(); double * rowUpper = master.rowUpper(); int iBlock; columnAdd[0] = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int iRow = iBlock + numberMasterRows;; rowLower[iRow] = 1.0; rowUpper[iRow] = 1.0; rowAdd[iBlock] = iRow; elementAdd[iBlock] = 1.0; objective[iBlock] = 1.0e13; columnAdd[iBlock+1] = iBlock + 1; when[iBlock] = -1; whichBlock[iBlock] = iBlock; } master.addColumns(numberBlocks, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); } // and resize matrix to double check clp will be happy //master.matrix()->setDimensions(numberMasterRows+numberBlocks, // numberMasterColumns+numberBlocks); std::cout << "Time to decompose " << CoinCpuTime() - time1 << " seconds" << std::endl; for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); // Solve master - may be infeasible //master.scaling(0); if (0) { master.writeMps("yy.mps"); } // Correct artificials double sumArtificials = 0.0; if (iPass) { double * upper = master.columnUpper(); double * solution = master.primalColumnSolution(); double * obj = master.objective(); sumArtificials = 0.0; for (int i = firstArtificial; i < lastArtificial; i++) { sumArtificials += solution[i]; //assert (solution[i]>-1.0e-2); if (solution[i] < 1.0e-6) { #if 0 // Could take out obj[i] = 0.0; upper[i] = 0.0; #else obj[i] = 1.0e7; upper[i] = 1.0e-1; #endif solution[i] = 0.0; master.setColumnStatus(i, isFixed); } else { upper[i] = solution[i] + 1.0e-5 * (1.0 + solution[i]); } } printf("Sum of artificials before solve is %g\n", sumArtificials); } // scale objective to be reasonable double scaleFactor = master.scaleObjective(-1.0e9); { double * dual = master.dualRowSolution(); int n = master.numberRows(); memset(dual, 0, n * sizeof(double)); double * solution = master.primalColumnSolution(); master.clpMatrix()->times(1.0, solution, dual); double sum = 0.0; double * lower = master.rowLower(); double * upper = master.rowUpper(); for (int iRow = 0; iRow < n; iRow++) { double value = dual[iRow]; if (value > upper[iRow]) sum += value - upper[iRow]; else if (value < lower[iRow]) sum -= value - lower[iRow]; } printf("suminf %g\n", sum); lower = master.columnLower(); upper = master.columnUpper(); n = master.numberColumns(); for (int iColumn = 0; iColumn < n; iColumn++) { double value = solution[iColumn]; if (value > upper[iColumn] + 1.0e-5) sum += value - upper[iColumn]; else if (value < lower[iColumn] - 1.0e-5) sum -= value - lower[iColumn]; } printf("suminf %g\n", sum); } master.primal(1); // Correct artificials sumArtificials = 0.0; { double * solution = master.primalColumnSolution(); for (int i = firstArtificial; i < lastArtificial; i++) { sumArtificials += solution[i]; } printf("Sum of artificials after solve is %g\n", sumArtificials); } master.scaleObjective(scaleFactor); int problemStatus = master.status(); // do here as can change (delcols) if (master.numberIterations() == 0 && iPass) break; // finished if (master.objectiveValue() > lastObjective - 1.0e-7 && iPass > 555) break; // finished lastObjective = master.objectiveValue(); // mark basic ones and delete if necessary int iColumn; numberColumnsGenerated = master.numberColumns() - numberMasterColumns; for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) { if (master.getStatus(iColumn + numberMasterColumns) == ClpSimplex::basic) when[iColumn] = iPass; } if (numberColumnsGenerated + numberBlocks > maximumColumns) { // delete int numberKeep = 0; int numberDelete = 0; int * whichDelete = new int[numberColumnsGenerated]; for (iColumn = 0; iColumn < numberColumnsGenerated; iColumn++) { if (when[iColumn] > iPass - 7) { // keep when[numberKeep] = when[iColumn]; whichBlock[numberKeep++] = whichBlock[iColumn]; } else { // delete whichDelete[numberDelete++] = iColumn + numberMasterColumns; } } numberColumnsGenerated -= numberDelete; master.deleteColumns(numberDelete, whichDelete); delete [] whichDelete; } const double * dual = NULL; bool deleteDual = false; if (problemStatus == 0) { dual = master.dualRowSolution(); } else if (problemStatus == 1) { // could do composite objective dual = master.infeasibilityRay(); deleteDual = true; printf("The sum of infeasibilities is %g\n", master.sumPrimalInfeasibilities()); } else if (!master.numberColumns()) { assert(!iPass); dual = master.dualRowSolution(); memset(master.dualRowSolution(), 0, (numberMasterRows + numberBlocks)*sizeof(double)); } else { abort(); } // Scale back on first time if (!iPass) { double * dual2 = master.dualRowSolution(); for (int i = 0; i < numberMasterRows + numberBlocks; i++) { dual2[i] *= 1.0e-7; } dual = master.dualRowSolution(); } // Create objective for sub problems and solve columnAdd[0] = 0; int numberProposals = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int numberColumns2 = sub[iBlock].numberColumns(); double * saveObj = new double [numberColumns2]; double * objective2 = sub[iBlock].objective(); memcpy(saveObj, objective2, numberColumns2 * sizeof(double)); // new objective top[iBlock]->transposeTimes(dual, objective2); int i; if (problemStatus == 0) { for (i = 0; i < numberColumns2; i++) objective2[i] = saveObj[i] - objective2[i]; } else { for (i = 0; i < numberColumns2; i++) objective2[i] = -objective2[i]; } // scale objective to be reasonable double scaleFactor = sub[iBlock].scaleObjective((sumArtificials > 1.0e-5) ? -1.0e-4 : -1.0e9); if (iPass) { sub[iBlock].primal(); } else { sub[iBlock].dual(); } sub[iBlock].scaleObjective(scaleFactor); if (!sub[iBlock].isProvenOptimal() && !sub[iBlock].isProvenDualInfeasible()) { memset(objective2, 0, numberColumns2 * sizeof(double)); sub[iBlock].primal(); if (problemStatus == 0) { for (i = 0; i < numberColumns2; i++) objective2[i] = saveObj[i] - objective2[i]; } else { for (i = 0; i < numberColumns2; i++) objective2[i] = -objective2[i]; } double scaleFactor = sub[iBlock].scaleObjective(-1.0e9); sub[iBlock].primal(1); sub[iBlock].scaleObjective(scaleFactor); } memcpy(objective2, saveObj, numberColumns2 * sizeof(double)); // get proposal if (sub[iBlock].numberIterations() || !iPass) { double objValue = 0.0; int start = columnAdd[numberProposals]; // proposal if (sub[iBlock].isProvenOptimal()) { const double * solution = sub[iBlock].primalColumnSolution(); top[iBlock]->times(solution, elementAdd + start); for (i = 0; i < numberColumns2; i++) objValue += solution[i] * saveObj[i]; // See if good dj and pack down int number = start; double dj = objValue; if (problemStatus) dj = 0.0; double smallest = 1.0e100; double largest = 0.0; for (i = 0; i < numberMasterRows; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { dj -= dual[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); rowAdd[number] = i; elementAdd[number++] = value; } } // and convexity dj -= dual[numberMasterRows+iBlock]; rowAdd[number] = numberMasterRows + iBlock; elementAdd[number++] = 1.0; // if elements large then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem %d smallest - %g, largest %g - dj %g\n", iBlock, smallest, largest, dj); if (dj < -1.0e-6 || !iPass) { // take objective[numberProposals] = objValue; columnAdd[++numberProposals] = number; when[numberColumnsGenerated] = iPass; whichBlock[numberColumnsGenerated++] = iBlock; } } else if (sub[iBlock].isProvenDualInfeasible()) { // use ray const double * solution = sub[iBlock].unboundedRay(); top[iBlock]->times(solution, elementAdd + start); for (i = 0; i < numberColumns2; i++) objValue += solution[i] * saveObj[i]; // See if good dj and pack down int number = start; double dj = objValue; double smallest = 1.0e100; double largest = 0.0; for (i = 0; i < numberMasterRows; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { dj -= dual[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); rowAdd[number] = i; elementAdd[number++] = value; } } // if elements large or small then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem ray %d smallest - %g, largest %g - dj %g\n", iBlock, smallest, largest, dj); if (dj < -1.0e-6) { // take objective[numberProposals] = objValue; columnAdd[++numberProposals] = number; when[numberColumnsGenerated] = iPass; whichBlock[numberColumnsGenerated++] = iBlock; } } else { abort(); } } delete [] saveObj; } if (deleteDual) delete [] dual; if (numberProposals) master.addColumns(numberProposals, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); } std::cout << "Time at end of D-W " << CoinCpuTime() - time1 << " seconds" << std::endl; //master.scaling(0); //master.primal(1); loadProblem(*model); // now put back a good solution double * lower = new double[numberMasterRows+numberBlocks]; double * upper = new double[numberMasterRows+numberBlocks]; numberColumnsGenerated += numberMasterColumns; double * sol = new double[numberColumnsGenerated]; const double * solution = master.primalColumnSolution(); const double * masterLower = master.rowLower(); const double * masterUpper = master.rowUpper(); double * fullSolution = primalColumnSolution(); const double * fullLower = columnLower(); const double * fullUpper = columnUpper(); const double * rowSolution = master.primalRowSolution(); double * fullRowSolution = primalRowSolution(); const int * rowBack = model->coinBlock(masterBlock)->originalRows(); int numberRows2 = model->coinBlock(masterBlock)->numberRows(); const int * columnBack = model->coinBlock(masterBlock)->originalColumns(); int numberColumns2 = model->coinBlock(masterBlock)->numberColumns(); for (int iRow = 0; iRow < numberRows2; iRow++) { int kRow = rowBack[iRow]; setRowStatus(kRow, master.getRowStatus(iRow)); fullRowSolution[kRow] = rowSolution[iRow]; } for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { int kColumn = columnBack[iColumn]; setStatus(kColumn, master.getStatus(iColumn)); fullSolution[kColumn] = solution[iColumn]; } for (iBlock = 0; iBlock < numberBlocks; iBlock++) { // move basis int kBlock = columnCounts[iBlock]; const int * rowBack = model->coinBlock(kBlock)->originalRows(); int numberRows2 = model->coinBlock(kBlock)->numberRows(); const int * columnBack = model->coinBlock(kBlock)->originalColumns(); int numberColumns2 = model->coinBlock(kBlock)->numberColumns(); for (int iRow = 0; iRow < numberRows2; iRow++) { int kRow = rowBack[iRow]; setRowStatus(kRow, sub[iBlock].getRowStatus(iRow)); } for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { int kColumn = columnBack[iColumn]; setStatus(kColumn, sub[iBlock].getStatus(iColumn)); } // convert top bit to by rows CoinPackedMatrix topMatrix = *top[iBlock]; topMatrix.reverseOrdering(); // zero solution memset(sol, 0, numberColumnsGenerated * sizeof(double)); for (int i = numberMasterColumns; i < numberColumnsGenerated; i++) { if (whichBlock[i-numberMasterColumns] == iBlock) sol[i] = solution[i]; } memset(lower, 0, (numberMasterRows + numberBlocks)*sizeof(double)); master.clpMatrix()->times(1.0, sol, lower); for (int iRow = 0; iRow < numberMasterRows; iRow++) { double value = lower[iRow]; if (masterUpper[iRow] < 1.0e20) upper[iRow] = value; else upper[iRow] = COIN_DBL_MAX; if (masterLower[iRow] > -1.0e20) lower[iRow] = value; else lower[iRow] = -COIN_DBL_MAX; } sub[iBlock].addRows(numberMasterRows, lower, upper, topMatrix.getVectorStarts(), topMatrix.getVectorLengths(), topMatrix.getIndices(), topMatrix.getElements()); sub[iBlock].primal(1); const double * subSolution = sub[iBlock].primalColumnSolution(); const double * subRowSolution = sub[iBlock].primalRowSolution(); // move solution for (int iRow = 0; iRow < numberRows2; iRow++) { int kRow = rowBack[iRow]; fullRowSolution[kRow] = subRowSolution[iRow]; } for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { int kColumn = columnBack[iColumn]; fullSolution[kColumn] = subSolution[iColumn]; } } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (fullSolution[iColumn] < fullUpper[iColumn] - 1.0e-8 && fullSolution[iColumn] > fullLower[iColumn] + 1.0e-8) { if (getStatus(iColumn) != ClpSimplex::basic) { if (columnLower_[iColumn] > -1.0e30 || columnUpper_[iColumn] < 1.0e30) setStatus(iColumn, ClpSimplex::superBasic); else setStatus(iColumn, ClpSimplex::isFree); } } else if (fullSolution[iColumn] >= fullUpper[iColumn] - 1.0e-8) { // may help to make rest non basic if (getStatus(iColumn) != ClpSimplex::basic) setStatus(iColumn, ClpSimplex::atUpperBound); } else if (fullSolution[iColumn] <= fullLower[iColumn] + 1.0e-8) { // may help to make rest non basic if (getStatus(iColumn) != ClpSimplex::basic) setStatus(iColumn, ClpSimplex::atLowerBound); } } //int numberRows=model->numberRows(); //for (int iRow=0;iRownumberColumns(); int numberRowBlocks = model->numberRowBlocks(); int numberColumnBlocks = model->numberColumnBlocks(); int numberElementBlocks = model->numberElementBlocks(); // We already have top level structure CoinModelBlockInfo * blockInfo = new CoinModelBlockInfo [numberElementBlocks]; for (int i = 0; i < numberElementBlocks; i++) { CoinModel * thisBlock = model->coinBlock(i); assert (thisBlock); // just fill in info CoinModelBlockInfo info = CoinModelBlockInfo(); int whatsSet = thisBlock->whatIsSet(); info.matrix = static_cast(((whatsSet & 1) != 0) ? 1 : 0); info.rhs = static_cast(((whatsSet & 2) != 0) ? 1 : 0); info.rowName = static_cast(((whatsSet & 4) != 0) ? 1 : 0); info.integer = static_cast(((whatsSet & 32) != 0) ? 1 : 0); info.bounds = static_cast(((whatsSet & 8) != 0) ? 1 : 0); info.columnName = static_cast(((whatsSet & 16) != 0) ? 1 : 0); // Which block int iRowBlock = model->rowBlock(thisBlock->getRowBlock()); info.rowBlock = iRowBlock; int iColumnBlock = model->columnBlock(thisBlock->getColumnBlock()); info.columnBlock = iColumnBlock; blockInfo[i] = info; } // make up problems int numberBlocks = numberColumnBlocks - 1; // Find master columns and rows int * columnCounts = new int [numberColumnBlocks]; CoinZeroN(columnCounts, numberColumnBlocks); int * rowCounts = new int [numberRowBlocks+1]; CoinZeroN(rowCounts, numberRowBlocks); int iBlock; for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) { int iColumnBlock = blockInfo[iBlock].columnBlock; columnCounts[iColumnBlock]++; int iRowBlock = blockInfo[iBlock].rowBlock; rowCounts[iRowBlock]++; } int * whichBlock = new int [numberElementBlocks]; int masterColumnBlock = -1; for (iBlock = 0; iBlock < numberColumnBlocks; iBlock++) { if (columnCounts[iBlock] > 1) { if (masterColumnBlock == -1) { masterColumnBlock = iBlock; } else { // Can't decode masterColumnBlock = -2; break; } } } int masterRowBlock = -1; int kBlock = 0; for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) { int count = rowCounts[iBlock]; rowCounts[iBlock] = kBlock; kBlock += count; } for (iBlock = 0; iBlock < numberElementBlocks; iBlock++) { int iRowBlock = blockInfo[iBlock].rowBlock; whichBlock[rowCounts[iRowBlock]] = iBlock; rowCounts[iRowBlock]++; } for (iBlock = numberRowBlocks - 1; iBlock >= 0; iBlock--) rowCounts[iBlock+1] = rowCounts[iBlock]; rowCounts[0] = 0; for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) { int count = rowCounts[iBlock+1] - rowCounts[iBlock]; if (count == 1) { int kBlock = whichBlock[rowCounts[iBlock]]; int iColumnBlock = blockInfo[kBlock].columnBlock; if (iColumnBlock == masterColumnBlock) { if (masterRowBlock == -1) { masterRowBlock = iBlock; } else { // Can't decode masterRowBlock = -2; break; } } } } if (masterColumnBlock < 0 || masterRowBlock == -2) { // What now abort(); } delete [] columnCounts; // create all data const CoinPackedMatrix ** first = new const CoinPackedMatrix * [numberRowBlocks]; ClpSimplex * sub = new ClpSimplex [numberBlocks]; ClpSimplex master; // Set offset master.setObjectiveOffset(model->objectiveOffset()); kBlock = 0; int masterBlock = -1; for (iBlock = 0; iBlock < numberRowBlocks; iBlock++) { first[kBlock] = NULL; int start = rowCounts[iBlock]; int end = rowCounts[iBlock+1]; assert (end - start <= 2); for (int j = start; j < end; j++) { int jBlock = whichBlock[j]; int iColumnBlock = blockInfo[jBlock].columnBlock; int iRowBlock = blockInfo[jBlock].rowBlock; assert (iRowBlock == iBlock); if (iRowBlock != masterRowBlock && iColumnBlock == masterColumnBlock) { // first matrix first[kBlock] = model->coinBlock(jBlock)->packedMatrix(); } else { const CoinPackedMatrix * matrix = model->coinBlock(jBlock)->packedMatrix(); // Get pointers to arrays const double * columnLower; const double * columnUpper; const double * rowLower; const double * rowUpper; const double * objective; model->block(iRowBlock, iColumnBlock, rowLower, rowUpper, columnLower, columnUpper, objective); if (iRowBlock != masterRowBlock) { // diagonal block sub[kBlock].loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); if (optimizationDirection_ < 0.0) { double * obj = sub[kBlock].objective(); int n = sub[kBlock].numberColumns(); for (int i = 0; i < n; i++) obj[i] = - obj[i]; } if (this->factorizationFrequency() == 200) { // User did not touch preset sub[kBlock].defaultFactorizationFrequency(); } else { // make sure model has correct value sub[kBlock].setFactorizationFrequency(this->factorizationFrequency()); } sub[kBlock].setPerturbation(50); // Set rowCounts to be diagonal block index for cleanup rowCounts[kBlock] = jBlock; } else { // master masterBlock = jBlock; master.loadProblem(*matrix, columnLower, columnUpper, objective, rowLower, rowUpper); if (optimizationDirection_ < 0.0) { double * obj = master.objective(); int n = master.numberColumns(); for (int i = 0; i < n; i++) obj[i] = - obj[i]; } } } } if (iBlock != masterRowBlock) kBlock++; } delete [] whichBlock; delete [] blockInfo; // For now master must have been defined (does not have to have rows) assert (master.numberColumns()); assert (masterBlock >= 0); int numberMasterColumns = master.numberColumns(); // Overkill in terms of space int spaceNeeded = CoinMax(numberBlocks * (numberMasterColumns + 1), 2 * numberMasterColumns); int * columnAdd = new int[spaceNeeded]; double * elementAdd = new double[spaceNeeded]; spaceNeeded = numberBlocks; int * rowAdd = new int[spaceNeeded+1]; double * objective = new double[spaceNeeded]; int maxPass = 500; int iPass; double lastObjective = -1.0e31; // Create columns for proposals int numberMasterRows = master.numberRows(); master.resize(numberMasterColumns + numberBlocks, numberMasterRows); if (this->factorizationFrequency() == 200) { // User did not touch preset master.defaultFactorizationFrequency(); } else { // make sure model has correct value master.setFactorizationFrequency(this->factorizationFrequency()); } master.setPerturbation(50); // Arrays to say which block and when created int maximumRows = 2 * numberMasterColumns + 10 * numberBlocks; whichBlock = new int[maximumRows]; int * when = new int[maximumRows]; int numberRowsGenerated = numberBlocks; // Add extra variables { int iBlock; columnAdd[0] = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { objective[iBlock] = 1.0; columnAdd[iBlock+1] = 0; when[iBlock] = -1; whichBlock[iBlock] = iBlock; } master.addColumns(numberBlocks, NULL, NULL, objective, columnAdd, rowAdd, elementAdd); } std::cout << "Time to decompose " << CoinCpuTime() - time1 << " seconds" << std::endl; for (iPass = 0; iPass < maxPass; iPass++) { printf("Start of pass %d\n", iPass); // Solve master - may be unbounded //master.scaling(0); if (1) { master.writeMps("yy.mps"); } master.dual(); int problemStatus = master.status(); // do here as can change (delcols) if (master.numberIterations() == 0 && iPass) break; // finished if (master.objectiveValue() < lastObjective + 1.0e-7 && iPass > 555) break; // finished lastObjective = master.objectiveValue(); // mark non-basic rows and delete if necessary int iRow; numberRowsGenerated = master.numberRows() - numberMasterRows; for (iRow = 0; iRow < numberRowsGenerated; iRow++) { if (master.getStatus(iRow + numberMasterRows) != ClpSimplex::basic) when[iRow] = iPass; } if (numberRowsGenerated > maximumRows) { // delete int numberKeep = 0; int numberDelete = 0; int * whichDelete = new int[numberRowsGenerated]; for (iRow = 0; iRow < numberRowsGenerated; iRow++) { if (when[iRow] > iPass - 7) { // keep when[numberKeep] = when[iRow]; whichBlock[numberKeep++] = whichBlock[iRow]; } else { // delete whichDelete[numberDelete++] = iRow + numberMasterRows; } } numberRowsGenerated -= numberDelete; master.deleteRows(numberDelete, whichDelete); delete [] whichDelete; } const double * primal = NULL; bool deletePrimal = false; if (problemStatus == 0) { primal = master.primalColumnSolution(); } else if (problemStatus == 2) { // could do composite objective primal = master.unboundedRay(); deletePrimal = true; printf("The sum of infeasibilities is %g\n", master.sumPrimalInfeasibilities()); } else if (!master.numberRows()) { assert(!iPass); primal = master.primalColumnSolution(); memset(master.primalColumnSolution(), 0, numberMasterColumns * sizeof(double)); } else { abort(); } // Create rhs for sub problems and solve rowAdd[0] = 0; int numberProposals = 0; for (iBlock = 0; iBlock < numberBlocks; iBlock++) { int numberRows2 = sub[iBlock].numberRows(); double * saveLower = new double [numberRows2]; double * lower2 = sub[iBlock].rowLower(); double * saveUpper = new double [numberRows2]; double * upper2 = sub[iBlock].rowUpper(); // new rhs CoinZeroN(saveUpper, numberRows2); first[iBlock]->times(primal, saveUpper); for (int i = 0; i < numberRows2; i++) { double value = saveUpper[i]; saveLower[i] = lower2[i]; saveUpper[i] = upper2[i]; if (saveLower[i] > -1.0e30) lower2[i] -= value; if (saveUpper[i] < 1.0e30) upper2[i] -= value; } sub[iBlock].dual(); memcpy(lower2, saveLower, numberRows2 * sizeof(double)); memcpy(upper2, saveUpper, numberRows2 * sizeof(double)); // get proposal if (sub[iBlock].numberIterations() || !iPass) { double objValue = 0.0; int start = rowAdd[numberProposals]; // proposal if (sub[iBlock].isProvenOptimal()) { const double * solution = sub[iBlock].dualRowSolution(); first[iBlock]->transposeTimes(solution, elementAdd + start); for (int i = 0; i < numberRows2; i++) { if (solution[i] < -dualTolerance_) { // at upper assert (saveUpper[i] < 1.0e30); objValue += solution[i] * saveUpper[i]; } else if (solution[i] > dualTolerance_) { // at lower assert (saveLower[i] > -1.0e30); objValue += solution[i] * saveLower[i]; } } // See if cuts off and pack down int number = start; double infeas = objValue; double smallest = 1.0e100; double largest = 0.0; for (int i = 0; i < numberMasterColumns; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { infeas -= primal[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); columnAdd[number] = i; elementAdd[number++] = -value; } } columnAdd[number] = numberMasterColumns + iBlock; elementAdd[number++] = -1.0; // if elements large then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem %d smallest - %g, largest %g - infeas %g\n", iBlock, smallest, largest, infeas); if (infeas < -1.0e-6 || !iPass) { // take objective[numberProposals] = objValue; rowAdd[++numberProposals] = number; when[numberRowsGenerated] = iPass; whichBlock[numberRowsGenerated++] = iBlock; } } else if (sub[iBlock].isProvenPrimalInfeasible()) { // use ray const double * solution = sub[iBlock].infeasibilityRay(); first[iBlock]->transposeTimes(solution, elementAdd + start); for (int i = 0; i < numberRows2; i++) { if (solution[i] < -dualTolerance_) { // at upper assert (saveUpper[i] < 1.0e30); objValue += solution[i] * saveUpper[i]; } else if (solution[i] > dualTolerance_) { // at lower assert (saveLower[i] > -1.0e30); objValue += solution[i] * saveLower[i]; } } // See if good infeas and pack down int number = start; double infeas = objValue; double smallest = 1.0e100; double largest = 0.0; for (int i = 0; i < numberMasterColumns; i++) { double value = elementAdd[start+i]; if (fabs(value) > 1.0e-15) { infeas -= primal[i] * value; smallest = CoinMin(smallest, fabs(value)); largest = CoinMax(largest, fabs(value)); columnAdd[number] = i; elementAdd[number++] = -value; } } // if elements large or small then scale? //if (largest>1.0e8||smallest<1.0e-8) printf("For subproblem ray %d smallest - %g, largest %g - infeas %g\n", iBlock, smallest, largest, infeas); if (infeas < -1.0e-6) { // take objective[numberProposals] = objValue; rowAdd[++numberProposals] = number; when[numberRowsGenerated] = iPass; whichBlock[numberRowsGenerated++] = iBlock; } } else { abort(); } } delete [] saveLower; delete [] saveUpper; } if (deletePrimal) delete [] primal; if (numberProposals) { master.addRows(numberProposals, NULL, objective, rowAdd, columnAdd, elementAdd); } } std::cout << "Time at end of Benders " << CoinCpuTime() - time1 << " seconds" << std::endl; //master.scaling(0); //master.primal(1); loadProblem(*model); // now put back a good solution const double * columnSolution = master.primalColumnSolution(); double * fullColumnSolution = primalColumnSolution(); const int * columnBack = model->coinBlock(masterBlock)->originalColumns(); int numberColumns2 = model->coinBlock(masterBlock)->numberColumns(); const int * rowBack = model->coinBlock(masterBlock)->originalRows(); int numberRows2 = model->coinBlock(masterBlock)->numberRows(); for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { int kColumn = columnBack[iColumn]; setColumnStatus(kColumn, master.getColumnStatus(iColumn)); fullColumnSolution[kColumn] = columnSolution[iColumn]; } for (int iRow = 0; iRow < numberRows2; iRow++) { int kRow = rowBack[iRow]; setStatus(kRow, master.getStatus(iRow)); //fullSolution[kRow]=solution[iRow]; } for (iBlock = 0; iBlock < numberBlocks; iBlock++) { // move basis int kBlock = rowCounts[iBlock]; const int * columnBack = model->coinBlock(kBlock)->originalColumns(); int numberColumns2 = model->coinBlock(kBlock)->numberColumns(); const int * rowBack = model->coinBlock(kBlock)->originalRows(); int numberRows2 = model->coinBlock(kBlock)->numberRows(); const double * subColumnSolution = sub[iBlock].primalColumnSolution(); for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { int kColumn = columnBack[iColumn]; setColumnStatus(kColumn, sub[iBlock].getColumnStatus(iColumn)); fullColumnSolution[kColumn] = subColumnSolution[iColumn]; } for (int iRow = 0; iRow < numberRows2; iRow++) { int kRow = rowBack[iRow]; setStatus(kRow, sub[iBlock].getStatus(iRow)); setStatus(kRow, atLowerBound); } } double * fullSolution = primalRowSolution(); CoinZeroN(fullSolution, numberRows_); times(1.0, fullColumnSolution, fullSolution); //int numberColumns=model->numberColumns(); //for (int iColumn=0;iColumnprimal(1); std::cout << "Total time " << CoinCpuTime() - time1 << " seconds" << std::endl; delete [] rowCounts; //delete [] sol; //delete [] lower; //delete [] upper; delete [] whichBlock; delete [] when; delete [] rowAdd; delete [] columnAdd; delete [] elementAdd; delete [] objective; delete [] first; delete [] sub; return 0; } Clp-1.15.10/src/ClpPrimalColumnSteepest.hpp0000644000076600007660000002176611510657452017153 0ustar coincoin/* $Id: ClpPrimalColumnSteepest.hpp 1665 2011-01-04 17:55:54Z 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 ClpPrimalColumnSteepest_H #define ClpPrimalColumnSteepest_H #include "ClpPrimalColumnPivot.hpp" #include //############################################################################# class CoinIndexedVector; /** Primal Column Pivot Steepest Edge Algorithm Class See Forrest-Goldfarb paper for algorithm */ class ClpPrimalColumnSteepest : public ClpPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none. The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row Parts of operation split out into separate functions for profiling and speed */ virtual int pivotColumn(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// For quadratic or funny nonlinearities int pivotColumnOldMethod(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Just update djs void justDjs(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update djs doing partial pricing (dantzig) int partialPricing(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, int numberWanted, int numberLook); /// Update djs, weights for Devex using djs void djsAndDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update djs, weights for Steepest using djs void djsAndSteepest(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update djs, weights for Devex using pivot row void djsAndDevex2(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update djs, weights for Steepest using pivot row void djsAndSteepest2(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update weights for Devex void justDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Update weights for Steepest void justSteepest(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Updates two arrays for steepest void transposeTimes2(const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, CoinIndexedVector * spare, double scaleFactor); /// Updates weights - part 1 - also checks accuracy virtual void updateWeights(CoinIndexedVector * input); /// Checks accuracy - just for debug void checkAccuracy(int sequence, double relativeTolerance, CoinIndexedVector * rowArray1, CoinIndexedVector * rowArray2); /// Initialize weights void initializeWeights(); /** Save weights - this may initialize weights as well mode is - 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights 5) at end of values pass (so need initialization) */ virtual void saveWeights(ClpSimplex * model, int mode); /// Gets rid of last update virtual void unrollWeights(); /// Gets rid of all arrays virtual void clearArrays(); /// Returns true if would not find any column virtual bool looksOptimal() const; /// Called when maximum pivots changes virtual void maximumPivotsChanged(); //@} /**@name gets and sets */ //@{ /// Mode inline int mode() const { return mode_; } /** Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ virtual int numberSprintColumns(int & numberIterations) const; /// Switch off sprint idea virtual void switchOffSprint(); //@} /** enums for persistence */ enum Persistence { normal = 0x00, // create (if necessary) and destroy keep = 0x01 // create (if necessary) and leave }; ///@name Constructors and destructors //@{ /** Default Constructor 0 is exact devex, 1 full steepest, 2 is partial exact devex 3 switches between 0 and 2 depending on factorization 4 starts as partial dantzig/devex but then may switch between 0 and 2. By partial exact devex is meant that the weights are updated as normal but only part of the nonbasic variables are scanned. This can be faster on very easy problems. */ ClpPrimalColumnSteepest(int mode = 3); /// Copy constructor ClpPrimalColumnSteepest(const ClpPrimalColumnSteepest & rhs); /// Assignment operator ClpPrimalColumnSteepest & operator=(const ClpPrimalColumnSteepest& rhs); /// Destructor virtual ~ClpPrimalColumnSteepest (); /// Clone virtual ClpPrimalColumnPivot * clone(bool copyData = true) const; //@} ///@name Private functions to deal with devex /** reference would be faster using ClpSimplex's status_, but I prefer to keep modularity. */ inline bool reference(int i) const { return ((reference_[i>>5] >> (i & 31)) & 1) != 0; } inline void setReference(int i, bool trueFalse) { unsigned int & value = reference_[i>>5]; int bit = i & 31; if (trueFalse) value |= (1 << bit); else value &= ~(1 << bit); } /// Set/ get persistence inline void setPersistence(Persistence life) { persistence_ = life; } inline Persistence persistence() const { return persistence_ ; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data // Update weight double devex_; /// weight array double * weights_; /// square of infeasibility array (just for infeasible columns) CoinIndexedVector * infeasible_; /// alternate weight array (so we can unroll) CoinIndexedVector * alternateWeights_; /// save weight array (so we can use checkpoint) double * savedWeights_; // Array for exact devex to say what is in reference framework unsigned int * reference_; /** Status 0) Normal -1) Needs initialization 1) Weights are stored by sequence number */ int state_; /** 0 is exact devex, 1 full steepest, 2 is partial exact devex 3 switches between 0 and 2 depending on factorization 4 starts as partial dantzig/devex but then may switch between 0 and 2. 5 is always partial dantzig By partial exact devex is meant that the weights are updated as normal but only part of the nonbasic variables are scanned. This can be faster on very easy problems. New dubious option is >=10 which does mini-sprint */ int mode_; /// Life of weights Persistence persistence_; /// Number of times switched from partial dantzig to 0/2 int numberSwitched_; // This is pivot row (or pivot sequence round re-factorization) int pivotSequence_; // This is saved pivot sequence int savedPivotSequence_; // This is saved outgoing variable int savedSequenceOut_; // Iteration when last rectified int lastRectified_; // Size of factorization at invert (used to decide algorithm) int sizeFactorization_; //@} }; #endif Clp-1.15.10/src/CoinAbcSmallFactorization4.cpp0000644000076600007660000000112612101105055017444 0ustar coincoin/* $Id: CoinAbcSmallFactorization4.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" // If we are twiddling this one has data #define FACTORS_HERE #include "CoinAbcBaseFactorization4.cpp" #endif Clp-1.15.10/src/ClpMessage.hpp0000644000076600007660000000613212130015370014370 0ustar coincoin/* $Id: ClpMessage.hpp 1928 2013-04-06 12:54: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 ClpMessage_H #define ClpMessage_H #include "CoinPragma.hpp" #include // This deals with Clp messages (as against Osi messages etc) #include "CoinMessageHandler.hpp" enum CLP_Message { CLP_SIMPLEX_FINISHED, CLP_SIMPLEX_INFEASIBLE, CLP_SIMPLEX_UNBOUNDED, CLP_SIMPLEX_STOPPED, CLP_SIMPLEX_ERROR, CLP_SIMPLEX_INTERRUPT, CLP_SIMPLEX_STATUS, CLP_DUAL_BOUNDS, CLP_SIMPLEX_ACCURACY, CLP_SIMPLEX_BADFACTOR, CLP_SIMPLEX_BOUNDTIGHTEN, CLP_SIMPLEX_INFEASIBILITIES, CLP_SIMPLEX_FLAG, CLP_SIMPLEX_GIVINGUP, CLP_DUAL_CHECKB, CLP_DUAL_ORIGINAL, CLP_SIMPLEX_PERTURB, CLP_PRIMAL_ORIGINAL, CLP_PRIMAL_WEIGHT, CLP_PRIMAL_OPTIMAL, CLP_SINGULARITIES, CLP_MODIFIEDBOUNDS, CLP_RIMSTATISTICS1, CLP_RIMSTATISTICS2, CLP_RIMSTATISTICS3, CLP_POSSIBLELOOP, CLP_SMALLELEMENTS, CLP_DUPLICATEELEMENTS, CLP_SIMPLEX_HOUSE1, CLP_SIMPLEX_HOUSE2, CLP_SIMPLEX_NONLINEAR, CLP_SIMPLEX_FREEIN, CLP_SIMPLEX_PIVOTROW, CLP_DUAL_CHECK, CLP_PRIMAL_DJ, CLP_PACKEDSCALE_INITIAL, CLP_PACKEDSCALE_WHILE, CLP_PACKEDSCALE_FINAL, CLP_PACKEDSCALE_FORGET, CLP_INITIALIZE_STEEP, CLP_UNABLE_OPEN, CLP_BAD_BOUNDS, CLP_BAD_MATRIX, CLP_LOOP, CLP_IMPORT_RESULT, CLP_IMPORT_ERRORS, CLP_EMPTY_PROBLEM, CLP_CRASH, CLP_END_VALUES_PASS, CLP_QUADRATIC_BOTH, CLP_QUADRATIC_PRIMAL_DETAILS, CLP_IDIOT_ITERATION, CLP_INFEASIBLE, CLP_MATRIX_CHANGE, CLP_TIMING, CLP_INTERVAL_TIMING, CLP_SPRINT, CLP_BARRIER_ITERATION, CLP_BARRIER_OBJECTIVE_GAP, CLP_BARRIER_GONE_INFEASIBLE, CLP_BARRIER_CLOSE_TO_OPTIMAL, CLP_BARRIER_COMPLEMENTARITY, CLP_BARRIER_EXIT2, CLP_BARRIER_STOPPING, CLP_BARRIER_EXIT, CLP_BARRIER_SCALING, CLP_BARRIER_MU, CLP_BARRIER_INFO, CLP_BARRIER_END, CLP_BARRIER_ACCURACY, CLP_BARRIER_SAFE, CLP_BARRIER_NEGATIVE_GAPS, CLP_BARRIER_REDUCING, CLP_BARRIER_DIAGONAL, CLP_BARRIER_SLACKS, CLP_BARRIER_DUALINF, CLP_BARRIER_KILLED, CLP_BARRIER_ABS_DROPPED, CLP_BARRIER_ABS_ERROR, CLP_BARRIER_FEASIBLE, CLP_BARRIER_STEP, CLP_BARRIER_KKT, CLP_RIM_SCALE, CLP_SLP_ITER, CLP_COMPLICATED_MODEL, CLP_BAD_STRING_VALUES, CLP_CRUNCH_STATS, CLP_PARAMETRICS_STATS, CLP_PARAMETRICS_STATS2, #ifndef NO_FATHOM_PRINT CLP_FATHOM_STATUS, CLP_FATHOM_SOLUTION, CLP_FATHOM_FINISH, #endif CLP_GENERAL, CLP_GENERAL2, CLP_GENERAL_WARNING, CLP_DUMMY_END }; /** This deals with Clp messages (as against Osi messages etc) */ class ClpMessage : public CoinMessages { public: /**@name Constructors etc */ //@{ /** Constructor */ ClpMessage(Language language = us_en); //@} }; #endif Clp-1.15.10/src/ClpPackedMatrix.cpp0000644000076600007660000104733212144647053015401 0ustar coincoin/* $Id: ClpPackedMatrix.cpp 1957 2013-05-15 08:58:19Z 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). #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" //#define THREAD #include "ClpSimplex.hpp" #include "ClpSimplexDual.hpp" #include "ClpFactorization.hpp" #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" #endif // at end to get min/max! #include "ClpPackedMatrix.hpp" #include "ClpMessage.hpp" #ifdef INTEL_MKL #include "mkl_spblas.h" #endif //#define DO_CHECK_FLAGS 1 //============================================================================= #ifdef COIN_PREFETCH #if 1 #define coin_prefetch(mem) \ __asm__ __volatile__ ("prefetchnta %0" : : "m" (*(reinterpret_cast(mem)))) #define coin_prefetch_const(mem) \ __asm__ __volatile__ ("prefetchnta %0" : : "m" (*(reinterpret_cast(mem)))) #else #define coin_prefetch(mem) \ __asm__ __volatile__ ("prefetch %0" : : "m" (*(reinterpret_cast(mem)))) #define coin_prefetch_const(mem) \ __asm__ __volatile__ ("prefetch %0" : : "m" (*(reinterpret_cast(mem)))) #endif #else // dummy #define coin_prefetch(mem) #define coin_prefetch_const(mem) #endif //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPackedMatrix::ClpPackedMatrix () : ClpMatrixBase(), matrix_(NULL), numberActiveColumns_(0), flags_(2), rowCopy_(NULL), columnCopy_(NULL) { setType(1); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPackedMatrix::ClpPackedMatrix (const ClpPackedMatrix & rhs) : ClpMatrixBase(rhs) { #ifdef DO_CHECK_FLAGS rhs.checkFlags(0); #endif #ifndef COIN_SPARSE_MATRIX // Guaranteed no gaps or small elements matrix_ = new CoinPackedMatrix(*(rhs.matrix_),-1,0) ; flags_ = rhs.flags_&(~0x02) ; #else // Gaps & small elements preserved matrix_ = new CoinPackedMatrix(*(rhs.matrix_),0,0) ; flags_ = rhs.flags_ ; if (matrix_->hasGaps()) flags_ |= 0x02 ; #endif numberActiveColumns_ = rhs.numberActiveColumns_; int numberRows = matrix_->getNumRows(); if (rhs.rhsOffset_ && numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_, numberRows); } else { rhsOffset_ = NULL; } if (rhs.rowCopy_) { assert ((flags_ & 4) != 0); rowCopy_ = new ClpPackedMatrix2(*rhs.rowCopy_); } else { rowCopy_ = NULL; } if (rhs.columnCopy_) { assert ((flags_&(8 + 16)) == 8 + 16); columnCopy_ = new ClpPackedMatrix3(*rhs.columnCopy_); } else { columnCopy_ = NULL; } #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } //------------------------------------------------------------------- // assign matrix (for space reasons) //------------------------------------------------------------------- ClpPackedMatrix::ClpPackedMatrix (CoinPackedMatrix * rhs) : ClpMatrixBase() { matrix_ = rhs; flags_ = ((matrix_->hasGaps())?0x02:0) ; numberActiveColumns_ = matrix_->getNumCols(); rowCopy_ = NULL; columnCopy_ = NULL; setType(1); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } ClpPackedMatrix::ClpPackedMatrix (const CoinPackedMatrix & rhs) : ClpMatrixBase() { #ifndef COIN_SPARSE_MATRIX matrix_ = new CoinPackedMatrix(rhs,-1,0) ; flags_ = 0 ; #else matrix_ = new CoinPackedMatrix(rhs,0,0) ; flags_ = ((matrix_->hasGaps())?0x02:0) ; #endif numberActiveColumns_ = matrix_->getNumCols(); rowCopy_ = NULL; columnCopy_ = NULL; setType(1); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPackedMatrix::~ClpPackedMatrix () { delete matrix_; delete rowCopy_; delete columnCopy_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPackedMatrix & ClpPackedMatrix::operator=(const ClpPackedMatrix& rhs) { if (this != &rhs) { ClpMatrixBase::operator=(rhs); delete matrix_; #ifndef COIN_SPARSE_MATRIX matrix_ = new CoinPackedMatrix(*(rhs.matrix_),-1,0) ; flags_ = rhs.flags_&(~0x02) ; #else matrix_ = new CoinPackedMatrix(*(rhs.matrix_),0,0) ; flags_ = rhs.flags_ ; if (matrix_->hasGaps()) flags_ |= 0x02 ; #endif numberActiveColumns_ = rhs.numberActiveColumns_; delete rowCopy_; delete columnCopy_; if (rhs.rowCopy_) { assert ((flags_ & 4) != 0); rowCopy_ = new ClpPackedMatrix2(*rhs.rowCopy_); } else { rowCopy_ = NULL; } if (rhs.columnCopy_) { assert ((flags_&(8 + 16)) == 8 + 16); columnCopy_ = new ClpPackedMatrix3(*rhs.columnCopy_); } else { columnCopy_ = NULL; } #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpPackedMatrix::clone() const { return new ClpPackedMatrix(*this); } // Copy contents - resizing if necessary - otherwise re-use memory void ClpPackedMatrix::copy(const ClpPackedMatrix * rhs) { //*this = *rhs; assert(numberActiveColumns_ == rhs->numberActiveColumns_); assert (matrix_->isColOrdered() == rhs->matrix_->isColOrdered()); matrix_->copyReuseArrays(*rhs->matrix_); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } /* Subset clone (without gaps). Duplicates are allowed and order is as given */ ClpMatrixBase * ClpPackedMatrix::subsetClone (int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const { return new ClpPackedMatrix(*this, numberRows, whichRows, numberColumns, whichColumns); } /* Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpPackedMatrix::ClpPackedMatrix ( const ClpPackedMatrix & rhs, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) : ClpMatrixBase(rhs) { matrix_ = new CoinPackedMatrix(*(rhs.matrix_), numberRows, whichRows, numberColumns, whichColumns); numberActiveColumns_ = matrix_->getNumCols(); rowCopy_ = NULL; flags_ = rhs.flags_&(~0x02) ; // no gaps columnCopy_ = NULL; #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } ClpPackedMatrix::ClpPackedMatrix ( const CoinPackedMatrix & rhs, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) : ClpMatrixBase() { matrix_ = new CoinPackedMatrix(rhs, numberRows, whichRows, numberColumns, whichColumns); numberActiveColumns_ = matrix_->getNumCols(); rowCopy_ = NULL; flags_ = 0 ; // no gaps columnCopy_ = NULL; setType(1); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } /* Returns a new matrix in reverse order without gaps */ ClpMatrixBase * ClpPackedMatrix::reverseOrderedCopy() const { ClpPackedMatrix * copy = new ClpPackedMatrix(); copy->matrix_ = new CoinPackedMatrix(); copy->matrix_->setExtraGap(0.0); copy->matrix_->setExtraMajor(0.0); copy->matrix_->reverseOrderedCopyOf(*matrix_); //copy->matrix_->removeGaps(); copy->numberActiveColumns_ = copy->matrix_->getNumCols(); copy->flags_ = flags_&(~0x02) ; // no gaps #ifdef DO_CHECK_FLAGS checkFlags(0); #endif return copy; } //unscaled versions void ClpPackedMatrix::times(double scalar, const double * x, double * y) const { int iRow, iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); //memset(y,0,matrix_->getNumRows()*sizeof(double)); assert (((flags_&0x02) != 0) == matrix_->hasGaps()); if (!(flags_ & 2)) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; double value = x[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; value *= scalar; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j]; } } } } else { const int * columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; double value = x[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; value *= scalar; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j]; } } } } } void ClpPackedMatrix::transposeTimes(double scalar, const double * x, double * y) const { int iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); if (!(flags_ & 2)) { if (scalar == -1.0) { CoinBigIndex start = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; double value = y[iColumn]; for (j = start; j < next; j++) { int jRow = row[j]; value -= x[jRow] * elementByColumn[j]; } start = next; y[iColumn] = value; } } else { CoinBigIndex start = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j]; } start = next; y[iColumn] += value * scalar; } } } else { const int * columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; double value = 0.0; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (j = start; j < end; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j]; } y[iColumn] += value * scalar; } } } void ClpPackedMatrix::times(double scalar, const double * COIN_RESTRICT x, double * COIN_RESTRICT y, const double * COIN_RESTRICT rowScale, const double * COIN_RESTRICT columnScale) const { if (rowScale) { int iRow, iColumn; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); if (!(flags_ & 2)) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = x[iColumn]; if (value) { // scaled value *= scalar * columnScale[iColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; CoinBigIndex j; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j] * rowScale[iRow]; } } } } else { const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = x[iColumn]; if (value) { // scaled value *= scalar * columnScale[iColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; CoinBigIndex j; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j] * rowScale[iRow]; } } } } } else { times(scalar, x, y); } } void ClpPackedMatrix::transposeTimes( double scalar, const double * COIN_RESTRICT x, double * COIN_RESTRICT y, const double * COIN_RESTRICT rowScale, const double * COIN_RESTRICT columnScale, double * COIN_RESTRICT spare) const { if (rowScale) { int iColumn; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); if (!spare) { if (!(flags_ & 2)) { CoinBigIndex start = columnStart[0]; if (scalar == -1.0) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; // scaled for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j] * rowScale[jRow]; } start = next; y[iColumn] -= value * columnScale[iColumn]; } } else { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; // scaled for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j] * rowScale[jRow]; } start = next; y[iColumn] += value * scalar * columnScale[iColumn]; } } } else { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; double value = 0.0; // scaled for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j] * rowScale[jRow]; } y[iColumn] += value * scalar * columnScale[iColumn]; } } } else { // can use spare region int iRow; int numberRows = matrix_->getNumRows(); for (iRow = 0; iRow < numberRows; iRow++) { double value = x[iRow]; if (value) spare[iRow] = value * rowScale[iRow]; else spare[iRow] = 0.0; } if (!(flags_ & 2)) { CoinBigIndex start = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; // scaled for (j = start; j < next; j++) { int jRow = row[j]; value += spare[jRow] * elementByColumn[j]; } start = next; y[iColumn] += value * scalar * columnScale[iColumn]; } } else { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; double value = 0.0; // scaled for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int jRow = row[j]; value += spare[jRow] * elementByColumn[j]; } y[iColumn] += value * scalar * columnScale[iColumn]; } } // no need to zero out //for (iRow=0;iRowgetIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); if (!spare || !rowScale) { if (rowScale) { for (int jColumn = 0; jColumn < number; jColumn++) { int iColumn = which[jColumn]; CoinBigIndex j; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j] * rowScale[jRow]; } y[iColumn] -= value * columnScale[iColumn]; } } else { for (int jColumn = 0; jColumn < number; jColumn++) { int iColumn = which[jColumn]; CoinBigIndex j; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j]; } y[iColumn] -= value; } } } else { // can use spare region int iRow; int numberRows = matrix_->getNumRows(); for (iRow = 0; iRow < numberRows; iRow++) { double value = x[iRow]; if (value) spare[iRow] = value * rowScale[iRow]; else spare[iRow] = 0.0; } for (int jColumn = 0; jColumn < number; jColumn++) { int iColumn = which[jColumn]; CoinBigIndex j; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex next = columnStart[iColumn+1]; double value = 0.0; for (j = start; j < next; j++) { int jRow = row[j]; value += spare[jRow] * elementByColumn[j]; } y[iColumn] -= value * columnScale[iColumn]; } } } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix::transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); #if 0 //def COIN_DEVELOP if (zeroTolerance != 1.0e-13) { printf("small element in matrix - zero tolerance %g\n", zeroTolerance); } #endif int numberRows = model->numberRows(); ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(model->rowCopy()); bool packed = rowArray->packedMode(); double factor = (numberRows < 100) ? 0.25 : 0.35; factor = 0.5; // We may not want to do by row if there may be cache problems // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberActiveColumns_ * sizeof(double) > 1000000) { if (numberRows * 10 < numberActiveColumns_) factor *= 0.333333333; else if (numberRows * 4 < numberActiveColumns_) factor *= 0.5; else if (numberRows * 2 < numberActiveColumns_) factor *= 0.66666666667; //if (model->numberIterations()%50==0) //printf("%d nonzero\n",numberInRowArray); } // if not packed then bias a bit more towards by column if (!packed) factor *= 0.9; assert (!y->getNumElements()); double multiplierX = 0.8; double factor2 = factor * multiplierX; if (packed && rowCopy_ && numberInRowArray > 2 && numberInRowArray > factor2 * numberRows && numberInRowArray < 0.9 * numberRows && 0) { rowCopy_->transposeTimes(model, rowCopy->matrix_, rowArray, y, columnArray); return; } if (numberInRowArray > factor * numberRows || !rowCopy) { // do by column // If no gaps - can do a bit faster if (!(flags_ & 2) || columnCopy_) { transposeTimesByColumn( model, scalar, rowArray, y, columnArray); return; } int iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); #if 0 ClpPackedMatrix * scaledMatrix = model->clpScaledMatrix(); if (rowScale && scaledMatrix) { rowScale = NULL; // get matrix data pointers row = scaledMatrix->getIndices(); columnStart = scaledMatrix->getVectorStarts(); columnLength = scaledMatrix->getVectorLengths(); elementByColumn = scaledMatrix->getElements(); } #endif if (packed) { // need to expand pi into y assert(y->capacity() >= numberRows); double * piOld = pi; pi = y->denseVector(); const int * whichRow = rowArray->getIndices(); int i; if (!rowScale) { // modify pi so can collapse to one loop if (scalar == -1.0) { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = -piOld[i]; } } else { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i]; } } for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled // modify pi so can collapse to one loop if (scalar == -1.0) { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = -piOld[i] * rowScale[iRow]; } } else { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i] * rowScale[iRow]; } } for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } value *= columnScale[iColumn]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } // zero out for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { if (!rowScale) { if (scalar == -1.0) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = -value; } } } else { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } value *= scalar; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled if (scalar == -1.0) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= columnScale[iColumn]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = -value; } } } else { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= scalar * columnScale[iColumn]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } } } columnArray->setNumElements(numberNonZero); y->setNumElements(0); } else { // do by row rowCopy->transposeTimesByRow(model, scalar, rowArray, y, columnArray); } if (packed) columnArray->setPackedMode(true); if (0) { columnArray->checkClean(); int numberNonZero = columnArray->getNumElements();; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int i; for (i = 0; i < numberNonZero; i++) { int j = index[i]; double value; if (packed) value = array[i]; else value = array[j]; printf("Ti %d %d %g\n", i, j, value); } } } //static int xA=0; //static int xB=0; //static int xC=0; //static int xD=0; //static double yA=0.0; //static double yC=0.0; /* Return x * scalar * A + y in z. Note - If x packed mode - then z packed mode This does by column and knows no gaps Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix::transposeTimesByColumn(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { double * COIN_RESTRICT pi = rowArray->denseVector(); int numberNonZero = 0; int * COIN_RESTRICT index = columnArray->getIndices(); double * COIN_RESTRICT array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); bool packed = rowArray->packedMode(); // do by column int iColumn; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT rowScale = model->rowScale(); assert (!y->getNumElements()); assert (numberActiveColumns_ > 0); const ClpPackedMatrix * thisMatrix = this; #if 0 ClpPackedMatrix * scaledMatrix = model->clpScaledMatrix(); if (rowScale && scaledMatrix) { rowScale = NULL; // get matrix data pointers row = scaledMatrix->getIndices(); columnStart = scaledMatrix->getVectorStarts(); elementByColumn = scaledMatrix->getElements(); thisMatrix = scaledMatrix; //printf("scaledMatrix\n"); } else if (rowScale) { //printf("no scaledMatrix\n"); } else { //printf("no rowScale\n"); } #endif if (packed) { // need to expand pi into y assert(y->capacity() >= model->numberRows()); double * piOld = pi; pi = y->denseVector(); const int * COIN_RESTRICT whichRow = rowArray->getIndices(); int i; if (!rowScale) { // modify pi so can collapse to one loop if (scalar == -1.0) { //yA += numberInRowArray; for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = -piOld[i]; } } else { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i]; } } if (!columnCopy_) { if ((model->specialOptions(), 131072) != 0) { if(model->spareIntArray_[0] > 0) { CoinIndexedVector * spareArray = model->rowArray(3); // also do dualColumn stuff double * spare = spareArray->denseVector(); int * spareIndex = spareArray->getIndices(); const double * reducedCost = model->djRegion(0); double multiplier[] = { -1.0, 1.0}; double dualT = - model->currentDualTolerance(); double acceptablePivot = model->spareDoubleArray_[0]; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e15; double upperTheta = 1.0e31; double bestPossible = 0.0; int addSequence = model->numberColumns(); const unsigned char * statusArray = model->statusArray() + addSequence; int numberRemaining = 0; assert (scalar == -1.0); for (i = 0; i < numberInRowArray; i++) { int iSequence = whichRow[i]; int iStatus = (statusArray[iSequence] & 3) - 1; if (iStatus) { double mult = multiplier[iStatus-1]; double alpha = piOld[i] * mult; double oldValue; double value; if (alpha > 0.0) { oldValue = reducedCost[iSequence] * mult; value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta); } // add to list spare[numberRemaining] = alpha * mult; spareIndex[numberRemaining++] = iSequence + addSequence; } } } } numberNonZero = thisMatrix->gutsOfTransposeTimesUnscaled(pi, columnArray->getIndices(), columnArray->denseVector(), model->statusArray(), spareIndex, spare, model->djRegion(1), upperTheta, bestPossible, acceptablePivot, model->currentDualTolerance(), numberRemaining, zeroTolerance); model->spareDoubleArray_[0] = upperTheta; model->spareDoubleArray_[1] = bestPossible; spareArray->setNumElements(numberRemaining); // signal partially done model->spareIntArray_[0] = -2; } else { numberNonZero = thisMatrix->gutsOfTransposeTimesUnscaled(pi, columnArray->getIndices(), columnArray->denseVector(), model->statusArray(), zeroTolerance); } } else { numberNonZero = thisMatrix->gutsOfTransposeTimesUnscaled(pi, columnArray->getIndices(), columnArray->denseVector(), zeroTolerance); } columnArray->setNumElements(numberNonZero); //xA++; } else { columnCopy_->transposeTimes(model, pi, columnArray); numberNonZero = columnArray->getNumElements(); //xB++; } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled // modify pi so can collapse to one loop if (scalar == -1.0) { //yC += numberInRowArray; for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = -piOld[i] * rowScale[iRow]; } } else { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i] * rowScale[iRow]; } } const double * columnScale = model->columnScale(); if (!columnCopy_) { if ((model->specialOptions(), 131072) != 0) numberNonZero = gutsOfTransposeTimesScaled(pi, columnScale, columnArray->getIndices(), columnArray->denseVector(), model->statusArray(), zeroTolerance); else numberNonZero = gutsOfTransposeTimesScaled(pi, columnScale, columnArray->getIndices(), columnArray->denseVector(), zeroTolerance); columnArray->setNumElements(numberNonZero); //xC++; } else { columnCopy_->transposeTimes(model, pi, columnArray); numberNonZero = columnArray->getNumElements(); //xD++; } } // zero out int numberRows = model->numberRows(); if (numberInRowArray * 4 < numberRows) { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { CoinZeroN(pi, numberRows); } //int kA=xA+xB; //int kC=xC+xD; //if ((kA+kC)%10000==0) //printf("AA %d %d %g, CC %d %d %g\n", // xA,xB,kA ? yA/(double)(kA): 0.0,xC,xD,kC ? yC/(double) (kC) :0.0); } else { if (!rowScale) { if (scalar == -1.0) { double value = 0.0; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+2]; if (fabs(value) > zeroTolerance) { array[iColumn] = -value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } } if (fabs(value) > zeroTolerance) { array[iColumn] = -value; index[numberNonZero++] = iColumn; } } else { double value = 0.0; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { value *= scalar; CoinBigIndex start = end; end = columnStart[iColumn+2]; if (fabs(value) > zeroTolerance) { array[iColumn] = value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } } value *= scalar; if (fabs(value) > zeroTolerance) { array[iColumn] = value; index[numberNonZero++] = iColumn; } } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled if (scalar == -1.0) { const double * columnScale = model->columnScale(); double value = 0.0; double scale = columnScale[0]; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { value *= scale; CoinBigIndex start = end; end = columnStart[iColumn+2]; scale = columnScale[iColumn+1]; if (fabs(value) > zeroTolerance) { array[iColumn] = -value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } } value *= scale; if (fabs(value) > zeroTolerance) { array[iColumn] = -value; index[numberNonZero++] = iColumn; } } else { const double * columnScale = model->columnScale(); double value = 0.0; double scale = columnScale[0] * scalar; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { value *= scale; CoinBigIndex start = end; end = columnStart[iColumn+2]; scale = columnScale[iColumn+1] * scalar; if (fabs(value) > zeroTolerance) { array[iColumn] = value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } } value *= scale; if (fabs(value) > zeroTolerance) { array[iColumn] = value; index[numberNonZero++] = iColumn; } } } } columnArray->setNumElements(numberNonZero); y->setNumElements(0); if (packed) columnArray->setPackedMode(true); } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix::transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); const int * column = matrix_->getIndices(); const CoinBigIndex * rowStart = getVectorStarts(); const double * element = getElements(); const int * whichRow = rowArray->getIndices(); bool packed = rowArray->packedMode(); if (numberInRowArray > 2) { // do by rows // ** Row copy is already scaled int iRow; int i; int numberOriginal = 0; if (packed) { int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); #if 0 { double * array2 = y->denseVector(); int numberColumns = matrix_->getNumCols(); for (int i=0;igetNumElements()); #if COIN_SPARSE_MATRIX != 2 // and set up mark as char array char * marked = reinterpret_cast (index+columnArray->capacity()); int * lookup = y->getIndices(); #ifndef NDEBUG //int numberColumns = matrix_->getNumCols(); //for (int i=0;idenseVector(); numberNonZero=gutsOfTransposeTimesByRowGE3(rowArray,index,array, array2,zeroTolerance,scalar); #endif #else int numberColumns = matrix_->getNumCols(); numberNonZero = gutsOfTransposeTimesByRowGEK(rowArray, index, array, numberColumns, zeroTolerance, scalar); #endif columnArray->setNumElements(numberNonZero); } else { double * markVector = y->denseVector(); numberNonZero = 0; // and set up mark as char array char * marked = reinterpret_cast (markVector); for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; marked[iColumn] = 0; } for (i = 0; i < numberInRowArray; i++) { iRow = whichRow[i]; double value = pi[iRow] * scalar; CoinBigIndex j; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (!marked[iColumn]) { marked[iColumn] = 1; index[numberNonZero++] = iColumn; } array[iColumn] += value * element[j]; } } // get rid of tiny values and zero out marked numberOriginal = numberNonZero; numberNonZero = 0; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; marked[iColumn] = 0; if (fabs(array[iColumn]) > zeroTolerance) { index[numberNonZero++] = iColumn; } else { array[iColumn] = 0.0; } } } } else if (numberInRowArray == 2) { // do by rows when two rows int numberOriginal; int i; CoinBigIndex j; numberNonZero = 0; double value; if (packed) { gutsOfTransposeTimesByRowEQ2(rowArray, columnArray, y, zeroTolerance, scalar); numberNonZero = columnArray->getNumElements(); } else { int iRow = whichRow[0]; value = pi[iRow] * scalar; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; double value2 = value * element[j]; index[numberNonZero++] = iColumn; array[iColumn] = value2; } iRow = whichRow[1]; value = pi[iRow] * scalar; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; double value2 = value * element[j]; // I am assuming no zeros in matrix if (array[iColumn]) value2 += array[iColumn]; else index[numberNonZero++] = iColumn; array[iColumn] = value2; } // get rid of tiny values and zero out marked numberOriginal = numberNonZero; numberNonZero = 0; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; if (fabs(array[iColumn]) > zeroTolerance) { index[numberNonZero++] = iColumn; } else { array[iColumn] = 0.0; } } } } else if (numberInRowArray == 1) { // Just one row int iRow = rowArray->getIndices()[0]; numberNonZero = 0; CoinBigIndex j; if (packed) { gutsOfTransposeTimesByRowEQ1(rowArray, columnArray, zeroTolerance, scalar); numberNonZero = columnArray->getNumElements(); } else { double value = pi[iRow] * scalar; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; double value2 = value * element[j]; if (fabs(value2) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value2; } } } } columnArray->setNumElements(numberNonZero); y->setNumElements(0); } // Meat of transposeTimes by column when not scaled int ClpPackedMatrix::gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const double zeroTolerance) const { int numberNonZero = 0; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); #if 1 //ndef INTEL_MKL double value = 0.0; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } int iColumn; for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+2]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } #else char transA = 'N'; //int numberRows = matrix_->getNumRows(); mkl_cspblas_dcsrgemv(&transA, const_cast(&numberActiveColumns_), const_cast(elementByColumn), const_cast(columnStart), const_cast(row), const_cast(pi), array); int iColumn; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { double value = array[iColumn]; if (value) { array[iColumn] = 0.0; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } #endif return numberNonZero; } // Meat of transposeTimes by column when scaled int ClpPackedMatrix::gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, const double * COIN_RESTRICT columnScale, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const double zeroTolerance) const { int numberNonZero = 0; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); double value = 0.0; double scale = columnScale[0]; CoinBigIndex j; CoinBigIndex end = columnStart[1]; for (j = columnStart[0]; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } int iColumn; for (iColumn = 0; iColumn < numberActiveColumns_ - 1; iColumn++) { value *= scale; CoinBigIndex start = end; scale = columnScale[iColumn+1]; end = columnStart[iColumn+2]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } } value *= scale; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } return numberNonZero; } // Meat of transposeTimes by column when not scaled int ClpPackedMatrix::gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * COIN_RESTRICT status, const double zeroTolerance) const { int numberNonZero = 0; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); double value = 0.0; int jColumn = -1; for (int iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { bool wanted = ((status[iColumn] & 3) != 1); if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } value = 0.0; if (wanted) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; jColumn = iColumn; int n = end - start; bool odd = (n & 1) != 0; n = n >> 1; const int * COIN_RESTRICT rowThis = row + start; const double * COIN_RESTRICT elementThis = elementByColumn + start; for (; n; n--) { int iRow0 = *rowThis; int iRow1 = *(rowThis + 1); rowThis += 2; value += pi[iRow0] * (*elementThis); value += pi[iRow1] * (*(elementThis + 1)); elementThis += 2; } if (odd) { int iRow = *rowThis; value += pi[iRow] * (*elementThis); } } } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } return numberNonZero; } /* Meat of transposeTimes by column when not scaled and skipping and doing part of dualColumn */ int ClpPackedMatrix::gutsOfTransposeTimesUnscaled(const double * COIN_RESTRICT pi, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * COIN_RESTRICT status, int * COIN_RESTRICT spareIndex, double * COIN_RESTRICT spareArray, const double * COIN_RESTRICT reducedCost, double & upperThetaP, double & bestPossibleP, double acceptablePivot, double dualTolerance, int & numberRemainingP, const double zeroTolerance) const { double tentativeTheta = 1.0e15; int numberRemaining = numberRemainingP; double upperTheta = upperThetaP; double bestPossible = bestPossibleP; int numberNonZero = 0; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); double multiplier[] = { -1.0, 1.0}; double dualT = - dualTolerance; for (int iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { int wanted = (status[iColumn] & 3) - 1; if (wanted) { double value = 0.0; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; int n = end - start; #if 1 bool odd = (n & 1) != 0; n = n >> 1; const int * COIN_RESTRICT rowThis = row + start; const double * COIN_RESTRICT elementThis = elementByColumn + start; for (; n; n--) { int iRow0 = *rowThis; int iRow1 = *(rowThis + 1); rowThis += 2; value += pi[iRow0] * (*elementThis); value += pi[iRow1] * (*(elementThis + 1)); elementThis += 2; } if (odd) { int iRow = *rowThis; value += pi[iRow] * (*elementThis); } #else const int * COIN_RESTRICT rowThis = &row[end-16]; const double * COIN_RESTRICT elementThis = &elementByColumn[end-16]; bool odd = (n & 1) != 0; n = n >> 1; double value2 = 0.0; if (odd) { int iRow = row[start]; value2 = pi[iRow] * elementByColumn[start]; } switch (n) { default: { if (odd) { start++; } n -= 8; for (; n; n--) { int iRow0 = row[start]; int iRow1 = row[start+1]; value += pi[iRow0] * elementByColumn[start]; value2 += pi[iRow1] * elementByColumn[start+1]; start += 2; } case 8: { int iRow0 = rowThis[16-16]; int iRow1 = rowThis[16-15]; value += pi[iRow0] * elementThis[16-16]; value2 += pi[iRow1] * elementThis[16-15]; } case 7: { int iRow0 = rowThis[16-14]; int iRow1 = rowThis[16-13]; value += pi[iRow0] * elementThis[16-14]; value2 += pi[iRow1] * elementThis[16-13]; } case 6: { int iRow0 = rowThis[16-12]; int iRow1 = rowThis[16-11]; value += pi[iRow0] * elementThis[16-12]; value2 += pi[iRow1] * elementThis[16-11]; } case 5: { int iRow0 = rowThis[16-10]; int iRow1 = rowThis[16-9]; value += pi[iRow0] * elementThis[16-10]; value2 += pi[iRow1] * elementThis[16-9]; } case 4: { int iRow0 = rowThis[16-8]; int iRow1 = rowThis[16-7]; value += pi[iRow0] * elementThis[16-8]; value2 += pi[iRow1] * elementThis[16-7]; } case 3: { int iRow0 = rowThis[16-6]; int iRow1 = rowThis[16-5]; value += pi[iRow0] * elementThis[16-6]; value2 += pi[iRow1] * elementThis[16-5]; } case 2: { int iRow0 = rowThis[16-4]; int iRow1 = rowThis[16-3]; value += pi[iRow0] * elementThis[16-4]; value2 += pi[iRow1] * elementThis[16-3]; } case 1: { int iRow0 = rowThis[16-2]; int iRow1 = rowThis[16-1]; value += pi[iRow0] * elementThis[16-2]; value2 += pi[iRow1] * elementThis[16-1]; } case 0: ; } } value += value2; #endif if (fabs(value) > zeroTolerance) { double mult = multiplier[wanted-1]; double alpha = value * mult; array[numberNonZero] = value; index[numberNonZero++] = iColumn; if (alpha > 0.0) { double oldValue = reducedCost[iColumn] * mult; double value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta); } // add to list spareArray[numberRemaining] = alpha * mult; spareIndex[numberRemaining++] = iColumn; } } } } } numberRemainingP = numberRemaining; upperThetaP = upperTheta; bestPossibleP = bestPossible; return numberNonZero; } // Meat of transposeTimes by column when scaled int ClpPackedMatrix::gutsOfTransposeTimesScaled(const double * COIN_RESTRICT pi, const double * COIN_RESTRICT columnScale, int * COIN_RESTRICT index, double * COIN_RESTRICT array, const unsigned char * COIN_RESTRICT status, const double zeroTolerance) const { int numberNonZero = 0; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); double value = 0.0; int jColumn = -1; for (int iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { bool wanted = ((status[iColumn] & 3) != 1); if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } value = 0.0; if (wanted) { double scale = columnScale[iColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; jColumn = iColumn; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } value *= scale; } } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } return numberNonZero; } // Meat of transposeTimes by row n > K if packed - returns number nonzero int ClpPackedMatrix::gutsOfTransposeTimesByRowGEK(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, int numberColumns, const double tolerance, const double scalar) const { const double * COIN_RESTRICT pi = piVector->denseVector(); int numberInRowArray = piVector->getNumElements(); const int * COIN_RESTRICT column = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT element = matrix_->getElements(); const int * COIN_RESTRICT whichRow = piVector->getIndices(); // ** Row copy is already scaled for (int i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; double value = pi[i] * scalar; CoinBigIndex start = rowStart[iRow]; CoinBigIndex end = rowStart[iRow+1]; int n = end - start; const int * COIN_RESTRICT columnThis = column + start; const double * COIN_RESTRICT elementThis = element + start; // could do by twos for (; n; n--) { int iColumn = *columnThis; columnThis++; double elValue = *elementThis; elementThis++; elValue *= value; output[iColumn] += elValue; } } // get rid of tiny values and count int numberNonZero = 0; for (int i = 0; i < numberColumns; i++) { double value = output[i]; if (value) { output[i] = 0.0; if (fabs(value) > tolerance) { output[numberNonZero] = value; index[numberNonZero++] = i; } } } #ifndef NDEBUG for (int i = numberNonZero; i < numberColumns; i++) assert(!output[i]); #endif return numberNonZero; } // Meat of transposeTimes by row n == 2 if packed void ClpPackedMatrix::gutsOfTransposeTimesByRowEQ2(const CoinIndexedVector * piVector, CoinIndexedVector * output, CoinIndexedVector * spareVector, const double tolerance, const double scalar) const { double * pi = piVector->denseVector(); int numberNonZero = 0; int * index = output->getIndices(); double * array = output->denseVector(); const int * column = matrix_->getIndices(); const CoinBigIndex * rowStart = matrix_->getVectorStarts(); const double * element = matrix_->getElements(); const int * whichRow = piVector->getIndices(); int iRow0 = whichRow[0]; int iRow1 = whichRow[1]; double pi0 = pi[0]; double pi1 = pi[1]; if (rowStart[iRow0+1] - rowStart[iRow0] > rowStart[iRow1+1] - rowStart[iRow1]) { // do one with fewer first iRow0 = iRow1; iRow1 = whichRow[0]; pi0 = pi1; pi1 = pi[0]; } // and set up mark as char array char * marked = reinterpret_cast (index + output->capacity()); int * lookup = spareVector->getIndices(); double value = pi0 * scalar; CoinBigIndex j; for (j = rowStart[iRow0]; j < rowStart[iRow0+1]; j++) { int iColumn = column[j]; double elValue = element[j]; double value2 = value * elValue; array[numberNonZero] = value2; marked[iColumn] = 1; lookup[iColumn] = numberNonZero; index[numberNonZero++] = iColumn; } int numberOriginal = numberNonZero; value = pi1 * scalar; for (j = rowStart[iRow1]; j < rowStart[iRow1+1]; j++) { int iColumn = column[j]; double elValue = element[j]; double value2 = value * elValue; // I am assuming no zeros in matrix if (marked[iColumn]) { int iLookup = lookup[iColumn]; array[iLookup] += value2; } else { if (fabs(value2) > tolerance) { array[numberNonZero] = value2; index[numberNonZero++] = iColumn; } } } // get rid of tiny values and zero out marked int i; int iFirst = numberNonZero; for (i = 0; i < numberOriginal; i++) { int iColumn = index[i]; marked[iColumn] = 0; if (fabs(array[i]) <= tolerance) { if (numberNonZero > numberOriginal) { numberNonZero--; double value = array[numberNonZero]; array[numberNonZero] = 0.0; array[i] = value; index[i] = index[numberNonZero]; } else { iFirst = i; } } } if (iFirst < numberNonZero) { int n = iFirst; for (i = n; i < numberOriginal; i++) { int iColumn = index[i]; double value = array[i]; array[i] = 0.0; if (fabs(value) > tolerance) { array[n] = value; index[n++] = iColumn; } } for (; i < numberNonZero; i++) { int iColumn = index[i]; double value = array[i]; array[i] = 0.0; array[n] = value; index[n++] = iColumn; } numberNonZero = n; } output->setNumElements(numberNonZero); spareVector->setNumElements(0); } // Meat of transposeTimes by row n == 1 if packed void ClpPackedMatrix::gutsOfTransposeTimesByRowEQ1(const CoinIndexedVector * piVector, CoinIndexedVector * output, const double tolerance, const double scalar) const { double * pi = piVector->denseVector(); int numberNonZero = 0; int * index = output->getIndices(); double * array = output->denseVector(); const int * column = matrix_->getIndices(); const CoinBigIndex * rowStart = matrix_->getVectorStarts(); const double * element = matrix_->getElements(); int iRow = piVector->getIndices()[0]; numberNonZero = 0; CoinBigIndex j; double value = pi[0] * scalar; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; double elValue = element[j]; double value2 = value * elValue; if (fabs(value2) > tolerance) { array[numberNonZero] = value2; index[numberNonZero++] = iColumn; } } output->setNumElements(numberNonZero); } /* Return x *A in z but just for indices in y. Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix::subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * rowArray, const CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * COIN_RESTRICT pi = rowArray->denseVector(); double * COIN_RESTRICT array = columnArray->denseVector(); int jColumn; // get matrix data pointers const int * COIN_RESTRICT row = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); const double * COIN_RESTRICT rowScale = model->rowScale(); int numberToDo = y->getNumElements(); const int * COIN_RESTRICT which = y->getIndices(); assert (!rowArray->packedMode()); columnArray->setPacked(); ClpPackedMatrix * scaledMatrix = model->clpScaledMatrix(); int flags = flags_; if (rowScale && scaledMatrix && !(scaledMatrix->flags() & 2)) { flags = 0; rowScale = NULL; // get matrix data pointers row = scaledMatrix->getIndices(); columnStart = scaledMatrix->getVectorStarts(); elementByColumn = scaledMatrix->getElements(); } if (!(flags & 2) && numberToDo>2) { // no gaps if (!rowScale) { int iColumn = which[0]; double value = 0.0; CoinBigIndex j; int columnNext = which[1]; CoinBigIndex startNext=columnStart[columnNext]; //coin_prefetch_const(row+startNext); //coin_prefetch_const(elementByColumn+startNext); CoinBigIndex endNext=columnStart[columnNext+1]; for (j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } for (jColumn = 0; jColumn < numberToDo - 2; jColumn++) { CoinBigIndex start = startNext; CoinBigIndex end = endNext; columnNext = which[jColumn+2]; startNext=columnStart[columnNext]; //coin_prefetch_const(row+startNext); //coin_prefetch_const(elementByColumn+startNext); endNext=columnStart[columnNext+1]; array[jColumn] = value; value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } } array[jColumn++] = value; value = 0.0; for (j = startNext; j < endNext; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } array[jColumn] = value; } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled const double * columnScale = model->columnScale(); int iColumn = which[0]; double value = 0.0; double scale = columnScale[iColumn]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } for (jColumn = 0; jColumn < numberToDo - 1; jColumn++) { int iColumn = which[jColumn+1]; value *= scale; scale = columnScale[iColumn]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; array[jColumn] = value; value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } } value *= scale; array[jColumn] = value; } } else if (numberToDo) { // gaps if (!rowScale) { for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } array[jColumn] = value; } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix - flags %d (%d) n %d\n", __LINE__, flags_, model->clpScaledMatrix()->flags(), numberToDo); #endif // scaled const double * columnScale = model->columnScale(); for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= columnScale[iColumn]; array[jColumn] = value; } } } } /* Returns true if can combine transposeTimes and subsetTransposeTimes and if it would be faster */ bool ClpPackedMatrix::canCombine(const ClpSimplex * model, const CoinIndexedVector * pi) const { int numberInRowArray = pi->getNumElements(); int numberRows = model->numberRows(); bool packed = pi->packedMode(); // factor should be smaller if doing both with two pi vectors double factor = 0.30; // We may not want to do by row if there may be cache problems // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberActiveColumns_ * sizeof(double) > 1000000) { if (numberRows * 10 < numberActiveColumns_) factor *= 0.333333333; else if (numberRows * 4 < numberActiveColumns_) factor *= 0.5; else if (numberRows * 2 < numberActiveColumns_) factor *= 0.66666666667; //if (model->numberIterations()%50==0) //printf("%d nonzero\n",numberInRowArray); } // if not packed then bias a bit more towards by column if (!packed) factor *= 0.9; return ((numberInRowArray > factor * numberRows || !model->rowCopy()) && !(flags_ & 2)); } #ifndef CLP_ALL_ONE_FILE // These have to match ClpPrimalColumnSteepest version #define reference(i) (((reference[i>>5]>>(i&31))&1)!=0) #endif // Updates two arrays for steepest void ClpPackedMatrix::transposeTimes2(const ClpSimplex * model, const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * spare, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { // put row of tableau in dj1 double * pi = pi1->denseVector(); int numberNonZero = 0; int * index = dj1->getIndices(); double * array = dj1->denseVector(); int numberInRowArray = pi1->getNumElements(); double zeroTolerance = model->zeroTolerance(); bool packed = pi1->packedMode(); // do by column int iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); assert (!spare->getNumElements()); assert (numberActiveColumns_ > 0); double * piWeight = pi2->denseVector(); assert (!pi2->packedMode()); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; if (packed) { // need to expand pi into y assert(spare->capacity() >= model->numberRows()); double * piOld = pi; pi = spare->denseVector(); const int * whichRow = pi1->getIndices(); int i; ClpPackedMatrix * scaledMatrix = model->clpScaledMatrix(); if (rowScale && scaledMatrix) { rowScale = NULL; // get matrix data pointers row = scaledMatrix->getIndices(); columnStart = scaledMatrix->getVectorStarts(); elementByColumn = scaledMatrix->getElements(); } if (!rowScale) { // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = piOld[i]; } if (!columnCopy_) { CoinBigIndex j; CoinBigIndex end = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+1]; ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value -= pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { // and do other array double modification = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j]; } double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } } else { // use special column copy // reset back if (killDjs) scaleFactor = 0.0; columnCopy_->transposeTimes2(model, pi, dj1, piWeight, referenceIn, devex, reference, weights, scaleFactor); numberNonZero = dj1->getNumElements(); } } else { // scaled // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = piOld[i] * rowScale[iRow]; } // can also scale piWeight as not used again int numberWeight = pi2->getNumElements(); const int * indexWeight = pi2->getIndices(); for (i = 0; i < numberWeight; i++) { int iRow = indexWeight[i]; piWeight[iRow] *= rowScale[iRow]; } if (!columnCopy_) { const double * columnScale = model->columnScale(); CoinBigIndex j; CoinBigIndex end = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+1]; ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double scale = columnScale[iColumn]; double value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value -= pi[iRow] * elementByColumn[j]; } value *= scale; if (fabs(value) > zeroTolerance) { double modification = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j]; } modification *= scale; double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } } else { // use special column copy // reset back if (killDjs) scaleFactor = 0.0; columnCopy_->transposeTimes2(model, pi, dj1, piWeight, referenceIn, devex, reference, weights, scaleFactor); numberNonZero = dj1->getNumElements(); } } // zero out int numberRows = model->numberRows(); if (numberInRowArray * 4 < numberRows) { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { CoinZeroN(pi, numberRows); } } else { if (!rowScale) { CoinBigIndex j; CoinBigIndex end = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+1]; ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value -= pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { // and do other array double modification = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j]; } double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[iColumn] = value; index[numberNonZero++] = iColumn; } } } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled // can also scale piWeight as not used again int numberWeight = pi2->getNumElements(); const int * indexWeight = pi2->getIndices(); for (int i = 0; i < numberWeight; i++) { int iRow = indexWeight[i]; piWeight[iRow] *= rowScale[iRow]; } const double * columnScale = model->columnScale(); CoinBigIndex j; CoinBigIndex end = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex start = end; end = columnStart[iColumn+1]; ClpSimplex::Status status = model->getStatus(iColumn); if (status == ClpSimplex::basic || status == ClpSimplex::isFixed) continue; double scale = columnScale[iColumn]; double value = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; value -= pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= scale; if (fabs(value) > zeroTolerance) { double modification = 0.0; for (j = start; j < end; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j]; } modification *= scale; double thisWeight = weights[iColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; if (!killDjs) { array[iColumn] = value; index[numberNonZero++] = iColumn; } } } } } dj1->setNumElements(numberNonZero); spare->setNumElements(0); if (packed) dj1->setPackedMode(true); } // Updates second array for steepest and does devex weights void ClpPackedMatrix::subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector *, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { int number = dj1->getNumElements(); const int * index = dj1->getIndices(); double * array = dj1->denseVector(); assert( dj1->packedMode()); // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); double * piWeight = pi2->denseVector(); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; if (!rowScale) { for (int k = 0; k < number; k++) { int iColumn = index[k]; double pivot = array[k] * scaleFactor; if (killDjs) array[k] = 0.0; // and do other array double modification = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j]; } double thisWeight = weights[iColumn]; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; } } else { #ifdef CLP_INVESTIGATE if (model->clpScaledMatrix()) printf("scaledMatrix_ at %d of ClpPackedMatrix\n", __LINE__); #endif // scaled const double * columnScale = model->columnScale(); for (int k = 0; k < number; k++) { int iColumn = index[k]; double pivot = array[k] * scaleFactor; double scale = columnScale[iColumn]; if (killDjs) array[k] = 0.0; // and do other array double modification = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; modification += piWeight[iRow] * elementByColumn[j] * rowScale[iRow]; } double thisWeight = weights[iColumn]; modification *= scale; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iColumn] = thisWeight; } } } /// returns number of elements in column part of basis, CoinBigIndex ClpPackedMatrix::countBasis( const int * whichColumn, int & numberColumnBasic) { const int * columnLength = matrix_->getVectorLengths(); int i; CoinBigIndex numberElements = 0; // just count - can be over so ignore zero problem for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; numberElements += columnLength[iColumn]; } return numberElements; } void ClpPackedMatrix::fillBasis(ClpSimplex * model, const int * COIN_RESTRICT whichColumn, int & numberColumnBasic, int * COIN_RESTRICT indexRowU, int * COIN_RESTRICT start, int * COIN_RESTRICT rowCount, int * COIN_RESTRICT columnCount, CoinFactorizationDouble * COIN_RESTRICT elementU) { const int * COIN_RESTRICT columnLength = matrix_->getVectorLengths(); int i; CoinBigIndex numberElements = start[0]; // fill const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT rowScale = model->rowScale(); const int * COIN_RESTRICT row = matrix_->getIndices(); const double * COIN_RESTRICT elementByColumn = matrix_->getElements(); ClpPackedMatrix * scaledMatrix = model->clpScaledMatrix(); if (scaledMatrix && true) { columnLength = scaledMatrix->matrix_->getVectorLengths(); columnStart = scaledMatrix->matrix_->getVectorStarts(); rowScale = NULL; row = scaledMatrix->matrix_->getIndices(); elementByColumn = scaledMatrix->matrix_->getElements(); } if ((flags_ & 1) == 0) { if (!rowScale) { // no scaling for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; int length = columnLength[iColumn]; CoinBigIndex startThis = columnStart[iColumn]; columnCount[i] = length; CoinBigIndex endThis = startThis + length; for (CoinBigIndex j = startThis; j < endThis; j++) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; assert (elementByColumn[j]); elementU[numberElements++] = elementByColumn[j]; } start[i+1] = numberElements; } } else { // scaling const double * COIN_RESTRICT columnScale = model->columnScale(); for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; double scale = columnScale[iColumn]; int length = columnLength[iColumn]; CoinBigIndex startThis = columnStart[iColumn]; columnCount[i] = length; CoinBigIndex endThis = startThis + length; for (CoinBigIndex j = startThis; j < endThis; j++) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; assert (elementByColumn[j]); elementU[numberElements++] = elementByColumn[j] * scale * rowScale[iRow]; } start[i+1] = numberElements; } } } else { // there are zero elements so need to look more closely if (!rowScale) { // no scaling for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { double value = elementByColumn[j]; if (value) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } start[i+1] = numberElements; columnCount[i] = numberElements - start[i]; } } else { // scaling const double * columnScale = model->columnScale(); for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j; double scale = columnScale[iColumn]; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[i]; j++) { double value = elementByColumn[j]; if (value) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value * scale * rowScale[iRow]; } } start[i+1] = numberElements; columnCount[i] = numberElements - start[i]; } } } } #if 0 int ClpPackedMatrix::scale2(ClpModel * model) const { ClpSimplex * baseModel = NULL; #ifndef NDEBUG //checkFlags(); #endif int numberRows = model->numberRows(); int numberColumns = matrix_->getNumCols(); model->setClpScaledMatrix(NULL); // get rid of any scaled matrix // If empty - return as sanityCheck will trap if (!numberRows || !numberColumns) { model->setRowScale(NULL); model->setColumnScale(NULL); return 1; } ClpMatrixBase * rowCopyBase = model->rowCopy(); double * rowScale; double * columnScale; //assert (!model->rowScale()); bool arraysExist; double * inverseRowScale = NULL; double * inverseColumnScale = NULL; if (!model->rowScale()) { rowScale = new double [numberRows*2]; columnScale = new double [numberColumns*2]; inverseRowScale = rowScale + numberRows; inverseColumnScale = columnScale + numberColumns; arraysExist = false; } else { rowScale = model->mutableRowScale(); columnScale = model->mutableColumnScale(); inverseRowScale = model->mutableInverseRowScale(); inverseColumnScale = model->mutableInverseColumnScale(); arraysExist = true; } assert (inverseRowScale == rowScale + numberRows); assert (inverseColumnScale == columnScale + numberColumns); // we are going to mark bits we are interested in char * usefulRow = new char [numberRows]; char * usefulColumn = new char [numberColumns]; double * rowLower = model->rowLower(); double * rowUpper = model->rowUpper(); double * columnLower = model->columnLower(); double * columnUpper = model->columnUpper(); int iColumn, iRow; //#define LEAVE_FIXED // mark free rows for (iRow = 0; iRow < numberRows; iRow++) { #if 0 //ndef LEAVE_FIXED if (rowUpper[iRow] < 1.0e20 || rowLower[iRow] > -1.0e20) usefulRow[iRow] = 1; else usefulRow[iRow] = 0; #else usefulRow[iRow] = 1; #endif } // mark empty and fixed columns // also see if worth scaling assert (model->scalingFlag() <= 4); // scale_stats[model->scalingFlag()]++; double largest = 0.0; double smallest = 1.0e50; // get matrix data pointers int * row = matrix_->getMutableIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); int * columnLength = matrix_->getMutableVectorLengths(); double * elementByColumn = matrix_->getMutableElements(); bool deletedElements = false; for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; char useful = 0; bool deleteSome = false; int start = columnStart[iColumn]; int end = start + columnLength[iColumn]; #ifndef LEAVE_FIXED if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12) { #endif for (j = start; j < end; j++) { iRow = row[j]; double value = fabs(elementByColumn[j]); if (value > 1.0e-20) { if(usefulRow[iRow]) { useful = 1; largest = CoinMax(largest, fabs(elementByColumn[j])); smallest = CoinMin(smallest, fabs(elementByColumn[j])); } } else { // small deleteSome = true; } } #ifndef LEAVE_FIXED } else { // just check values for (j = start; j < end; j++) { double value = fabs(elementByColumn[j]); if (value <= 1.0e-20) { // small deleteSome = true; } } } #endif usefulColumn[iColumn] = useful; if (deleteSome) { deletedElements = true; CoinBigIndex put = start; for (j = start; j < end; j++) { double value = elementByColumn[j]; if (fabs(value) > 1.0e-20) { row[put] = row[j]; elementByColumn[put++] = value; } } columnLength[iColumn] = put - start; } } model->messageHandler()->message(CLP_PACKEDSCALE_INITIAL, *model->messagesPointer()) << smallest << largest << CoinMessageEol; if (smallest >= 0.5 && largest <= 2.0 && !deletedElements) { // don't bother scaling model->messageHandler()->message(CLP_PACKEDSCALE_FORGET, *model->messagesPointer()) << CoinMessageEol; if (!arraysExist) { delete [] rowScale; delete [] columnScale; } else { model->setRowScale(NULL); model->setColumnScale(NULL); } delete [] usefulRow; delete [] usefulColumn; return 1; } else { #ifdef CLP_INVESTIGATE if (deletedElements) printf("DEL_ELS\n"); #endif if (!rowCopyBase) { // temporary copy rowCopyBase = reverseOrderedCopy(); } else if (deletedElements) { rowCopyBase = reverseOrderedCopy(); model->setNewRowCopy(rowCopyBase); } #ifndef NDEBUG ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); #else ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(rowCopyBase); #endif const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * element = rowCopy->getElements(); // need to scale if (largest > 1.0e13 * smallest) { // safer to have smaller zero tolerance double ratio = smallest / largest; ClpSimplex * simplex = static_cast (model); double newTolerance = CoinMax(ratio * 0.5, 1.0e-18); if (simplex->zeroTolerance() > newTolerance) simplex->setZeroTolerance(newTolerance); } int scalingMethod = model->scalingFlag(); if (scalingMethod == 4) { // As auto scalingMethod = 3; } // and see if there any empty rows for (iRow = 0; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { CoinBigIndex j; int useful = 0; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { useful = 1; break; } } usefulRow[iRow] = static_cast(useful); } } double savedOverallRatio = 0.0; double tolerance = 5.0 * model->primalTolerance(); double overallLargest = -1.0e-20; double overallSmallest = 1.0e20; bool finished = false; // if scalingMethod 3 then may change bool extraDetails = (model->logLevel() > 2); while (!finished) { int numberPass = 3; overallLargest = -1.0e-20; overallSmallest = 1.0e20; if (!baseModel) { ClpFillN ( rowScale, numberRows, 1.0); ClpFillN ( columnScale, numberColumns, 1.0); } else { // Copy scales and do quick scale on extra rows // Then just one? pass assert (numberColumns == baseModel->numberColumns()); int numberRows2 = baseModel->numberRows(); assert (numberRows >= numberRows2); assert (baseModel->rowScale()); CoinMemcpyN(baseModel->rowScale(), numberRows2, rowScale); CoinMemcpyN(baseModel->columnScale(), numberColumns, columnScale); if (numberRows > numberRows2) { numberPass = 1; // do some scaling if (scalingMethod == 1 || scalingMethod == 3) { // Maximum in each row for (iRow = numberRows2; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { CoinBigIndex j; largest = 1.0e-10; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j] * columnScale[iColumn]); largest = CoinMax(largest, value); assert (largest < 1.0e40); } } rowScale[iRow] = 1.0 / largest; #ifdef COIN_DEVELOP if (extraDetails) { overallLargest = CoinMax(overallLargest, largest); overallSmallest = CoinMin(overallSmallest, largest); } #endif } } } else { overallLargest = 0.0; overallSmallest = 1.0e50; // Geometric mean on row scales for (iRow = 0; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } if (iRow >= numberRows2) { rowScale[iRow] = 1.0 / sqrt(smallest * largest); //rowScale[iRow]=CoinMax(1.0e-10,CoinMin(1.0e10,rowScale[iRow])); } #ifdef COIN_DEVELOP if (extraDetails) { overallLargest = CoinMax(largest * rowScale[iRow], overallLargest); overallSmallest = CoinMin(smallest * rowScale[iRow], overallSmallest); } #endif } } } } else { // just use numberPass = 0; } } if (!baseModel && (scalingMethod == 1 || scalingMethod == 3)) { // Maximum in each row for (iRow = 0; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { CoinBigIndex j; largest = 1.0e-10; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); largest = CoinMax(largest, value); assert (largest < 1.0e40); } } rowScale[iRow] = 1.0 / largest; #ifdef COIN_DEVELOP if (extraDetails) { overallLargest = CoinMax(overallLargest, largest); overallSmallest = CoinMin(overallSmallest, largest); } #endif } } } else { #ifdef USE_OBJECTIVE // This will be used to help get scale factors double * objective = new double[numberColumns]; CoinMemcpyN(model->costRegion(1), numberColumns, objective); double objScale = 1.0; #endif while (numberPass) { overallLargest = 0.0; overallSmallest = 1.0e50; numberPass--; // Geometric mean on row scales for (iRow = 0; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } rowScale[iRow] = 1.0 / sqrt(smallest * largest); //rowScale[iRow]=CoinMax(1.0e-10,CoinMin(1.0e10,rowScale[iRow])); if (extraDetails) { overallLargest = CoinMax(largest * rowScale[iRow], overallLargest); overallSmallest = CoinMin(smallest * rowScale[iRow], overallSmallest); } } } #ifdef USE_OBJECTIVE largest = 1.0e-20; smallest = 1.0e50; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { double value = fabs(objective[iColumn]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } objScale = 1.0 / sqrt(smallest * largest); #endif model->messageHandler()->message(CLP_PACKEDSCALE_WHILE, *model->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; // skip last column round if (numberPass == 1) break; // Geometric mean on column scales for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; double value = fabs(elementByColumn[j]); if (usefulRow[iRow]) { value *= rowScale[iRow]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } #ifdef USE_OBJECTIVE if (fabs(objective[iColumn]) > 1.0e-20) { double value = fabs(objective[iColumn]) * objScale; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } #endif columnScale[iColumn] = 1.0 / sqrt(smallest * largest); //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn])); } } } #ifdef USE_OBJECTIVE delete [] objective; printf("obj scale %g - use it if you want\n", objScale); #endif } // If ranges will make horrid then scale for (iRow = 0; iRow < numberRows; iRow++) { if (usefulRow[iRow]) { double difference = rowUpper[iRow] - rowLower[iRow]; double scaledDifference = difference * rowScale[iRow]; if (scaledDifference > tolerance && scaledDifference < 1.0e-4) { // make gap larger rowScale[iRow] *= 1.0e-4 / scaledDifference; rowScale[iRow] = CoinMax(1.0e-10, CoinMin(1.0e10, rowScale[iRow])); //printf("Row %d difference %g scaled diff %g => %g\n",iRow,difference, // scaledDifference,difference*rowScale[iRow]); } } } // final pass to scale columns so largest is reasonable // See what smallest will be if largest is 1.0 overallSmallest = 1.0e50; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; if(elementByColumn[j] && usefulRow[iRow]) { double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } if (overallSmallest * largest > smallest) overallSmallest = smallest / largest; } } if (scalingMethod == 1 || scalingMethod == 2) { finished = true; } else if (savedOverallRatio == 0.0 && scalingMethod != 4) { savedOverallRatio = overallSmallest; scalingMethod = 4; } else { assert (scalingMethod == 4); if (overallSmallest > 2.0 * savedOverallRatio) { finished = true; // geometric was better if (model->scalingFlag() == 4) { // If in Branch and bound change if ((model->specialOptions() & 1024) != 0) { model->scaling(2); } } } else { scalingMethod = 1; // redo equilibrium if (model->scalingFlag() == 4) { // If in Branch and bound change if ((model->specialOptions() & 1024) != 0) { model->scaling(1); } } } #if 0 if (extraDetails) { if (finished) printf("equilibrium ratio %g, geometric ratio %g , geo chosen\n", savedOverallRatio, overallSmallest); else printf("equilibrium ratio %g, geometric ratio %g , equi chosen\n", savedOverallRatio, overallSmallest); } #endif } } //#define RANDOMIZE #ifdef RANDOMIZE // randomize by up to 10% for (iRow = 0; iRow < numberRows; iRow++) { double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 rowScale[iRow] *= (1.0 + 0.1 * value); } #endif overallLargest = 1.0; if (overallSmallest < 1.0e-1) overallLargest = 1.0 / sqrt(overallSmallest); overallLargest = CoinMin(100.0, overallLargest); overallSmallest = 1.0e50; //printf("scaling %d\n",model->scalingFlag()); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12) { //if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; if(elementByColumn[j] && usefulRow[iRow]) { double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } columnScale[iColumn] = overallLargest / largest; //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn])); #ifdef RANDOMIZE double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 columnScale[iColumn] *= (1.0 + 0.1 * value); #endif double difference = columnUpper[iColumn] - columnLower[iColumn]; if (difference < 1.0e-5 * columnScale[iColumn]) { // make gap larger columnScale[iColumn] = difference / 1.0e-5; //printf("Column %d difference %g scaled diff %g => %g\n",iColumn,difference, // scaledDifference,difference*columnScale[iColumn]); } double value = smallest * columnScale[iColumn]; if (overallSmallest > value) overallSmallest = value; //overallSmallest = CoinMin(overallSmallest,smallest*columnScale[iColumn]); } } model->messageHandler()->message(CLP_PACKEDSCALE_FINAL, *model->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; if (overallSmallest < 1.0e-13) { // Change factorization zero tolerance double newTolerance = CoinMax(1.0e-15 * (overallSmallest / 1.0e-13), 1.0e-18); ClpSimplex * simplex = static_cast (model); if (simplex->factorization()->zeroTolerance() > newTolerance) simplex->factorization()->zeroTolerance(newTolerance); newTolerance = CoinMax(overallSmallest * 0.5, 1.0e-18); simplex->setZeroTolerance(newTolerance); } delete [] usefulRow; delete [] usefulColumn; #ifndef SLIM_CLP // If quadratic then make symmetric ClpObjective * obj = model->objectiveAsObject(); #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj)); #else ClpQuadraticObjective * quadraticObj = NULL; if (obj->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(obj)); #endif if (quadraticObj) { if (!rowCopyBase) { // temporary copy rowCopyBase = reverseOrderedCopy(); } #ifndef NDEBUG ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); #else ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(rowCopyBase); #endif const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); int numberXColumns = quadratic->getNumCols(); if (numberXColumns < numberColumns) { // we assume symmetric int numberQuadraticColumns = 0; int i; //const int * columnQuadratic = quadratic->getIndices(); //const int * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); for (i = 0; i < numberXColumns; i++) { int length = columnQuadraticLength[i]; #ifndef CORRECT_COLUMN_COUNTS length = 1; #endif if (length) numberQuadraticColumns++; } int numberXRows = numberRows - numberQuadraticColumns; numberQuadraticColumns = 0; for (i = 0; i < numberXColumns; i++) { int length = columnQuadraticLength[i]; #ifndef CORRECT_COLUMN_COUNTS length = 1; #endif if (length) { rowScale[numberQuadraticColumns+numberXRows] = columnScale[i]; numberQuadraticColumns++; } } int numberQuadraticRows = 0; for (i = 0; i < numberXRows; i++) { // See if any in row quadratic CoinBigIndex j; int numberQ = 0; for (j = rowStart[i]; j < rowStart[i+1]; j++) { int iColumn = column[j]; if (columnQuadraticLength[iColumn]) numberQ++; } #ifndef CORRECT_ROW_COUNTS numberQ = 1; #endif if (numberQ) { columnScale[numberQuadraticRows+numberXColumns] = rowScale[i]; numberQuadraticRows++; } } // and make sure Sj okay for (iColumn = numberQuadraticRows + numberXColumns; iColumn < numberColumns; iColumn++) { CoinBigIndex j = columnStart[iColumn]; assert(columnLength[iColumn] == 1); int iRow = row[j]; double value = fabs(elementByColumn[j] * rowScale[iRow]); columnScale[iColumn] = 1.0 / value; } } } #endif // make copy (could do faster by using previous values) // could just do partial for (iRow = 0; iRow < numberRows; iRow++) inverseRowScale[iRow] = 1.0 / rowScale[iRow] ; for (iColumn = 0; iColumn < numberColumns; iColumn++) inverseColumnScale[iColumn] = 1.0 / columnScale[iColumn] ; if (!arraysExist) { model->setRowScale(rowScale); model->setColumnScale(columnScale); } if (model->rowCopy()) { // need to replace row by row ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(model->rowCopy()); double * element = rowCopy->getMutableElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); // scale row copy for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; double scale = rowScale[iRow]; double * elementsInThisRow = element + rowStart[iRow]; const int * columnsInThisRow = column + rowStart[iRow]; int number = rowStart[iRow+1] - rowStart[iRow]; assert (number <= numberColumns); for (j = 0; j < number; j++) { int iColumn = columnsInThisRow[j]; elementsInThisRow[j] *= scale * columnScale[iColumn]; } } if ((model->specialOptions() & 262144) != 0) { //if ((model->specialOptions()&(COIN_CBC_USING_CLP|16384))!=0) { //if (model->inCbcBranchAndBound()&&false) { // copy without gaps CoinPackedMatrix * scaledMatrix = new CoinPackedMatrix(*matrix_, 0, 0); ClpPackedMatrix * scaled = new ClpPackedMatrix(scaledMatrix); model->setClpScaledMatrix(scaled); // get matrix data pointers const int * row = scaledMatrix->getIndices(); const CoinBigIndex * columnStart = scaledMatrix->getVectorStarts(); #ifndef NDEBUG const int * columnLength = scaledMatrix->getVectorLengths(); #endif double * elementByColumn = scaledMatrix->getMutableElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double scale = columnScale[iColumn]; assert (columnStart[iColumn+1] == columnStart[iColumn] + columnLength[iColumn]); for (j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; elementByColumn[j] *= scale * rowScale[iRow]; } } } else { //printf("not in b&b\n"); } } else { // no row copy delete rowCopyBase; } return 0; } } #endif //#define SQRT_ARRAY #ifdef SQRT_ARRAY static void doSqrts(double * array, int n) { for (int i = 0; i < n; i++) array[i] = 1.0 / sqrt(array[i]); } #endif //static int scale_stats[5]={0,0,0,0,0}; // Creates scales for column copy (rowCopy in model may be modified) int ClpPackedMatrix::scale(ClpModel * model, const ClpSimplex * /*baseModel*/) const { //const ClpSimplex * baseModel=NULL; //return scale2(model); #if 0 ClpMatrixBase * rowClone = NULL; if (model->rowCopy()) rowClone = model->rowCopy()->clone(); assert (!model->rowScale()); assert (!model->columnScale()); int returnCode = scale2(model); if (returnCode) return returnCode; #endif #ifndef NDEBUG //checkFlags(); #endif int numberRows = model->numberRows(); int numberColumns = matrix_->getNumCols(); model->setClpScaledMatrix(NULL); // get rid of any scaled matrix // If empty - return as sanityCheck will trap if (!numberRows || !numberColumns) { model->setRowScale(NULL); model->setColumnScale(NULL); return 1; } #if 0 // start fake double * rowScale2 = CoinCopyOfArray(model->rowScale(), numberRows); double * columnScale2 = CoinCopyOfArray(model->columnScale(), numberColumns); model->setRowScale(NULL); model->setColumnScale(NULL); model->setNewRowCopy(rowClone); #endif ClpMatrixBase * rowCopyBase = model->rowCopy(); double * rowScale; double * columnScale; //assert (!model->rowScale()); bool arraysExist; double * inverseRowScale = NULL; double * inverseColumnScale = NULL; if (!model->rowScale()) { rowScale = new double [numberRows*2]; columnScale = new double [numberColumns*2]; inverseRowScale = rowScale + numberRows; inverseColumnScale = columnScale + numberColumns; arraysExist = false; } else { rowScale = model->mutableRowScale(); columnScale = model->mutableColumnScale(); inverseRowScale = model->mutableInverseRowScale(); inverseColumnScale = model->mutableInverseColumnScale(); arraysExist = true; } assert (inverseRowScale == rowScale + numberRows); assert (inverseColumnScale == columnScale + numberColumns); // we are going to mark bits we are interested in char * usefulColumn = new char [numberColumns]; double * rowLower = model->rowLower(); double * rowUpper = model->rowUpper(); double * columnLower = model->columnLower(); double * columnUpper = model->columnUpper(); int iColumn, iRow; //#define LEAVE_FIXED // mark empty and fixed columns // also see if worth scaling assert (model->scalingFlag() <= 5); // scale_stats[model->scalingFlag()]++; double largest = 0.0; double smallest = 1.0e50; // get matrix data pointers int * row = matrix_->getMutableIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); int * columnLength = matrix_->getMutableVectorLengths(); double * elementByColumn = matrix_->getMutableElements(); int deletedElements = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; char useful = 0; bool deleteSome = false; int start = columnStart[iColumn]; int end = start + columnLength[iColumn]; #ifndef LEAVE_FIXED if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12) { #endif for (j = start; j < end; j++) { iRow = row[j]; double value = fabs(elementByColumn[j]); if (value > 1.0e-20) { useful = 1; largest = CoinMax(largest, fabs(elementByColumn[j])); smallest = CoinMin(smallest, fabs(elementByColumn[j])); } else { // small deleteSome = true; } } #ifndef LEAVE_FIXED } else { // just check values for (j = start; j < end; j++) { double value = fabs(elementByColumn[j]); if (value <= 1.0e-20) { // small deleteSome = true; } } } #endif usefulColumn[iColumn] = useful; if (deleteSome) { CoinBigIndex put = start; for (j = start; j < end; j++) { double value = elementByColumn[j]; if (fabs(value) > 1.0e-20) { row[put] = row[j]; elementByColumn[put++] = value; } } deletedElements += end - put; columnLength[iColumn] = put - start; } } if (deletedElements) { matrix_->setNumElements(matrix_->getNumElements()-deletedElements); flags_ |= 0x02 ; } model->messageHandler()->message(CLP_PACKEDSCALE_INITIAL, *model->messagesPointer()) << smallest << largest << CoinMessageEol; if (smallest >= 0.5 && largest <= 2.0 && !deletedElements) { // don't bother scaling model->messageHandler()->message(CLP_PACKEDSCALE_FORGET, *model->messagesPointer()) << CoinMessageEol; if (!arraysExist) { delete [] rowScale; delete [] columnScale; } else { model->setRowScale(NULL); model->setColumnScale(NULL); } delete [] usefulColumn; return 1; } else { #ifdef CLP_INVESTIGATE if (deletedElements) printf("DEL_ELS\n"); #endif if (!rowCopyBase) { // temporary copy rowCopyBase = reverseOrderedCopy(); } else if (deletedElements) { rowCopyBase = reverseOrderedCopy(); model->setNewRowCopy(rowCopyBase); } #ifndef NDEBUG ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); #else ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(rowCopyBase); #endif const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * element = rowCopy->getElements(); // need to scale if (largest > 1.0e13 * smallest) { // safer to have smaller zero tolerance double ratio = smallest / largest; ClpSimplex * simplex = static_cast (model); double newTolerance = CoinMax(ratio * 0.5, 1.0e-18); if (simplex->zeroTolerance() > newTolerance) simplex->setZeroTolerance(newTolerance); } int scalingMethod = model->scalingFlag(); if (scalingMethod == 4) { // As auto scalingMethod = 3; } else if (scalingMethod == 5) { // As geometric scalingMethod = 2; } double savedOverallRatio = 0.0; double tolerance = 5.0 * model->primalTolerance(); double overallLargest = -1.0e-20; double overallSmallest = 1.0e20; bool finished = false; // if scalingMethod 3 then may change bool extraDetails = (model->logLevel() > 2); #if 0 for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12 && columnLength[iColumn]) assert(usefulColumn[iColumn]!=0); else assert(usefulColumn[iColumn]==0); } #endif while (!finished) { int numberPass = 3; overallLargest = -1.0e-20; overallSmallest = 1.0e20; ClpFillN ( rowScale, numberRows, 1.0); ClpFillN ( columnScale, numberColumns, 1.0); if (scalingMethod == 1 || scalingMethod == 3) { // Maximum in each row for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; largest = 1.0e-10; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); largest = CoinMax(largest, value); assert (largest < 1.0e40); } } rowScale[iRow] = 1.0 / largest; #ifdef COIN_DEVELOP if (extraDetails) { overallLargest = CoinMax(overallLargest, largest); overallSmallest = CoinMin(overallSmallest, largest); } #endif } } else { #ifdef USE_OBJECTIVE // This will be used to help get scale factors double * objective = new double[numberColumns]; CoinMemcpyN(model->costRegion(1), numberColumns, objective); double objScale = 1.0; #endif while (numberPass) { overallLargest = 0.0; overallSmallest = 1.0e50; numberPass--; // Geometric mean on row scales for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; largest = 1.0e-50; smallest = 1.0e50; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; if (usefulColumn[iColumn]) { double value = fabs(element[j]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } #ifdef SQRT_ARRAY rowScale[iRow] = smallest * largest; #else rowScale[iRow] = 1.0 / sqrt(smallest * largest); #endif //rowScale[iRow]=CoinMax(1.0e-10,CoinMin(1.0e10,rowScale[iRow])); if (extraDetails) { overallLargest = CoinMax(largest * rowScale[iRow], overallLargest); overallSmallest = CoinMin(smallest * rowScale[iRow], overallSmallest); } } if (model->scalingFlag() == 5) break; // just scale rows #ifdef SQRT_ARRAY doSqrts(rowScale, numberRows); #endif #ifdef USE_OBJECTIVE largest = 1.0e-20; smallest = 1.0e50; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { double value = fabs(objective[iColumn]); value *= columnScale[iColumn]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } } objScale = 1.0 / sqrt(smallest * largest); #endif model->messageHandler()->message(CLP_PACKEDSCALE_WHILE, *model->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; // skip last column round if (numberPass == 1) break; // Geometric mean on column scales for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-50; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; double value = fabs(elementByColumn[j]); value *= rowScale[iRow]; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } #ifdef USE_OBJECTIVE if (fabs(objective[iColumn]) > 1.0e-20) { double value = fabs(objective[iColumn]) * objScale; largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } #endif #ifdef SQRT_ARRAY columnScale[iColumn] = smallest * largest; #else columnScale[iColumn] = 1.0 / sqrt(smallest * largest); #endif //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn])); } } #ifdef SQRT_ARRAY doSqrts(columnScale, numberColumns); #endif } #ifdef USE_OBJECTIVE delete [] objective; printf("obj scale %g - use it if you want\n", objScale); #endif } // If ranges will make horrid then scale for (iRow = 0; iRow < numberRows; iRow++) { double difference = rowUpper[iRow] - rowLower[iRow]; double scaledDifference = difference * rowScale[iRow]; if (scaledDifference > tolerance && scaledDifference < 1.0e-4) { // make gap larger rowScale[iRow] *= 1.0e-4 / scaledDifference; rowScale[iRow] = CoinMax(1.0e-10, CoinMin(1.0e10, rowScale[iRow])); //printf("Row %d difference %g scaled diff %g => %g\n",iRow,difference, // scaledDifference,difference*rowScale[iRow]); } } // final pass to scale columns so largest is reasonable // See what smallest will be if largest is 1.0 if (model->scalingFlag() != 5) { overallSmallest = 1.0e50; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } if (overallSmallest * largest > smallest) overallSmallest = smallest / largest; } } } if (scalingMethod == 1 || scalingMethod == 2) { finished = true; } else if (savedOverallRatio == 0.0 && scalingMethod != 4) { savedOverallRatio = overallSmallest; scalingMethod = 4; } else { assert (scalingMethod == 4); if (overallSmallest > 2.0 * savedOverallRatio) { finished = true; // geometric was better if (model->scalingFlag() == 4) { // If in Branch and bound change if ((model->specialOptions() & 1024) != 0) { model->scaling(2); } } } else { scalingMethod = 1; // redo equilibrium if (model->scalingFlag() == 4) { // If in Branch and bound change if ((model->specialOptions() & 1024) != 0) { model->scaling(1); } } } #if 0 if (extraDetails) { if (finished) printf("equilibrium ratio %g, geometric ratio %g , geo chosen\n", savedOverallRatio, overallSmallest); else printf("equilibrium ratio %g, geometric ratio %g , equi chosen\n", savedOverallRatio, overallSmallest); } #endif } } //#define RANDOMIZE #ifdef RANDOMIZE // randomize by up to 10% for (iRow = 0; iRow < numberRows; iRow++) { double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 rowScale[iRow] *= (1.0 + 0.1 * value); } #endif overallLargest = 1.0; if (overallSmallest < 1.0e-1) overallLargest = 1.0 / sqrt(overallSmallest); overallLargest = CoinMin(100.0, overallLargest); overallSmallest = 1.0e50; char * usedRow = reinterpret_cast(inverseRowScale); memset(usedRow, 0, numberRows); //printf("scaling %d\n",model->scalingFlag()); if (model->scalingFlag() != 5) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] > columnLower[iColumn] + 1.0e-12) { //if (usefulColumn[iColumn]) { CoinBigIndex j; largest = 1.0e-20; smallest = 1.0e50; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { iRow = row[j]; usedRow[iRow] = 1; double value = fabs(elementByColumn[j] * rowScale[iRow]); largest = CoinMax(largest, value); smallest = CoinMin(smallest, value); } columnScale[iColumn] = overallLargest / largest; //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn])); #ifdef RANDOMIZE double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5 columnScale[iColumn] *= (1.0 + 0.1 * value); #endif double difference = columnUpper[iColumn] - columnLower[iColumn]; if (difference < 1.0e-5 * columnScale[iColumn]) { // make gap larger columnScale[iColumn] = difference / 1.0e-5; //printf("Column %d difference %g scaled diff %g => %g\n",iColumn,difference, // scaledDifference,difference*columnScale[iColumn]); } double value = smallest * columnScale[iColumn]; if (overallSmallest > value) overallSmallest = value; //overallSmallest = CoinMin(overallSmallest,smallest*columnScale[iColumn]); } else { assert(columnScale[iColumn] == 1.0); //columnScale[iColumn]=1.0; } } for (iRow = 0; iRow < numberRows; iRow++) { if (!usedRow[iRow]) { rowScale[iRow] = 1.0; } } } model->messageHandler()->message(CLP_PACKEDSCALE_FINAL, *model->messagesPointer()) << overallSmallest << overallLargest << CoinMessageEol; #if 0 { for (iRow = 0; iRow < numberRows; iRow++) { assert (rowScale[iRow] == rowScale2[iRow]); } delete [] rowScale2; for (iColumn = 0; iColumn < numberColumns; iColumn++) { assert (columnScale[iColumn] == columnScale2[iColumn]); } delete [] columnScale2; } #endif if (overallSmallest < 1.0e-13) { // Change factorization zero tolerance double newTolerance = CoinMax(1.0e-15 * (overallSmallest / 1.0e-13), 1.0e-18); ClpSimplex * simplex = static_cast (model); if (simplex->factorization()->zeroTolerance() > newTolerance) simplex->factorization()->zeroTolerance(newTolerance); newTolerance = CoinMax(overallSmallest * 0.5, 1.0e-18); simplex->setZeroTolerance(newTolerance); } delete [] usefulColumn; #ifndef SLIM_CLP // If quadratic then make symmetric ClpObjective * obj = model->objectiveAsObject(); #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj)); #else ClpQuadraticObjective * quadraticObj = NULL; if (obj->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(obj)); #endif if (quadraticObj) { if (!rowCopyBase) { // temporary copy rowCopyBase = reverseOrderedCopy(); } #ifndef NDEBUG ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); #else ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(rowCopyBase); #endif const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); int numberXColumns = quadratic->getNumCols(); if (numberXColumns < numberColumns) { // we assume symmetric int numberQuadraticColumns = 0; int i; //const int * columnQuadratic = quadratic->getIndices(); //const int * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); for (i = 0; i < numberXColumns; i++) { int length = columnQuadraticLength[i]; #ifndef CORRECT_COLUMN_COUNTS length = 1; #endif if (length) numberQuadraticColumns++; } int numberXRows = numberRows - numberQuadraticColumns; numberQuadraticColumns = 0; for (i = 0; i < numberXColumns; i++) { int length = columnQuadraticLength[i]; #ifndef CORRECT_COLUMN_COUNTS length = 1; #endif if (length) { rowScale[numberQuadraticColumns+numberXRows] = columnScale[i]; numberQuadraticColumns++; } } int numberQuadraticRows = 0; for (i = 0; i < numberXRows; i++) { // See if any in row quadratic CoinBigIndex j; int numberQ = 0; for (j = rowStart[i]; j < rowStart[i+1]; j++) { int iColumn = column[j]; if (columnQuadraticLength[iColumn]) numberQ++; } #ifndef CORRECT_ROW_COUNTS numberQ = 1; #endif if (numberQ) { columnScale[numberQuadraticRows+numberXColumns] = rowScale[i]; numberQuadraticRows++; } } // and make sure Sj okay for (iColumn = numberQuadraticRows + numberXColumns; iColumn < numberColumns; iColumn++) { CoinBigIndex j = columnStart[iColumn]; assert(columnLength[iColumn] == 1); int iRow = row[j]; double value = fabs(elementByColumn[j] * rowScale[iRow]); columnScale[iColumn] = 1.0 / value; } } } #endif // make copy (could do faster by using previous values) // could just do partial for (iRow = 0; iRow < numberRows; iRow++) inverseRowScale[iRow] = 1.0 / rowScale[iRow] ; for (iColumn = 0; iColumn < numberColumns; iColumn++) inverseColumnScale[iColumn] = 1.0 / columnScale[iColumn] ; if (!arraysExist) { model->setRowScale(rowScale); model->setColumnScale(columnScale); } if (model->rowCopy()) { // need to replace row by row ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(model->rowCopy()); double * element = rowCopy->getMutableElements(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); // scale row copy for (iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; double scale = rowScale[iRow]; double * elementsInThisRow = element + rowStart[iRow]; const int * columnsInThisRow = column + rowStart[iRow]; int number = rowStart[iRow+1] - rowStart[iRow]; assert (number <= numberColumns); for (j = 0; j < number; j++) { int iColumn = columnsInThisRow[j]; elementsInThisRow[j] *= scale * columnScale[iColumn]; } } if ((model->specialOptions() & 262144) != 0) { //if ((model->specialOptions()&(COIN_CBC_USING_CLP|16384))!=0) { //if (model->inCbcBranchAndBound()&&false) { // copy without gaps CoinPackedMatrix * scaledMatrix = new CoinPackedMatrix(*matrix_, 0, 0); ClpPackedMatrix * scaled = new ClpPackedMatrix(scaledMatrix); model->setClpScaledMatrix(scaled); // get matrix data pointers const int * row = scaledMatrix->getIndices(); const CoinBigIndex * columnStart = scaledMatrix->getVectorStarts(); #ifndef NDEBUG const int * columnLength = scaledMatrix->getVectorLengths(); #endif double * elementByColumn = scaledMatrix->getMutableElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double scale = columnScale[iColumn]; assert (columnStart[iColumn+1] == columnStart[iColumn] + columnLength[iColumn]); for (j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; elementByColumn[j] *= scale * rowScale[iRow]; } } } else { //printf("not in b&b\n"); } } else { // no row copy delete rowCopyBase; } return 0; } } // Creates scaled column copy if scales exist void ClpPackedMatrix::createScaledMatrix(ClpSimplex * model) const { int numberRows = model->numberRows(); int numberColumns = matrix_->getNumCols(); model->setClpScaledMatrix(NULL); // get rid of any scaled matrix // If empty - return as sanityCheck will trap if (!numberRows || !numberColumns) { model->setRowScale(NULL); model->setColumnScale(NULL); return ; } if (!model->rowScale()) return; double * rowScale = model->mutableRowScale(); double * columnScale = model->mutableColumnScale(); // copy without gaps CoinPackedMatrix * scaledMatrix = new CoinPackedMatrix(*matrix_, 0, 0); ClpPackedMatrix * scaled = new ClpPackedMatrix(scaledMatrix); model->setClpScaledMatrix(scaled); // get matrix data pointers const int * row = scaledMatrix->getIndices(); const CoinBigIndex * columnStart = scaledMatrix->getVectorStarts(); #ifndef NDEBUG const int * columnLength = scaledMatrix->getVectorLengths(); #endif double * elementByColumn = scaledMatrix->getMutableElements(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double scale = columnScale[iColumn]; assert (columnStart[iColumn+1] == columnStart[iColumn] + columnLength[iColumn]); for (j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; elementByColumn[j] *= scale * rowScale[iRow]; } } #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } /* Unpacks a column into an CoinIndexedvector */ void ClpPackedMatrix::unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn) const { const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); CoinBigIndex i; if (!rowScale) { for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { rowArray->quickAdd(row[i], elementByColumn[i]); } } else { // apply scaling double scale = model->columnScale()[iColumn]; for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; rowArray->quickAdd(iRow, elementByColumn[i]*scale * rowScale[iRow]); } } } /* Unpacks a column into a CoinIndexedVector ** in packed format Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ void ClpPackedMatrix::unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn) const { const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); CoinBigIndex i; int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); int number = 0; if (!rowScale) { for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; double value = elementByColumn[i]; if (value) { array[number] = value; index[number++] = iRow; } } rowArray->setNumElements(number); rowArray->setPackedMode(true); } else { // apply scaling double scale = model->columnScale()[iColumn]; for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; double value = elementByColumn[i] * scale * rowScale[iRow]; if (value) { array[number] = value; index[number++] = iRow; } } rowArray->setNumElements(number); rowArray->setPackedMode(true); } } /* Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ void ClpPackedMatrix::add(const ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn, double multiplier) const { const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); CoinBigIndex i; if (!rowScale) { for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; rowArray->quickAdd(iRow, multiplier * elementByColumn[i]); } } else { // apply scaling double scale = model->columnScale()[iColumn] * multiplier; for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; rowArray->quickAdd(iRow, elementByColumn[i]*scale * rowScale[iRow]); } } } /* Adds multiple of a column into an array */ void ClpPackedMatrix::add(const ClpSimplex * model, double * array, int iColumn, double multiplier) const { const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); CoinBigIndex i; if (!rowScale) { for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; array[iRow] += multiplier * elementByColumn[i]; } } else { // apply scaling double scale = model->columnScale()[iColumn] * multiplier; for (i = columnStart[iColumn]; i < columnStart[iColumn] + columnLength[iColumn]; i++) { int iRow = row[i]; array[iRow] += elementByColumn[i] * scale * rowScale[iRow]; } } } /* Checks if all elements are in valid range. Can just return true if you are not paranoid. For Clp I will probably expect no zeros. Code can modify matrix to get rid of small elements. check bits (can be turned off to save time) : 1 - check if matrix has gaps 2 - check if zero elements 4 - check and compress duplicates 8 - report on large and small */ bool ClpPackedMatrix::allElementsInRange(ClpModel * model, double smallest, double largest, int check) { int iColumn; // make sure matrix correct size assert (matrix_->getNumRows() <= model->numberRows()); if (model->clpScaledMatrix()) assert (model->clpScaledMatrix()->getNumElements() == matrix_->getNumElements()); assert (matrix_->getNumRows() <= model->numberRows()); matrix_->setDimensions(model->numberRows(), model->numberColumns()); CoinBigIndex numberLarge = 0;; CoinBigIndex numberSmall = 0;; CoinBigIndex numberDuplicate = 0;; int firstBadColumn = -1; int firstBadRow = -1; double firstBadElement = 0.0; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); int numberRows = model->numberRows(); int numberColumns = matrix_->getNumCols(); // Say no gaps flags_ &= ~2; if (type_>=10) return true; // gub if (check == 14 || check == 10) { if (matrix_->getNumElements() < columnStart[numberColumns]) { // pack down! #if 0 matrix_->removeGaps(); #else checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif #endif #ifdef COIN_DEVELOP //printf("flags set to 2\n"); #endif } else if (numberColumns) { assert(columnStart[numberColumns] == columnStart[numberColumns-1] + columnLength[numberColumns-1]); } return true; } assert (check == 15 || check == 11); if (check == 15) { int * mark = new int [numberRows]; int i; for (i = 0; i < numberRows; i++) mark[i] = -1; for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; if (end != columnStart[iColumn+1]) flags_ |= 2; for (j = start; j < end; j++) { double value = fabs(elementByColumn[j]); int iRow = row[j]; if (iRow < 0 || iRow >= numberRows) { #ifndef COIN_BIG_INDEX printf("Out of range %d %d %d %g\n", iColumn, j, row[j], elementByColumn[j]); #elif COIN_BIG_INDEX==0 printf("Out of range %d %d %d %g\n", iColumn, j, row[j], elementByColumn[j]); #elif COIN_BIG_INDEX==1 printf("Out of range %d %ld %d %g\n", iColumn, j, row[j], elementByColumn[j]); #else printf("Out of range %d %lld %d %g\n", iColumn, j, row[j], elementByColumn[j]); #endif return false; } if (mark[iRow] == -1) { mark[iRow] = j; } else { // duplicate numberDuplicate++; } //printf("%d %d %d %g\n",iColumn,j,row[j],elementByColumn[j]); if (!value) flags_ |= 1; // there are zero elements if (value < smallest) { numberSmall++; } else if (!(value <= largest)) { numberLarge++; if (firstBadColumn < 0) { firstBadColumn = iColumn; firstBadRow = row[j]; firstBadElement = elementByColumn[j]; } } } //clear mark for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; mark[iRow] = -1; } } delete [] mark; } else { // just check for out of range - not for duplicates for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; if (end != columnStart[iColumn+1]) flags_ |= 2; for (j = start; j < end; j++) { double value = fabs(elementByColumn[j]); int iRow = row[j]; if (iRow < 0 || iRow >= numberRows) { #ifndef COIN_BIG_INDEX printf("Out of range %d %d %d %g\n", iColumn, j, row[j], elementByColumn[j]); #elif COIN_BIG_INDEX==0 printf("Out of range %d %d %d %g\n", iColumn, j, row[j], elementByColumn[j]); #elif COIN_BIG_INDEX==1 printf("Out of range %d %ld %d %g\n", iColumn, j, row[j], elementByColumn[j]); #else printf("Out of range %d %lld %d %g\n", iColumn, j, row[j], elementByColumn[j]); #endif return false; } if (!value) flags_ |= 1; // there are zero elements if (value < smallest) { numberSmall++; } else if (!(value <= largest)) { numberLarge++; if (firstBadColumn < 0) { firstBadColumn = iColumn; firstBadRow = iRow; firstBadElement = value; } } } } } if (numberLarge) { model->messageHandler()->message(CLP_BAD_MATRIX, model->messages()) << numberLarge << firstBadColumn << firstBadRow << firstBadElement << CoinMessageEol; return false; } if (numberSmall) model->messageHandler()->message(CLP_SMALLELEMENTS, model->messages()) << numberSmall << CoinMessageEol; if (numberDuplicate) model->messageHandler()->message(CLP_DUPLICATEELEMENTS, model->messages()) << numberDuplicate << CoinMessageEol; if (numberDuplicate) matrix_->eliminateDuplicates(smallest); else if (numberSmall) matrix_->compress(smallest); // If smallest >0.0 then there can't be zero elements if (smallest > 0.0) flags_ &= ~1;; if (numberSmall || numberDuplicate) flags_ |= 2; // will have gaps return true; } int ClpPackedMatrix::gutsOfTransposeTimesByRowGE3a(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, int * COIN_RESTRICT lookup, char * COIN_RESTRICT marked, const double tolerance, const double scalar) const { const double * COIN_RESTRICT pi = piVector->denseVector(); int numberNonZero = 0; int numberInRowArray = piVector->getNumElements(); const int * COIN_RESTRICT column = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT element = matrix_->getElements(); const int * COIN_RESTRICT whichRow = piVector->getIndices(); int * fakeRow = const_cast (whichRow); fakeRow[numberInRowArray]=0; // so can touch #ifndef NDEBUG int maxColumn = 0; #endif // ** Row copy is already scaled int nextRow=whichRow[0]; CoinBigIndex nextStart = rowStart[nextRow]; CoinBigIndex nextEnd = rowStart[nextRow+1]; for (int i = 0; i < numberInRowArray; i++) { double value = pi[i] * scalar; CoinBigIndex start=nextStart; CoinBigIndex end=nextEnd; nextRow=whichRow[i+1]; nextStart = rowStart[nextRow]; //coin_prefetch_const(column + nextStart); //coin_prefetch_const(element + nextStart); nextEnd = rowStart[nextRow+1]; CoinBigIndex j; for (j = start; j < end; j++) { int iColumn = column[j]; #ifndef NDEBUG maxColumn = CoinMax(maxColumn, iColumn); #endif double elValue = element[j]; elValue *= value; if (marked[iColumn]) { int k = lookup[iColumn]; output[k] += elValue; } else { output[numberNonZero] = elValue; marked[iColumn] = 1; lookup[iColumn] = numberNonZero; index[numberNonZero++] = iColumn; } } } #ifndef NDEBUG int saveN = numberNonZero; #endif // get rid of tiny values and zero out lookup for (int i = 0; i < numberNonZero; i++) { int iColumn = index[i]; marked[iColumn] = 0; double value = output[i]; if (fabs(value) <= tolerance) { while (fabs(value) <= tolerance) { numberNonZero--; value = output[numberNonZero]; iColumn = index[numberNonZero]; marked[iColumn] = 0; if (i < numberNonZero) { output[numberNonZero] = 0.0; output[i] = value; index[i] = iColumn; } else { output[i] = 0.0; value = 1.0; // to force end of while } } } } #ifndef NDEBUG for (int i = numberNonZero; i < saveN; i++) assert(!output[i]); for (int i = 0; i <= maxColumn; i++) assert (!marked[i]); #endif return numberNonZero; } int ClpPackedMatrix::gutsOfTransposeTimesByRowGE3(const CoinIndexedVector * COIN_RESTRICT piVector, int * COIN_RESTRICT index, double * COIN_RESTRICT output, double * COIN_RESTRICT array, const double tolerance, const double scalar) const { const double * COIN_RESTRICT pi = piVector->denseVector(); int numberNonZero = 0; int numberInRowArray = piVector->getNumElements(); const int * COIN_RESTRICT column = matrix_->getIndices(); const CoinBigIndex * COIN_RESTRICT rowStart = matrix_->getVectorStarts(); const double * COIN_RESTRICT element = matrix_->getElements(); const int * COIN_RESTRICT whichRow = piVector->getIndices(); // ** Row copy is already scaled for (int i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; double value = pi[i] * scalar; CoinBigIndex j; for (j = rowStart[iRow]; j < rowStart[iRow+1]; j++) { int iColumn = column[j]; double inValue = array[iColumn]; double elValue = element[j]; elValue *= value; if (inValue) { double outValue = inValue + elValue; if (!outValue) outValue = COIN_INDEXED_REALLY_TINY_ELEMENT; array[iColumn] = outValue; } else { array[iColumn] = elValue; assert (elValue); index[numberNonZero++] = iColumn; } } } int saveN = numberNonZero; // get rid of tiny values numberNonZero=0; for (int i = 0; i < saveN; i++) { int iColumn = index[i]; double value = array[iColumn]; array[iColumn] =0.0; if (fabs(value) > tolerance) { output[numberNonZero] = value; index[numberNonZero++] = iColumn; } } return numberNonZero; } /* Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ CoinBigIndex * ClpPackedMatrix::dubiousWeights(const ClpSimplex * model, int * inputWeights) const { int numberRows = model->numberRows(); int numberColumns = matrix_->getNumCols(); int number = numberRows + numberColumns; CoinBigIndex * weights = new CoinBigIndex[number]; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); int i; for (i = 0; i < numberColumns; i++) { CoinBigIndex j; CoinBigIndex count = 0; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; count += inputWeights[iRow]; } weights[i] = count; } for (i = 0; i < numberRows; i++) { weights[i+numberColumns] = inputWeights[i]; } return weights; } /* Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ void ClpPackedMatrix::rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive) { smallestNegative = -COIN_DBL_MAX; largestNegative = 0.0; smallestPositive = COIN_DBL_MAX; largestPositive = 0.0; // get matrix data pointers const double * elementByColumn = matrix_->getElements(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); int numberColumns = matrix_->getNumCols(); int i; for (i = 0; i < numberColumns; i++) { CoinBigIndex j; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { double value = elementByColumn[j]; if (value > 0.0) { smallestPositive = CoinMin(smallestPositive, value); largestPositive = CoinMax(largestPositive, value); } else if (value < 0.0) { smallestNegative = CoinMax(smallestNegative, value); largestNegative = CoinMin(largestNegative, value); } } } } // Says whether it can do partial pricing bool ClpPackedMatrix::canDoPartialPricing() const { return true; } // Partial pricing void ClpPackedMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; int start = static_cast (startFraction * numberActiveColumns_); int end = CoinMin(static_cast (endFraction * numberActiveColumns_ + 1), numberActiveColumns_); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); const double * rowScale = model->rowScale(); const double * columnScale = model->columnScale(); int iSequence; CoinBigIndex j; double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); const double * cost = model->costRegion(); double bestDj; if (bestSequence >= 0) bestDj = fabs(model->clpMatrix()->reducedCost(model, bestSequence)); else bestDj = tolerance; int sequenceOut = model->sequenceOut(); int saveSequence = bestSequence; int lastScan = minimumObjectsScan_ < 0 ? end : start + minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ == -1 ? numberWanted : minimumGoodReducedCosts_; if (rowScale) { // scaled for (iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = 0.0; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = fabs(cost[iSequence] + value * columnScale[iSequence]); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = 0.0; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = cost[iSequence] + value * columnScale[iSequence]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = 0.0; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = -(cost[iSequence] + value * columnScale[iSequence]); if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (numberWanted + minNeg < originalWanted_ && iSequence > lastScan) { // give up break; } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = 0.0; // scaled for (j = startColumn[bestSequence]; j < startColumn[bestSequence] + length[bestSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } reducedCost[bestSequence] = cost[bestSequence] + value * columnScale[bestSequence]; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } } else { // not scaled for (iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = cost[iSequence]; for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence]; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = cost[iSequence]; for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (numberWanted + minNeg < originalWanted_ && iSequence > lastScan) { // give up break; } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = cost[bestSequence]; for (j = startColumn[bestSequence]; j < startColumn[bestSequence] + length[bestSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } reducedCost[bestSequence] = value; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } } currentWanted_ = numberWanted; } // Sets up an effective RHS void ClpPackedMatrix::useEffectiveRhs(ClpSimplex * model) { delete [] rhsOffset_; int numberRows = model->numberRows(); rhsOffset_ = new double[numberRows]; rhsOffset(model, true); } // Gets rid of special copies void ClpPackedMatrix::clearCopies() { delete rowCopy_; delete columnCopy_; rowCopy_ = NULL; columnCopy_ = NULL; flags_ &= ~(4 + 8); checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } // makes sure active columns correct int ClpPackedMatrix::refresh(ClpSimplex * ) { numberActiveColumns_ = matrix_->getNumCols(); #if 0 ClpMatrixBase * rowCopyBase = reverseOrderedCopy(); ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); const int * column = rowCopy->matrix_->getIndices(); const CoinBigIndex * rowStart = rowCopy->matrix_->getVectorStarts(); const int * rowLength = rowCopy->matrix_->getVectorLengths(); const double * element = rowCopy->matrix_->getElements(); int numberRows = rowCopy->matrix_->getNumRows(); for (int i = 0; i < numberRows; i++) { if (!rowLength[i]) printf("zero row %d\n", i); } delete rowCopy; #endif checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif return 0; } /* Scales rowCopy if column copy scaled Only called if scales already exist */ void ClpPackedMatrix::scaleRowCopy(ClpModel * model) const { if (model->rowCopy()) { // need to replace row by row int numberRows = model->numberRows(); #ifndef NDEBUG int numberColumns = matrix_->getNumCols(); #endif ClpMatrixBase * rowCopyBase = model->rowCopy(); #ifndef NDEBUG ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(rowCopyBase); // Make sure it is really a ClpPackedMatrix assert (rowCopy != NULL); #else ClpPackedMatrix* rowCopy = static_cast< ClpPackedMatrix*>(rowCopyBase); #endif const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); double * element = rowCopy->getMutableElements(); const double * rowScale = model->rowScale(); const double * columnScale = model->columnScale(); // scale row copy for (int iRow = 0; iRow < numberRows; iRow++) { CoinBigIndex j; double scale = rowScale[iRow]; double * elementsInThisRow = element + rowStart[iRow]; const int * columnsInThisRow = column + rowStart[iRow]; int number = rowStart[iRow+1] - rowStart[iRow]; assert (number <= numberColumns); for (j = 0; j < number; j++) { int iColumn = columnsInThisRow[j]; elementsInThisRow[j] *= scale * columnScale[iColumn]; } } } } /* Realy really scales column copy Only called if scales already exist. Up to user ro delete */ ClpMatrixBase * ClpPackedMatrix::scaledColumnCopy(ClpModel * model) const { // need to replace column by column #ifndef NDEBUG int numberRows = model->numberRows(); #endif int numberColumns = matrix_->getNumCols(); ClpPackedMatrix * copy = new ClpPackedMatrix(*this); const int * row = copy->getIndices(); const CoinBigIndex * columnStart = copy->getVectorStarts(); const int * length = copy->getVectorLengths(); double * element = copy->getMutableElements(); const double * rowScale = model->rowScale(); const double * columnScale = model->columnScale(); // scale column copy for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double scale = columnScale[iColumn]; double * elementsInThisColumn = element + columnStart[iColumn]; const int * rowsInThisColumn = row + columnStart[iColumn]; int number = length[iColumn]; assert (number <= numberRows); for (j = 0; j < number; j++) { int iRow = rowsInThisColumn[j]; elementsInThisColumn[j] *= scale * rowScale[iRow]; } } return copy; } // Really scale matrix void ClpPackedMatrix::reallyScale(const double * rowScale, const double * columnScale) { clearCopies(); int numberColumns = matrix_->getNumCols(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); double * element = matrix_->getMutableElements(); // scale for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex j; double scale = columnScale[iColumn]; for (j = columnStart[iColumn]; j < columnStart[iColumn] + length[iColumn]; j++) { int iRow = row[j]; element[j] *= scale * rowScale[iRow]; } } } /* Delete the columns whose indices are listed in indDel. */ void ClpPackedMatrix::deleteCols(const int numDel, const int * indDel) { if (matrix_->getNumCols()) matrix_->deleteCols(numDel, indDel); clearCopies(); numberActiveColumns_ = matrix_->getNumCols(); // may now have gaps checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif matrix_->setExtraGap(0.0); } /* Delete the rows whose indices are listed in indDel. */ void ClpPackedMatrix::deleteRows(const int numDel, const int * indDel) { if (matrix_->getNumRows()) matrix_->deleteRows(numDel, indDel); clearCopies(); numberActiveColumns_ = matrix_->getNumCols(); // may now have gaps checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif matrix_->setExtraGap(0.0); } #ifndef CLP_NO_VECTOR // Append Columns void ClpPackedMatrix::appendCols(int number, const CoinPackedVectorBase * const * columns) { matrix_->appendCols(number, columns); numberActiveColumns_ = matrix_->getNumCols(); clearCopies(); } // Append Rows void ClpPackedMatrix::appendRows(int number, const CoinPackedVectorBase * const * rows) { matrix_->appendRows(number, rows); numberActiveColumns_ = matrix_->getNumCols(); // may now have gaps checkGaps(); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif clearCopies(); } #endif /* Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ void ClpPackedMatrix::setDimensions(int numrows, int numcols) { matrix_->setDimensions(numrows, numcols); #ifdef DO_CHECK_FLAGS checkFlags(0); #endif } /* Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ int ClpPackedMatrix::appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther) { int numberErrors = 0; // make sure other dimension is big enough if (type == 0) { // rows if (matrix_->isColOrdered() && numberOther > matrix_->getNumCols()) matrix_->setDimensions(-1, numberOther); if (!matrix_->isColOrdered() || numberOther >= 0 || matrix_->getExtraGap()) { numberErrors = matrix_->appendRows(number, starts, index, element, numberOther); } else { //CoinPackedMatrix mm(*matrix_); matrix_->appendMinorFast(number, starts, index, element); //mm.appendRows(number,starts,index,element,numberOther); //if (!mm.isEquivalent(*matrix_)) { //printf("bad append\n"); //abort(); //} } } else { // columns if (!matrix_->isColOrdered() && numberOther > matrix_->getNumRows()) matrix_->setDimensions(numberOther, -1); if (element) numberErrors = matrix_->appendCols(number, starts, index, element, numberOther); else matrix_->setDimensions(-1,matrix_->getNumCols()+number); // resize } clearCopies(); numberActiveColumns_ = matrix_->getNumCols(); return numberErrors; } void ClpPackedMatrix::specialRowCopy(ClpSimplex * model, const ClpMatrixBase * rowCopy) { delete rowCopy_; rowCopy_ = new ClpPackedMatrix2(model, rowCopy->getPackedMatrix()); // See if anything in it if (!rowCopy_->usefulInfo()) { delete rowCopy_; rowCopy_ = NULL; flags_ &= ~4; } else { flags_ |= 4; } } void ClpPackedMatrix::specialColumnCopy(ClpSimplex * model) { delete columnCopy_; if ((flags_ & 16) != 0) { columnCopy_ = new ClpPackedMatrix3(model, matrix_); flags_ |= 8; } else { columnCopy_ = NULL; } } // Say we don't want special column copy void ClpPackedMatrix::releaseSpecialColumnCopy() { flags_ &= ~(8 + 16); delete columnCopy_; columnCopy_ = NULL; } // Correct sequence in and out to give true value void ClpPackedMatrix::correctSequence(const ClpSimplex * model, int & sequenceIn, int & sequenceOut) { if (columnCopy_) { if (sequenceIn != -999) { if (sequenceIn != sequenceOut) { if (sequenceIn < numberActiveColumns_) columnCopy_->swapOne(model, this, sequenceIn); if (sequenceOut < numberActiveColumns_) columnCopy_->swapOne(model, this, sequenceOut); } } else { // do all columnCopy_->sortBlocks(model); } } } // Check validity void ClpPackedMatrix::checkFlags(int type) const { int iColumn; // get matrix data pointers //const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); if (!zeros()) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (!elementByColumn[j]) abort(); } } } if ((flags_ & 2) == 0) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { if (columnStart[iColumn+1] != columnStart[iColumn] + columnLength[iColumn]) { abort(); } } } if (type) { if ((flags_ & 2) != 0) { bool ok = true; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { if (columnStart[iColumn+1] != columnStart[iColumn] + columnLength[iColumn]) { ok = false; break; } } if (ok) COIN_DETAIL_PRINT(printf("flags_ could be 0\n")); } } } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPackedMatrix2::ClpPackedMatrix2 () : numberBlocks_(0), numberRows_(0), offset_(NULL), count_(NULL), rowStart_(NULL), column_(NULL), work_(NULL) { #ifdef THREAD threadId_ = NULL; info_ = NULL; #endif } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpPackedMatrix2::ClpPackedMatrix2 (ClpSimplex * , const CoinPackedMatrix * rowCopy) : numberBlocks_(0), numberRows_(0), offset_(NULL), count_(NULL), rowStart_(NULL), column_(NULL), work_(NULL) { #ifdef THREAD threadId_ = NULL; info_ = NULL; #endif numberRows_ = rowCopy->getNumRows(); if (!numberRows_) return; int numberColumns = rowCopy->getNumCols(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * length = rowCopy->getVectorLengths(); const double * element = rowCopy->getElements(); int chunk = 32768; // tune //chunk=100; // tune #if 0 int chunkY[7] = {1024, 2048, 4096, 8192, 16384, 32768, 65535}; int its = model->maximumIterations(); if (its >= 1000000 && its < 1000999) { its -= 1000000; its = its / 10; if (its >= 7) abort(); chunk = chunkY[its]; printf("chunk size %d\n", chunk); #define cpuid(func,ax,bx,cx,dx)\ __asm__ __volatile__ ("cpuid":\ "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func)); unsigned int a, b, c, d; int func = 0; cpuid(func, a, b, c, d); { int i; unsigned int value; value = b; for (i = 0; i < 4; i++) { printf("%c", (value & 0xff)); value = value >> 8; } value = d; for (i = 0; i < 4; i++) { printf("%c", (value & 0xff)); value = value >> 8; } value = c; for (i = 0; i < 4; i++) { printf("%c", (value & 0xff)); value = value >> 8; } printf("\n"); int maxfunc = a; if (maxfunc > 10) { printf("not intel?\n"); abort(); } for (func = 1; func <= maxfunc; func++) { cpuid(func, a, b, c, d); printf("func %d, %x %x %x %x\n", func, a, b, c, d); } } #else if (numberColumns > 10000 || chunk == 100) { #endif } else { //printf("no chunk\n"); return; } // Could also analyze matrix to get natural breaks numberBlocks_ = (numberColumns + chunk - 1) / chunk; #ifdef THREAD // Get work areas threadId_ = new pthread_t [numberBlocks_]; info_ = new dualColumn0Struct[numberBlocks_]; #endif // Even out chunk = (numberColumns + numberBlocks_ - 1) / numberBlocks_; offset_ = new int[numberBlocks_+1]; offset_[numberBlocks_] = numberColumns; int nRow = numberBlocks_ * numberRows_; count_ = new unsigned short[nRow]; memset(count_, 0, nRow * sizeof(unsigned short)); rowStart_ = new CoinBigIndex[nRow+numberRows_+1]; CoinBigIndex nElement = rowStart[numberRows_]; rowStart_[nRow+numberRows_] = nElement; column_ = new unsigned short [nElement]; // assumes int <= double int sizeWork = 6 * numberBlocks_; work_ = new double[sizeWork];; int iBlock; int nZero = 0; for (iBlock = 0; iBlock < numberBlocks_; iBlock++) { int start = iBlock * chunk; offset_[iBlock] = start; int end = start + chunk; for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowStart[iRow+1] != rowStart[iRow] + length[iRow]) { printf("not packed correctly - gaps\n"); abort(); } bool lastFound = false; int nFound = 0; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + length[iRow]; j++) { int iColumn = column[j]; if (iColumn >= start) { if (iColumn < end) { if (!element[j]) { printf("not packed correctly - zero element\n"); abort(); } column_[j] = static_cast(iColumn - start); nFound++; if (lastFound) { printf("not packed correctly - out of order\n"); abort(); } } else { //can't find any more lastFound = true; } } } count_[iRow*numberBlocks_+iBlock] = static_cast(nFound); if (!nFound) nZero++; } } //double fraction = ((double) nZero)/((double) (numberBlocks_*numberRows_)); //printf("%d empty blocks, %g%%\n",nZero,100.0*fraction); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPackedMatrix2::ClpPackedMatrix2 (const ClpPackedMatrix2 & rhs) : numberBlocks_(rhs.numberBlocks_), numberRows_(rhs.numberRows_) { if (numberBlocks_) { offset_ = CoinCopyOfArray(rhs.offset_, numberBlocks_ + 1); int nRow = numberBlocks_ * numberRows_; count_ = CoinCopyOfArray(rhs.count_, nRow); rowStart_ = CoinCopyOfArray(rhs.rowStart_, nRow + numberRows_ + 1); CoinBigIndex nElement = rowStart_[nRow+numberRows_]; column_ = CoinCopyOfArray(rhs.column_, nElement); int sizeWork = 6 * numberBlocks_; work_ = CoinCopyOfArray(rhs.work_, sizeWork); #ifdef THREAD threadId_ = new pthread_t [numberBlocks_]; info_ = new dualColumn0Struct[numberBlocks_]; #endif } else { offset_ = NULL; count_ = NULL; rowStart_ = NULL; column_ = NULL; work_ = NULL; #ifdef THREAD threadId_ = NULL; info_ = NULL; #endif } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPackedMatrix2::~ClpPackedMatrix2 () { delete [] offset_; delete [] count_; delete [] rowStart_; delete [] column_; delete [] work_; #ifdef THREAD delete [] threadId_; delete [] info_; #endif } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPackedMatrix2 & ClpPackedMatrix2::operator=(const ClpPackedMatrix2& rhs) { if (this != &rhs) { numberBlocks_ = rhs.numberBlocks_; numberRows_ = rhs.numberRows_; delete [] offset_; delete [] count_; delete [] rowStart_; delete [] column_; delete [] work_; #ifdef THREAD delete [] threadId_; delete [] info_; #endif if (numberBlocks_) { offset_ = CoinCopyOfArray(rhs.offset_, numberBlocks_ + 1); int nRow = numberBlocks_ * numberRows_; count_ = CoinCopyOfArray(rhs.count_, nRow); rowStart_ = CoinCopyOfArray(rhs.rowStart_, nRow + numberRows_ + 1); CoinBigIndex nElement = rowStart_[nRow+numberRows_]; column_ = CoinCopyOfArray(rhs.column_, nElement); int sizeWork = 6 * numberBlocks_; work_ = CoinCopyOfArray(rhs.work_, sizeWork); #ifdef THREAD threadId_ = new pthread_t [numberBlocks_]; info_ = new dualColumn0Struct[numberBlocks_]; #endif } else { offset_ = NULL; count_ = NULL; rowStart_ = NULL; column_ = NULL; work_ = NULL; #ifdef THREAD threadId_ = NULL; info_ = NULL; #endif } } return *this; } static int dualColumn0(const ClpSimplex * model, double * spare, int * spareIndex, const double * arrayTemp, const int * indexTemp, int numberIn, int offset, double acceptablePivot, double * bestPossiblePtr, double * upperThetaPtr, int * posFreePtr, double * freePivotPtr) { // do dualColumn0 int i; int numberRemaining = 0; double bestPossible = 0.0; double upperTheta = 1.0e31; double freePivot = acceptablePivot; int posFree = -1; const double * reducedCost = model->djRegion(1); double dualTolerance = model->dualTolerance(); // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; for (i = 0; i < numberIn; i++) { double alpha = arrayTemp[i]; int iSequence = indexTemp[i] + offset; double oldValue; double value; bool keep; switch(model->getStatus(iSequence)) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: bestPossible = CoinMax(bestPossible, fabs(alpha)); oldValue = reducedCost[iSequence]; // If free has to be very large - should come in via dualRow if (model->getStatus(iSequence) == ClpSimplex::isFree && fabs(alpha) < 1.0e-3) break; if (oldValue > dualTolerance) { keep = true; } else if (oldValue < -dualTolerance) { keep = true; } else { if (fabs(alpha) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) keep = true; else keep = false; } if (keep) { // free - choose largest if (fabs(alpha) > freePivot) { freePivot = fabs(alpha); posFree = i; } } break; case ClpSimplex::atUpperBound: oldValue = reducedCost[iSequence]; value = oldValue - tentativeTheta * alpha; //assert (oldValue<=dualTolerance*1.0001); if (value > dualTolerance) { bestPossible = CoinMax(bestPossible, -alpha); value = oldValue - upperTheta * alpha; if (value > dualTolerance && -alpha >= acceptablePivot) upperTheta = (oldValue - dualTolerance) / alpha; // add to list spare[numberRemaining] = alpha; spareIndex[numberRemaining++] = iSequence; } break; case ClpSimplex::atLowerBound: oldValue = reducedCost[iSequence]; value = oldValue - tentativeTheta * alpha; //assert (oldValue>=-dualTolerance*1.0001); if (value < -dualTolerance) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < -dualTolerance && alpha >= acceptablePivot) upperTheta = (oldValue + dualTolerance) / alpha; // add to list spare[numberRemaining] = alpha; spareIndex[numberRemaining++] = iSequence; } break; } } *bestPossiblePtr = bestPossible; *upperThetaPtr = upperTheta; *freePivotPtr = freePivot; *posFreePtr = posFree; return numberRemaining; } static int doOneBlock(double * array, int * index, const double * pi, const CoinBigIndex * rowStart, const double * element, const unsigned short * column, int numberInRowArray, int numberLook) { int iWhich = 0; int nextN = 0; CoinBigIndex nextStart = 0; double nextPi = 0.0; for (; iWhich < numberInRowArray; iWhich++) { nextStart = rowStart[0]; nextN = rowStart[numberInRowArray] - nextStart; rowStart++; if (nextN) { nextPi = pi[iWhich]; break; } } int i; while (iWhich < numberInRowArray) { double value = nextPi; CoinBigIndex j = nextStart; int n = nextN; // get next iWhich++; for (; iWhich < numberInRowArray; iWhich++) { nextStart = rowStart[0]; nextN = rowStart[numberInRowArray] - nextStart; rowStart++; if (nextN) { //coin_prefetch_const(element + nextStart); nextPi = pi[iWhich]; break; } } CoinBigIndex end = j + n; //coin_prefetch_const(element+rowStart_[i+1]); //coin_prefetch_const(column_+rowStart_[i+1]); if (n < 100) { if ((n & 1) != 0) { unsigned int jColumn = column[j]; array[jColumn] -= value * element[j]; j++; } //coin_prefetch_const(column + nextStart); for (; j < end; j += 2) { unsigned int jColumn0 = column[j]; double value0 = value * element[j]; unsigned int jColumn1 = column[j+1]; double value1 = value * element[j+1]; array[jColumn0] -= value0; array[jColumn1] -= value1; } } else { if ((n & 1) != 0) { unsigned int jColumn = column[j]; array[jColumn] -= value * element[j]; j++; } if ((n & 2) != 0) { unsigned int jColumn0 = column[j]; double value0 = value * element[j]; unsigned int jColumn1 = column[j+1]; double value1 = value * element[j+1]; array[jColumn0] -= value0; array[jColumn1] -= value1; j += 2; } if ((n & 4) != 0) { unsigned int jColumn0 = column[j]; double value0 = value * element[j]; unsigned int jColumn1 = column[j+1]; double value1 = value * element[j+1]; unsigned int jColumn2 = column[j+2]; double value2 = value * element[j+2]; unsigned int jColumn3 = column[j+3]; double value3 = value * element[j+3]; array[jColumn0] -= value0; array[jColumn1] -= value1; array[jColumn2] -= value2; array[jColumn3] -= value3; j += 4; } //coin_prefetch_const(column+nextStart); for (; j < end; j += 8) { //coin_prefetch_const(element + j + 16); unsigned int jColumn0 = column[j]; double value0 = value * element[j]; unsigned int jColumn1 = column[j+1]; double value1 = value * element[j+1]; unsigned int jColumn2 = column[j+2]; double value2 = value * element[j+2]; unsigned int jColumn3 = column[j+3]; double value3 = value * element[j+3]; array[jColumn0] -= value0; array[jColumn1] -= value1; array[jColumn2] -= value2; array[jColumn3] -= value3; //coin_prefetch_const(column + j + 16); jColumn0 = column[j+4]; value0 = value * element[j+4]; jColumn1 = column[j+5]; value1 = value * element[j+5]; jColumn2 = column[j+6]; value2 = value * element[j+6]; jColumn3 = column[j+7]; value3 = value * element[j+7]; array[jColumn0] -= value0; array[jColumn1] -= value1; array[jColumn2] -= value2; array[jColumn3] -= value3; } } } // get rid of tiny values int nSmall = numberLook; int numberNonZero = 0; for (i = 0; i < nSmall; i++) { double value = array[i]; array[i] = 0.0; if (fabs(value) > 1.0e-12) { array[numberNonZero] = value; index[numberNonZero++] = i; } } for (; i < numberLook; i += 4) { double value0 = array[i+0]; double value1 = array[i+1]; double value2 = array[i+2]; double value3 = array[i+3]; array[i+0] = 0.0; array[i+1] = 0.0; array[i+2] = 0.0; array[i+3] = 0.0; if (fabs(value0) > 1.0e-12) { array[numberNonZero] = value0; index[numberNonZero++] = i + 0; } if (fabs(value1) > 1.0e-12) { array[numberNonZero] = value1; index[numberNonZero++] = i + 1; } if (fabs(value2) > 1.0e-12) { array[numberNonZero] = value2; index[numberNonZero++] = i + 2; } if (fabs(value3) > 1.0e-12) { array[numberNonZero] = value3; index[numberNonZero++] = i + 3; } } return numberNonZero; } #ifdef THREAD static void * doOneBlockThread(void * voidInfo) { dualColumn0Struct * info = (dualColumn0Struct *) voidInfo; *(info->numberInPtr) = doOneBlock(info->arrayTemp, info->indexTemp, info->pi, info->rowStart, info->element, info->column, info->numberInRowArray, info->numberLook); return NULL; } static void * doOneBlockAnd0Thread(void * voidInfo) { dualColumn0Struct * info = (dualColumn0Struct *) voidInfo; *(info->numberInPtr) = doOneBlock(info->arrayTemp, info->indexTemp, info->pi, info->rowStart, info->element, info->column, info->numberInRowArray, info->numberLook); *(info->numberOutPtr) = dualColumn0(info->model, info->spare, info->spareIndex, (const double *)info->arrayTemp, (const int *) info->indexTemp, *(info->numberInPtr), info->offset, info->acceptablePivot, info->bestPossiblePtr, info->upperThetaPtr, info->posFreePtr, info->freePivotPtr); return NULL; } #endif /* Return x * scalar * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix2::transposeTimes(const ClpSimplex * model, const CoinPackedMatrix * rowCopy, const CoinIndexedVector * rowArray, CoinIndexedVector * spareArray, CoinIndexedVector * columnArray) const { // See if dualColumn0 coding wanted bool dualColumn = model->spareIntArray_[0] == 1; double acceptablePivot = model->spareDoubleArray_[0]; double bestPossible = 0.0; double upperTheta = 1.0e31; double freePivot = acceptablePivot; int posFree = -1; int numberRemaining = 0; //if (model->numberIterations()>=200000) { //printf("time %g\n",CoinCpuTime()-startTime); //exit(77); //} double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); const int * whichRow = rowArray->getIndices(); double * element = const_cast(rowCopy->getElements()); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); int i; CoinBigIndex * rowStart2 = rowStart_; if (!dualColumn) { for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; CoinBigIndex start = rowStart[iRow]; *rowStart2 = start; unsigned short * count1 = count_ + iRow * numberBlocks_; int put = 0; for (int j = 0; j < numberBlocks_; j++) { put += numberInRowArray; start += count1[j]; rowStart2[put] = start; } rowStart2 ++; } } else { // also do dualColumn stuff double * spare = spareArray->denseVector(); int * spareIndex = spareArray->getIndices(); const double * reducedCost = model->djRegion(0); double dualTolerance = model->dualTolerance(); // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; int addSequence = model->numberColumns(); for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; double alpha = pi[i]; double oldValue; double value; bool keep; switch(model->getStatus(iRow + addSequence)) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: bestPossible = CoinMax(bestPossible, fabs(alpha)); oldValue = reducedCost[iRow]; // If free has to be very large - should come in via dualRow if (model->getStatus(iRow + addSequence) == ClpSimplex::isFree && fabs(alpha) < 1.0e-3) break; if (oldValue > dualTolerance) { keep = true; } else if (oldValue < -dualTolerance) { keep = true; } else { if (fabs(alpha) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) keep = true; else keep = false; } if (keep) { // free - choose largest if (fabs(alpha) > freePivot) { freePivot = fabs(alpha); posFree = i + addSequence; } } break; case ClpSimplex::atUpperBound: oldValue = reducedCost[iRow]; value = oldValue - tentativeTheta * alpha; //assert (oldValue<=dualTolerance*1.0001); if (value > dualTolerance) { bestPossible = CoinMax(bestPossible, -alpha); value = oldValue - upperTheta * alpha; if (value > dualTolerance && -alpha >= acceptablePivot) upperTheta = (oldValue - dualTolerance) / alpha; // add to list spare[numberRemaining] = alpha; spareIndex[numberRemaining++] = iRow + addSequence; } break; case ClpSimplex::atLowerBound: oldValue = reducedCost[iRow]; value = oldValue - tentativeTheta * alpha; //assert (oldValue>=-dualTolerance*1.0001); if (value < -dualTolerance) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < -dualTolerance && alpha >= acceptablePivot) upperTheta = (oldValue + dualTolerance) / alpha; // add to list spare[numberRemaining] = alpha; spareIndex[numberRemaining++] = iRow + addSequence; } break; } CoinBigIndex start = rowStart[iRow]; *rowStart2 = start; unsigned short * count1 = count_ + iRow * numberBlocks_; int put = 0; for (int j = 0; j < numberBlocks_; j++) { put += numberInRowArray; start += count1[j]; rowStart2[put] = start; } rowStart2 ++; } } double * spare = spareArray->denseVector(); int * spareIndex = spareArray->getIndices(); int saveNumberRemaining = numberRemaining; int iBlock; for (iBlock = 0; iBlock < numberBlocks_; iBlock++) { double * dwork = work_ + 6 * iBlock; int * iwork = reinterpret_cast (dwork + 3); if (!dualColumn) { #ifndef THREAD int offset = offset_[iBlock]; int offset3 = offset; offset = numberNonZero; double * arrayTemp = array + offset; int * indexTemp = index + offset; iwork[0] = doOneBlock(arrayTemp, indexTemp, pi, rowStart_ + numberInRowArray * iBlock, element, column_, numberInRowArray, offset_[iBlock+1] - offset); int number = iwork[0]; for (i = 0; i < number; i++) { //double value = arrayTemp[i]; //arrayTemp[i]=0.0; //array[numberNonZero]=value; index[numberNonZero++] = indexTemp[i] + offset3; } #else int offset = offset_[iBlock]; double * arrayTemp = array + offset; int * indexTemp = index + offset; dualColumn0Struct * infoPtr = info_ + iBlock; infoPtr->arrayTemp = arrayTemp; infoPtr->indexTemp = indexTemp; infoPtr->numberInPtr = &iwork[0]; infoPtr->pi = pi; infoPtr->rowStart = rowStart_ + numberInRowArray * iBlock; infoPtr->element = element; infoPtr->column = column_; infoPtr->numberInRowArray = numberInRowArray; infoPtr->numberLook = offset_[iBlock+1] - offset; pthread_create(&threadId_[iBlock], NULL, doOneBlockThread, infoPtr); #endif } else { #ifndef THREAD int offset = offset_[iBlock]; // allow for already saved int offset2 = offset + saveNumberRemaining; int offset3 = offset; offset = numberNonZero; offset2 = numberRemaining; double * arrayTemp = array + offset; int * indexTemp = index + offset; iwork[0] = doOneBlock(arrayTemp, indexTemp, pi, rowStart_ + numberInRowArray * iBlock, element, column_, numberInRowArray, offset_[iBlock+1] - offset); iwork[1] = dualColumn0(model, spare + offset2, spareIndex + offset2, arrayTemp, indexTemp, iwork[0], offset3, acceptablePivot, &dwork[0], &dwork[1], &iwork[2], &dwork[2]); int number = iwork[0]; int numberLook = iwork[1]; #if 1 numberRemaining += numberLook; #else double * spareTemp = spare + offset2; const int * spareIndexTemp = spareIndex + offset2; for (i = 0; i < numberLook; i++) { double value = spareTemp[i]; spareTemp[i] = 0.0; spare[numberRemaining] = value; spareIndex[numberRemaining++] = spareIndexTemp[i]; } #endif if (dwork[2] > freePivot) { freePivot = dwork[2]; posFree = iwork[2] + numberNonZero; } upperTheta = CoinMin(dwork[1], upperTheta); bestPossible = CoinMax(dwork[0], bestPossible); for (i = 0; i < number; i++) { // double value = arrayTemp[i]; //arrayTemp[i]=0.0; //array[numberNonZero]=value; index[numberNonZero++] = indexTemp[i] + offset3; } #else int offset = offset_[iBlock]; // allow for already saved int offset2 = offset + saveNumberRemaining; double * arrayTemp = array + offset; int * indexTemp = index + offset; dualColumn0Struct * infoPtr = info_ + iBlock; infoPtr->model = model; infoPtr->spare = spare + offset2; infoPtr->spareIndex = spareIndex + offset2; infoPtr->arrayTemp = arrayTemp; infoPtr->indexTemp = indexTemp; infoPtr->numberInPtr = &iwork[0]; infoPtr->offset = offset; infoPtr->acceptablePivot = acceptablePivot; infoPtr->bestPossiblePtr = &dwork[0]; infoPtr->upperThetaPtr = &dwork[1]; infoPtr->posFreePtr = &iwork[2]; infoPtr->freePivotPtr = &dwork[2]; infoPtr->numberOutPtr = &iwork[1]; infoPtr->pi = pi; infoPtr->rowStart = rowStart_ + numberInRowArray * iBlock; infoPtr->element = element; infoPtr->column = column_; infoPtr->numberInRowArray = numberInRowArray; infoPtr->numberLook = offset_[iBlock+1] - offset; if (iBlock >= 2) pthread_join(threadId_[iBlock-2], NULL); pthread_create(threadId_ + iBlock, NULL, doOneBlockAnd0Thread, infoPtr); //pthread_join(threadId_[iBlock],NULL); #endif } } for ( iBlock = CoinMax(0, numberBlocks_ - 2); iBlock < numberBlocks_; iBlock++) { #ifdef THREAD pthread_join(threadId_[iBlock], NULL); #endif } #ifdef THREAD for ( iBlock = 0; iBlock < numberBlocks_; iBlock++) { //pthread_join(threadId_[iBlock],NULL); int offset = offset_[iBlock]; double * dwork = work_ + 6 * iBlock; int * iwork = (int *) (dwork + 3); int number = iwork[0]; if (dualColumn) { // allow for already saved int offset2 = offset + saveNumberRemaining; int numberLook = iwork[1]; double * spareTemp = spare + offset2; const int * spareIndexTemp = spareIndex + offset2; for (i = 0; i < numberLook; i++) { double value = spareTemp[i]; spareTemp[i] = 0.0; spare[numberRemaining] = value; spareIndex[numberRemaining++] = spareIndexTemp[i]; } if (dwork[2] > freePivot) { freePivot = dwork[2]; posFree = iwork[2] + numberNonZero; } upperTheta = CoinMin(dwork[1], upperTheta); bestPossible = CoinMax(dwork[0], bestPossible); } double * arrayTemp = array + offset; const int * indexTemp = index + offset; for (i = 0; i < number; i++) { double value = arrayTemp[i]; arrayTemp[i] = 0.0; array[numberNonZero] = value; index[numberNonZero++] = indexTemp[i] + offset; } } #endif columnArray->setNumElements(numberNonZero); columnArray->setPackedMode(true); if (dualColumn) { model->spareDoubleArray_[0] = upperTheta; model->spareDoubleArray_[1] = bestPossible; // and theta and alpha and sequence if (posFree < 0) { model->spareIntArray_[1] = -1; } else { const double * reducedCost = model->djRegion(0); double alpha; int numberColumns = model->numberColumns(); if (posFree < numberColumns) { alpha = columnArray->denseVector()[posFree]; posFree = columnArray->getIndices()[posFree]; } else { alpha = rowArray->denseVector()[posFree-numberColumns]; posFree = rowArray->getIndices()[posFree-numberColumns] + numberColumns; } model->spareDoubleArray_[2] = fabs(reducedCost[posFree] / alpha);; model->spareDoubleArray_[3] = alpha; model->spareIntArray_[1] = posFree; } spareArray->setNumElements(numberRemaining); // signal done model->spareIntArray_[0] = -1; } } /* Default constructor. */ ClpPackedMatrix3::ClpPackedMatrix3() : numberBlocks_(0), numberColumns_(0), column_(NULL), start_(NULL), row_(NULL), element_(NULL), block_(NULL) { } /* Constructor from copy. */ ClpPackedMatrix3::ClpPackedMatrix3(ClpSimplex * model, const CoinPackedMatrix * columnCopy) : numberBlocks_(0), numberColumns_(0), column_(NULL), start_(NULL), row_(NULL), element_(NULL), block_(NULL) { #define MINBLOCK 6 #define MAXBLOCK 100 #define MAXUNROLL 10 numberColumns_ = model->getNumCols(); int numberColumns = columnCopy->getNumCols(); assert (numberColumns_ >= numberColumns); int numberRows = columnCopy->getNumRows(); int * counts = new int[numberRows+1]; CoinZeroN(counts, numberRows + 1); CoinBigIndex nels = 0; CoinBigIndex nZeroEl = 0; int iColumn; // get matrix data pointers const int * row = columnCopy->getIndices(); const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); const int * columnLength = columnCopy->getVectorLengths(); const double * elementByColumn = columnCopy->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; int n = columnLength[iColumn]; CoinBigIndex end = start + n; int kZero = 0; for (CoinBigIndex j = start; j < end; j++) { if(!elementByColumn[j]) kZero++; } n -= kZero; nZeroEl += kZero; nels += n; counts[n]++; } counts[0] += numberColumns_ - numberColumns; int nZeroColumns = counts[0]; counts[0] = -1; numberColumns_ -= nZeroColumns; column_ = new int [2*numberColumns_+nZeroColumns]; int * lookup = column_ + numberColumns_; row_ = new int[nels]; element_ = new double[nels]; int nOdd = 0; CoinBigIndex nInOdd = 0; int i; for (i = 1; i <= numberRows; i++) { int n = counts[i]; if (n) { if (n < MINBLOCK || i > MAXBLOCK) { nOdd += n; counts[i] = -1; nInOdd += n * i; } else { numberBlocks_++; } } else { counts[i] = -1; } } start_ = new CoinBigIndex [nOdd+1]; // even if no blocks do a dummy one numberBlocks_ = CoinMax(numberBlocks_, 1); block_ = new blockStruct [numberBlocks_]; memset(block_, 0, numberBlocks_ * sizeof(blockStruct)); // Fill in what we can int nTotal = nOdd; // in case no blocks block_->startIndices_ = nTotal; nels = nInOdd; int nBlock = 0; for (i = 0; i <= CoinMin(MAXBLOCK, numberRows); i++) { if (counts[i] > 0) { blockStruct * block = block_ + nBlock; int n = counts[i]; counts[i] = nBlock; // backward pointer nBlock++; block->startIndices_ = nTotal; block->startElements_ = nels; block->numberElements_ = i; // up counts nTotal += n; nels += n * i; } } for (iColumn = numberColumns; iColumn < numberColumns_; iColumn++) lookup[iColumn] = -1; // fill start_[0] = 0; nOdd = 0; nInOdd = 0; const double * columnScale = model->columnScale(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start = columnStart[iColumn]; int n = columnLength[iColumn]; CoinBigIndex end = start + n; int kZero = 0; for (CoinBigIndex j = start; j < end; j++) { if(!elementByColumn[j]) kZero++; } n -= kZero; if (n) { int iBlock = counts[n]; if (iBlock >= 0) { blockStruct * block = block_ + iBlock; int k = block->numberInBlock_; block->numberInBlock_ ++; column_[block->startIndices_+k] = iColumn; lookup[iColumn] = k; CoinBigIndex put = block->startElements_ + k * n; for (CoinBigIndex j = start; j < end; j++) { double value = elementByColumn[j]; if(value) { if (columnScale) value *= columnScale[iColumn]; element_[put] = value; row_[put++] = row[j]; } } } else { // odd ones for (CoinBigIndex j = start; j < end; j++) { double value = elementByColumn[j]; if(value) { if (columnScale) value *= columnScale[iColumn]; element_[nInOdd] = value; row_[nInOdd++] = row[j]; } } column_[nOdd] = iColumn; lookup[iColumn] = -1; nOdd++; start_[nOdd] = nInOdd; } } else { // zero column lookup[iColumn] = -1; } } delete [] counts; } /* Destructor */ ClpPackedMatrix3::~ClpPackedMatrix3() { delete [] column_; delete [] start_; delete [] row_; delete [] element_; delete [] block_; } /* The copy constructor. */ ClpPackedMatrix3::ClpPackedMatrix3(const ClpPackedMatrix3 & rhs) : numberBlocks_(rhs.numberBlocks_), numberColumns_(rhs.numberColumns_), column_(NULL), start_(NULL), row_(NULL), element_(NULL), block_(NULL) { if (rhs.numberBlocks_) { block_ = CoinCopyOfArray(rhs.block_, numberBlocks_); column_ = CoinCopyOfArray(rhs.column_, 2 * numberColumns_); int numberOdd = block_->startIndices_; start_ = CoinCopyOfArray(rhs.start_, numberOdd + 1); blockStruct * lastBlock = block_ + (numberBlocks_ - 1); CoinBigIndex numberElements = lastBlock->startElements_ + lastBlock->numberInBlock_ * lastBlock->numberElements_; row_ = CoinCopyOfArray(rhs.row_, numberElements); element_ = CoinCopyOfArray(rhs.element_, numberElements); } } ClpPackedMatrix3& ClpPackedMatrix3::operator=(const ClpPackedMatrix3 & rhs) { if (this != &rhs) { delete [] column_; delete [] start_; delete [] row_; delete [] element_; delete [] block_; numberBlocks_ = rhs.numberBlocks_; numberColumns_ = rhs.numberColumns_; if (rhs.numberBlocks_) { block_ = CoinCopyOfArray(rhs.block_, numberBlocks_); column_ = CoinCopyOfArray(rhs.column_, 2 * numberColumns_); int numberOdd = block_->startIndices_; start_ = CoinCopyOfArray(rhs.start_, numberOdd + 1); blockStruct * lastBlock = block_ + (numberBlocks_ - 1); CoinBigIndex numberElements = lastBlock->startElements_ + lastBlock->numberInBlock_ * lastBlock->numberElements_; row_ = CoinCopyOfArray(rhs.row_, numberElements); element_ = CoinCopyOfArray(rhs.element_, numberElements); } else { column_ = NULL; start_ = NULL; row_ = NULL; element_ = NULL; block_ = NULL; } } return *this; } /* Sort blocks */ void ClpPackedMatrix3::sortBlocks(const ClpSimplex * model) { int * lookup = column_ + numberColumns_; for (int iBlock = 0; iBlock < numberBlocks_; iBlock++) { blockStruct * block = block_ + iBlock; int numberInBlock = block->numberInBlock_; int nel = block->numberElements_; int * row = row_ + block->startElements_; double * element = element_ + block->startElements_; int * column = column_ + block->startIndices_; int lastPrice = 0; int firstNotPrice = numberInBlock - 1; while (lastPrice <= firstNotPrice) { // find first basic or fixed int iColumn = numberInBlock; for (; lastPrice <= firstNotPrice; lastPrice++) { iColumn = column[lastPrice]; if (model->getColumnStatus(iColumn) == ClpSimplex::basic || model->getColumnStatus(iColumn) == ClpSimplex::isFixed) break; } // find last non basic or fixed int jColumn = -1; for (; firstNotPrice > lastPrice; firstNotPrice--) { jColumn = column[firstNotPrice]; if (model->getColumnStatus(jColumn) != ClpSimplex::basic && model->getColumnStatus(jColumn) != ClpSimplex::isFixed) break; } if (firstNotPrice > lastPrice) { assert (column[lastPrice] == iColumn); assert (column[firstNotPrice] == jColumn); // need to swap column[firstNotPrice] = iColumn; lookup[iColumn] = firstNotPrice; column[lastPrice] = jColumn; lookup[jColumn] = lastPrice; double * elementA = element + lastPrice * nel; int * rowA = row + lastPrice * nel; double * elementB = element + firstNotPrice * nel; int * rowB = row + firstNotPrice * nel; for (int i = 0; i < nel; i++) { int temp = rowA[i]; double tempE = elementA[i]; rowA[i] = rowB[i]; elementA[i] = elementB[i]; rowB[i] = temp; elementB[i] = tempE; } firstNotPrice--; lastPrice++; } else if (lastPrice == firstNotPrice) { // make sure correct side iColumn = column[lastPrice]; if (model->getColumnStatus(iColumn) != ClpSimplex::basic && model->getColumnStatus(iColumn) != ClpSimplex::isFixed) lastPrice++; break; } } block->numberPrice_ = lastPrice; #ifndef NDEBUG // check int i; for (i = 0; i < lastPrice; i++) { int iColumn = column[i]; assert (model->getColumnStatus(iColumn) != ClpSimplex::basic && model->getColumnStatus(iColumn) != ClpSimplex::isFixed); assert (lookup[iColumn] == i); } for (; i < numberInBlock; i++) { int iColumn = column[i]; assert (model->getColumnStatus(iColumn) == ClpSimplex::basic || model->getColumnStatus(iColumn) == ClpSimplex::isFixed); assert (lookup[iColumn] == i); } #endif } } // Swap one variable void ClpPackedMatrix3::swapOne(const ClpSimplex * model, const ClpPackedMatrix * matrix, int iColumn) { int * lookup = column_ + numberColumns_; // position in block int kA = lookup[iColumn]; if (kA < 0) return; // odd one // get matrix data pointers const CoinPackedMatrix * columnCopy = matrix->getPackedMatrix(); //const int * row = columnCopy->getIndices(); const CoinBigIndex * columnStart = columnCopy->getVectorStarts(); const int * columnLength = columnCopy->getVectorLengths(); const double * elementByColumn = columnCopy->getElements(); CoinBigIndex start = columnStart[iColumn]; int n = columnLength[iColumn]; if (matrix->zeros()) { CoinBigIndex end = start + n; for (CoinBigIndex j = start; j < end; j++) { if(!elementByColumn[j]) n--; } } // find block - could do binary search int iBlock = CoinMin(n, numberBlocks_) - 1; while (block_[iBlock].numberElements_ != n) iBlock--; blockStruct * block = block_ + iBlock; int nel = block->numberElements_; int * row = row_ + block->startElements_; double * element = element_ + block->startElements_; int * column = column_ + block->startIndices_; assert (column[kA] == iColumn); bool moveUp = (model->getColumnStatus(iColumn) == ClpSimplex::basic || model->getColumnStatus(iColumn) == ClpSimplex::isFixed); int lastPrice = block->numberPrice_; int kB; if (moveUp) { // May already be in correct place (e.g. fixed basic leaving basis) if (kA >= lastPrice) return; kB = lastPrice - 1; block->numberPrice_--; } else { assert (kA >= lastPrice); kB = lastPrice; block->numberPrice_++; } int jColumn = column[kB]; column[kA] = jColumn; lookup[jColumn] = kA; column[kB] = iColumn; lookup[iColumn] = kB; double * elementA = element + kB * nel; int * rowA = row + kB * nel; double * elementB = element + kA * nel; int * rowB = row + kA * nel; int i; for (i = 0; i < nel; i++) { int temp = rowA[i]; double tempE = elementA[i]; rowA[i] = rowB[i]; elementA[i] = elementB[i]; rowB[i] = temp; elementB[i] = tempE; } #ifndef NDEBUG // check for (i = 0; i < block->numberPrice_; i++) { int iColumn = column[i]; if (iColumn != model->sequenceIn() && iColumn != model->sequenceOut()) assert (model->getColumnStatus(iColumn) != ClpSimplex::basic && model->getColumnStatus(iColumn) != ClpSimplex::isFixed); assert (lookup[iColumn] == i); } int numberInBlock = block->numberInBlock_; for (; i < numberInBlock; i++) { int iColumn = column[i]; if (iColumn != model->sequenceIn() && iColumn != model->sequenceOut()) assert (model->getColumnStatus(iColumn) == ClpSimplex::basic || model->getColumnStatus(iColumn) == ClpSimplex::isFixed); assert (lookup[iColumn] == i); } #endif } /* Return x * -1 * A in z. Note - x packed and z will be packed mode Squashes small elements and knows about ClpSimplex */ void ClpPackedMatrix3::transposeTimes(const ClpSimplex * model, const double * pi, CoinIndexedVector * output) const { int numberNonZero = 0; int * index = output->getIndices(); double * array = output->denseVector(); double zeroTolerance = model->zeroTolerance(); double value = 0.0; CoinBigIndex j; int numberOdd = block_->startIndices_; if (numberOdd) { // A) as probably long may be worth unrolling CoinBigIndex end = start_[1]; for (j = start_[0]; j < end; j++) { int iRow = row_[j]; value += pi[iRow] * element_[j]; } int iColumn; // int jColumn=column_[0]; for (iColumn = 0; iColumn < numberOdd - 1; iColumn++) { CoinBigIndex start = end; end = start_[iColumn+2]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = column_[iColumn]; //index[numberNonZero++]=jColumn; } // jColumn = column_[iColumn+1]; value = 0.0; //if (model->getColumnStatus(jColumn)!=ClpSimplex::basic) { for (j = start; j < end; j++) { int iRow = row_[j]; value += pi[iRow] * element_[j]; } //} } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = column_[iColumn]; //index[numberNonZero++]=jColumn; } } for (int iBlock = 0; iBlock < numberBlocks_; iBlock++) { // B) Can sort so just do nonbasic (and nonfixed) // C) Can do two at a time (if so put odd one into start_) // D) can use switch blockStruct * block = block_ + iBlock; //int numberPrice = block->numberInBlock_; int numberPrice = block->numberPrice_; int nel = block->numberElements_; int * row = row_ + block->startElements_; double * element = element_ + block->startElements_; int * column = column_ + block->startIndices_; #if 0 // two at a time if ((numberPrice & 1) != 0) { double value = 0.0; int nel2 = nel; for (; nel2; nel2--) { int iRow = *row++; value += pi[iRow] * (*element++); } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = *column; } column++; } numberPrice = numberPrice >> 1; switch ((nel % 2)) { // 2 k +0 case 0: for (; numberPrice; numberPrice--) { double value0 = 0.0; double value1 = 0.0; int nel2 = nel; for (; nel2; nel2--) { int iRow0 = *row; int iRow1 = *(row + nel); row++; double element0 = *element; double element1 = *(element + nel); element++; value0 += pi[iRow0] * element0; value1 += pi[iRow1] * element1; } row += nel; element += nel; if (fabs(value0) > zeroTolerance) { array[numberNonZero] = value0; index[numberNonZero++] = *column; } column++; if (fabs(value1) > zeroTolerance) { array[numberNonZero] = value1; index[numberNonZero++] = *column; } column++; } break; // 2 k +1 case 1: for (; numberPrice; numberPrice--) { double value0; double value1; int nel2 = nel - 1; { int iRow0 = row[0]; int iRow1 = row[nel]; double pi0 = pi[iRow0]; double pi1 = pi[iRow1]; value0 = pi0 * element[0]; value1 = pi1 * element[nel]; row++; element++; } for (; nel2; nel2--) { int iRow0 = *row; int iRow1 = *(row + nel); row++; double element0 = *element; double element1 = *(element + nel); element++; value0 += pi[iRow0] * element0; value1 += pi[iRow1] * element1; } row += nel; element += nel; if (fabs(value0) > zeroTolerance) { array[numberNonZero] = value0; index[numberNonZero++] = *column; } column++; if (fabs(value1) > zeroTolerance) { array[numberNonZero] = value1; index[numberNonZero++] = *column; } column++; } break; } #else for (; numberPrice; numberPrice--) { double value = 0.0; int nel2 = nel; for (; nel2; nel2--) { int iRow = *row++; value += pi[iRow] * (*element++); } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = *column; } column++; } #endif } output->setNumElements(numberNonZero); } // Updates two arrays for steepest void ClpPackedMatrix3::transposeTimes2(const ClpSimplex * model, const double * pi, CoinIndexedVector * output, const double * piWeight, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { int numberNonZero = 0; int * index = output->getIndices(); double * array = output->denseVector(); double zeroTolerance = model->zeroTolerance(); double value = 0.0; bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; int numberOdd = block_->startIndices_; int iColumn; CoinBigIndex end = start_[0]; for (iColumn = 0; iColumn < numberOdd; iColumn++) { CoinBigIndex start = end; CoinBigIndex j; int jColumn = column_[iColumn]; end = start_[iColumn+1]; value = 0.0; if (model->getColumnStatus(jColumn) != ClpSimplex::basic) { for (j = start; j < end; j++) { int iRow = row_[j]; value -= pi[iRow] * element_[j]; } if (fabs(value) > zeroTolerance) { // and do other array double modification = 0.0; for (j = start; j < end; j++) { int iRow = row_[j]; modification += piWeight[iRow] * element_[j]; } double thisWeight = weights[jColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(jColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[jColumn] = thisWeight; if (!killDjs) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } } } } for (int iBlock = 0; iBlock < numberBlocks_; iBlock++) { // B) Can sort so just do nonbasic (and nonfixed) // C) Can do two at a time (if so put odd one into start_) // D) can use switch blockStruct * block = block_ + iBlock; //int numberPrice = block->numberInBlock_; int numberPrice = block->numberPrice_; int nel = block->numberElements_; int * row = row_ + block->startElements_; double * element = element_ + block->startElements_; int * column = column_ + block->startIndices_; for (; numberPrice; numberPrice--) { double value = 0.0; int nel2 = nel; for (; nel2; nel2--) { int iRow = *row++; value -= pi[iRow] * (*element++); } if (fabs(value) > zeroTolerance) { int jColumn = *column; // back to beginning row -= nel; element -= nel; // and do other array double modification = 0.0; nel2 = nel; for (; nel2; nel2--) { int iRow = *row++; modification += piWeight[iRow] * (*element++); } double thisWeight = weights[jColumn]; double pivot = value * scaleFactor; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(jColumn)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[jColumn] = thisWeight; if (!killDjs) { array[numberNonZero] = value; index[numberNonZero++] = jColumn; } } column++; } } output->setNumElements(numberNonZero); output->setPackedMode(true); } #if COIN_LONG_WORK // For long double versions void ClpPackedMatrix::times(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const { int iRow, iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); //memset(y,0,matrix_->getNumRows()*sizeof(double)); assert (((flags_ & 2) != 0) == matrix_->hasGaps()); if (!(flags_ & 2)) { for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinWorkDouble value = x[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn+1]; value *= scalar; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j]; } } } } else { const int * columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinWorkDouble value = x[iColumn]; if (value) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; value *= scalar; for (j = start; j < end; j++) { iRow = row[j]; y[iRow] += value * elementByColumn[j]; } } } } } void ClpPackedMatrix::transposeTimes(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const { int iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); if (!(flags_ & 2)) { if (scalar == -1.0) { CoinBigIndex start = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; CoinWorkDouble value = y[iColumn]; for (j = start; j < next; j++) { int jRow = row[j]; value -= x[jRow] * elementByColumn[j]; } start = next; y[iColumn] = value; } } else { CoinBigIndex start = columnStart[0]; for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinBigIndex next = columnStart[iColumn+1]; CoinWorkDouble value = 0.0; for (j = start; j < next; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j]; } start = next; y[iColumn] += value * scalar; } } } else { const int * columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberActiveColumns_; iColumn++) { CoinBigIndex j; CoinWorkDouble value = 0.0; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (j = start; j < end; j++) { int jRow = row[j]; value += x[jRow] * elementByColumn[j]; } y[iColumn] += value * scalar; } } } #endif #ifdef CLP_ALL_ONE_FILE #undef reference #endif Clp-1.15.10/src/ClpEventHandler.hpp0000644000076600007660000001260511662222261015375 0ustar coincoin/* $Id: ClpEventHandler.hpp 1825 2011-11-20 16:02:57Z 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 ClpEventHandler_H #define ClpEventHandler_H #include "ClpSimplex.hpp" /** Base class for Clp event handling This is just here to allow for event handling. By event I mean a Clp event e.g. end of values pass. One use would be to let a user handle a system event e.g. Control-C. This could be done by deriving a class MyEventHandler which knows about such events. If one occurs MyEventHandler::event() could clear event status and return 3 (stopped). Clp would then return to user code. As it is called every iteration this should be fine grained enough. User can derive and construct from CbcModel - not pretty */ class ClpEventHandler { public: /** enums for what sort of event. These will also be returned in ClpModel::secondaryStatus() as int */ enum Event { endOfIteration = 100, // used to set secondary status endOfFactorization, // after gutsOfSolution etc endOfValuesPass, node, // for Cbc treeStatus, // for Cbc solution, // for Cbc theta, // hit in parametrics pivotRow, // used to choose pivot row presolveStart, // ClpSolve presolve start presolveSize, // sees if ClpSolve presolve too big or too small presolveInfeasible, // ClpSolve presolve infeasible presolveBeforeSolve, // ClpSolve presolve before solve presolveAfterFirstSolve, // ClpSolve presolve after solve presolveAfterSolve, // ClpSolve presolve after solve presolveEnd, // ClpSolve presolve end goodFactorization, // before gutsOfSolution complicatedPivotIn, // in modifyCoefficients noCandidateInPrimal, // tentative end looksEndInPrimal, // About to declare victory (or defeat) endInPrimal, // Victory (or defeat) beforeStatusOfProblemInPrimal, startOfStatusOfProblemInPrimal, complicatedPivotOut, // in modifyCoefficients noCandidateInDual, // tentative end looksEndInDual, // About to declare victory (or defeat) endInDual, // Victory (or defeat) beforeStatusOfProblemInDual, startOfStatusOfProblemInDual, startOfIterationInDual, updateDualsInDual, endOfCreateRim, slightlyInfeasible, modifyMatrixInMiniPresolve, moreMiniPresolve, modifyMatrixInMiniPostsolve, noTheta // At end (because no pivot) }; /**@name Virtual method that the derived classes should provide. The base class instance does nothing and as event() is only useful method it would not be very useful NOT providing one! */ //@{ /** This can do whatever it likes. If return code -1 then carries on if 0 sets ClpModel::status() to 5 (stopped by event) and will return to user. At present if <-1 carries on and if >0 acts as if 0 - this may change. For ClpSolve 2 -> too big return status of -2 and -> too small 3 */ virtual int event(Event whichEvent); /** This can do whatever it likes. Return code -1 means no action. This passes in something */ virtual int eventWithInfo(Event whichEvent, void * info) ; //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpEventHandler(ClpSimplex * model = NULL); /** Destructor */ virtual ~ClpEventHandler(); // Copy ClpEventHandler(const ClpEventHandler&); // Assignment ClpEventHandler& operator=(const ClpEventHandler&); /// Clone virtual ClpEventHandler * clone() const; //@} /**@name Sets/gets */ //@{ /** set model. */ void setSimplex(ClpSimplex * model); /// Get model inline ClpSimplex * simplex() const { return model_; } //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer to simplex ClpSimplex * model_; //@} }; /** Base class for Clp disaster handling This is here to allow for disaster handling. By disaster I mean that Clp would otherwise give up */ class ClpDisasterHandler { public: /**@name Virtual methods that the derived classe should provide. */ //@{ /// Into simplex virtual void intoSimplex() = 0; /// Checks if disaster virtual bool check() const = 0; /// saves information for next attempt virtual void saveInfo() = 0; /// Type of disaster 0 can fix, 1 abort virtual int typeOfDisaster(); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpDisasterHandler(ClpSimplex * model = NULL); /** Destructor */ virtual ~ClpDisasterHandler(); // Copy ClpDisasterHandler(const ClpDisasterHandler&); // Assignment ClpDisasterHandler& operator=(const ClpDisasterHandler&); /// Clone virtual ClpDisasterHandler * clone() const = 0; //@} /**@name Sets/gets */ //@{ /** set model. */ void setSimplex(ClpSimplex * model); /// Get model inline ClpSimplex * simplex() const { return model_; } //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer to simplex ClpSimplex * model_; //@} }; #endif Clp-1.15.10/src/ClpHelperFunctions.hpp0000644000076600007660000002356111654457077016151 0ustar coincoin/* $Id: ClpHelperFunctions.hpp 1817 2011-11-03 09:26:23Z forrest $ */ // 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 ClpHelperFunctions_H #define ClpHelperFunctions_H #include "ClpConfig.h" #ifdef HAVE_CMATH # include #else # ifdef HAVE_MATH_H # include # else # error "don't have header file for math" # endif #endif /** Note (JJF) I have added some operations on arrays even though they may duplicate CoinDenseVector. I think the use of templates was a mistake as I don't think inline generic code can take as much advantage of parallelism or machine architectures or memory hierarchies. */ double maximumAbsElement(const double * region, int size); void setElements(double * region, int size, double value); void multiplyAdd(const double * region1, int size, double multiplier1, double * region2, double multiplier2); double innerProduct(const double * region1, int size, const double * region2); void getNorms(const double * region, int size, double & norm1, double & norm2); #if COIN_LONG_WORK // For long double versions CoinWorkDouble maximumAbsElement(const CoinWorkDouble * region, int size); void setElements(CoinWorkDouble * region, int size, CoinWorkDouble value); void multiplyAdd(const CoinWorkDouble * region1, int size, CoinWorkDouble multiplier1, CoinWorkDouble * region2, CoinWorkDouble multiplier2); CoinWorkDouble innerProduct(const CoinWorkDouble * region1, int size, const CoinWorkDouble * region2); void getNorms(const CoinWorkDouble * region, int size, CoinWorkDouble & norm1, CoinWorkDouble & norm2); inline void CoinMemcpyN(const double * from, const int size, CoinWorkDouble * to) { for (int i = 0; i < size; i++) to[i] = from[i]; } inline void CoinMemcpyN(const CoinWorkDouble * from, const int size, double * to) { for (int i = 0; i < size; i++) to[i] = static_cast(from[i]); } inline CoinWorkDouble CoinMax(const CoinWorkDouble x1, const double x2) { return (x1 > x2) ? x1 : x2; } inline CoinWorkDouble CoinMax(double x1, const CoinWorkDouble x2) { return (x1 > x2) ? x1 : x2; } inline CoinWorkDouble CoinMin(const CoinWorkDouble x1, const double x2) { return (x1 < x2) ? x1 : x2; } inline CoinWorkDouble CoinMin(double x1, const CoinWorkDouble x2) { return (x1 < x2) ? x1 : x2; } inline CoinWorkDouble CoinSqrt(CoinWorkDouble x) { return sqrtl(x); } #else inline double CoinSqrt(double x) { return sqrt(x); } #endif /// Trace # ifdef NDEBUG # define ClpTraceDebug(expression) {} # else void ClpTracePrint(std::string fileName, std::string message, int line); # define ClpTraceDebug(expression) { \ if (!(expression)) { ClpTracePrint(__FILE__,__STRING(expression),__LINE__); } \ } # endif /// Following only included if ClpPdco defined #ifdef ClpPdco_H inline double pdxxxmerit(int nlow, int nupp, int *low, int *upp, CoinDenseVector &r1, CoinDenseVector &r2, CoinDenseVector &rL, CoinDenseVector &rU, CoinDenseVector &cL, CoinDenseVector &cU ) { // Evaluate the merit function for Newton's method. // It is the 2-norm of the three sets of residuals. double sum1, sum2; CoinDenseVector f(6); f[0] = r1.twoNorm(); f[1] = r2.twoNorm(); sum1 = sum2 = 0.0; for (int k = 0; k < nlow; k++) { sum1 += rL[low[k]] * rL[low[k]]; sum2 += cL[low[k]] * cL[low[k]]; } f[2] = sqrt(sum1); f[4] = sqrt(sum2); sum1 = sum2 = 0.0; for (int k = 0; k < nupp; k++) { sum1 += rL[upp[k]] * rL[upp[k]]; sum2 += cL[upp[k]] * cL[upp[k]]; } f[3] = sqrt(sum1); f[5] = sqrt(sum2); return f.twoNorm(); } //----------------------------------------------------------------------- // End private function pdxxxmerit //----------------------------------------------------------------------- //function [r1,r2,rL,rU,Pinf,Dinf] = ... // pdxxxresid1( Aname,fix,low,upp, ... // b,bl,bu,d1,d2,grad,rL,rU,x,x1,x2,y,z1,z2 ) inline void pdxxxresid1(ClpPdco *model, const int nlow, const int nupp, const int nfix, int *low, int *upp, int *fix, CoinDenseVector &b, double *bl, double *bu, double d1, double d2, CoinDenseVector &grad, CoinDenseVector &rL, CoinDenseVector &rU, CoinDenseVector &x, CoinDenseVector &x1, CoinDenseVector &x2, CoinDenseVector &y, CoinDenseVector &z1, CoinDenseVector &z2, CoinDenseVector &r1, CoinDenseVector &r2, double *Pinf, double *Dinf) { // Form residuals for the primal and dual equations. // rL, rU are output, but we input them as full vectors // initialized (permanently) with any relevant zeros. // Get some element pointers for efficiency double *x_elts = x.getElements(); double *r2_elts = r2.getElements(); for (int k = 0; k < nfix; k++) x_elts[fix[k]] = 0; r1.clear(); r2.clear(); model->matVecMult( 1, r1, x ); model->matVecMult( 2, r2, y ); for (int k = 0; k < nfix; k++) r2_elts[fix[k]] = 0; r1 = b - r1 - d2 * d2 * y; r2 = grad - r2 - z1; // grad includes d1*d1*x if (nupp > 0) r2 = r2 + z2; for (int k = 0; k < nlow; k++) rL[low[k]] = bl[low[k]] - x[low[k]] + x1[low[k]]; for (int k = 0; k < nupp; k++) rU[upp[k]] = - bu[upp[k]] + x[upp[k]] + x2[upp[k]]; double normL = 0.0; double normU = 0.0; for (int k = 0; k < nlow; k++) if (rL[low[k]] > normL) normL = rL[low[k]]; for (int k = 0; k < nupp; k++) if (rU[upp[k]] > normU) normU = rU[upp[k]]; *Pinf = CoinMax(normL, normU); *Pinf = CoinMax( r1.infNorm() , *Pinf ); *Dinf = r2.infNorm(); *Pinf = CoinMax( *Pinf, 1e-99 ); *Dinf = CoinMax( *Dinf, 1e-99 ); } //----------------------------------------------------------------------- // End private function pdxxxresid1 //----------------------------------------------------------------------- //function [cL,cU,center,Cinf,Cinf0] = ... // pdxxxresid2( mu,low,upp,cL,cU,x1,x2,z1,z2 ) inline void pdxxxresid2(double mu, int nlow, int nupp, int *low, int *upp, CoinDenseVector &cL, CoinDenseVector &cU, CoinDenseVector &x1, CoinDenseVector &x2, CoinDenseVector &z1, CoinDenseVector &z2, double *center, double *Cinf, double *Cinf0) { // Form residuals for the complementarity equations. // cL, cU are output, but we input them as full vectors // initialized (permanently) with any relevant zeros. // Cinf is the complementarity residual for X1 z1 = mu e, etc. // Cinf0 is the same for mu=0 (i.e., for the original problem). double maxXz = -1e20; double minXz = 1e20; double *x1_elts = x1.getElements(); double *z1_elts = z1.getElements(); double *cL_elts = cL.getElements(); for (int k = 0; k < nlow; k++) { double x1z1 = x1_elts[low[k]] * z1_elts[low[k]]; cL_elts[low[k]] = mu - x1z1; if (x1z1 > maxXz) maxXz = x1z1; if (x1z1 < minXz) minXz = x1z1; } double *x2_elts = x2.getElements(); double *z2_elts = z2.getElements(); double *cU_elts = cU.getElements(); for (int k = 0; k < nupp; k++) { double x2z2 = x2_elts[upp[k]] * z2_elts[upp[k]]; cU_elts[upp[k]] = mu - x2z2; if (x2z2 > maxXz) maxXz = x2z2; if (x2z2 < minXz) minXz = x2z2; } maxXz = CoinMax( maxXz, 1e-99 ); minXz = CoinMax( minXz, 1e-99 ); *center = maxXz / minXz; double normL = 0.0; double normU = 0.0; for (int k = 0; k < nlow; k++) if (cL_elts[low[k]] > normL) normL = cL_elts[low[k]]; for (int k = 0; k < nupp; k++) if (cU_elts[upp[k]] > normU) normU = cU_elts[upp[k]]; *Cinf = CoinMax( normL, normU); *Cinf0 = maxXz; } //----------------------------------------------------------------------- // End private function pdxxxresid2 //----------------------------------------------------------------------- inline double pdxxxstep( CoinDenseVector &x, CoinDenseVector &dx ) { // Assumes x > 0. // Finds the maximum step such that x + step*dx >= 0. double step = 1e+20; int n = x.size(); double *x_elts = x.getElements(); double *dx_elts = dx.getElements(); for (int k = 0; k < n; k++) if (dx_elts[k] < 0) if ((x_elts[k] / (-dx_elts[k])) < step) step = x_elts[k] / (-dx_elts[k]); return step; } //----------------------------------------------------------------------- // End private function pdxxxstep //----------------------------------------------------------------------- inline double pdxxxstep(int nset, int *set, CoinDenseVector &x, CoinDenseVector &dx ) { // Assumes x > 0. // Finds the maximum step such that x + step*dx >= 0. double step = 1e+20; int n = x.size(); double *x_elts = x.getElements(); double *dx_elts = dx.getElements(); for (int k = 0; k < n; k++) if (dx_elts[k] < 0) if ((x_elts[k] / (-dx_elts[k])) < step) step = x_elts[k] / (-dx_elts[k]); return step; } //----------------------------------------------------------------------- // End private function pdxxxstep //----------------------------------------------------------------------- #endif #endif Clp-1.15.10/src/ClpNonLinearCost.hpp0000644000076600007660000003422311613504607015537 0ustar coincoin/* $Id: ClpNonLinearCost.hpp 1769 2011-07-26 09:31:51Z 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 ClpNonLinearCost_H #define ClpNonLinearCost_H #include "CoinPragma.hpp" class ClpSimplex; class CoinIndexedVector; /** Trivial class to deal with non linear costs I don't make any explicit assumptions about convexity but I am sure I do make implicit ones. One interesting idea for normal LP's will be to allow non-basic variables to come into basis as infeasible i.e. if variable at lower bound has very large positive reduced cost (when problem is infeasible) could it reduce overall problem infeasibility more by bringing it into basis below its lower bound. Another feature would be to automatically discover when problems are convex piecewise linear and re-formulate to use non-linear. I did some work on this many years ago on "grade" problems, but while it improved primal interior point algorithms were much better for that particular problem. */ /* status has original status and current status 0 - below lower so stored is upper 1 - in range 2 - above upper so stored is lower 4 - (for current) - same as original */ #define CLP_BELOW_LOWER 0 #define CLP_FEASIBLE 1 #define CLP_ABOVE_UPPER 2 #define CLP_SAME 4 inline int originalStatus(unsigned char status) { return (status & 15); } inline int currentStatus(unsigned char status) { return (status >> 4); } inline void setOriginalStatus(unsigned char & status, int value) { status = static_cast(status & ~15); status = static_cast(status | value); } inline void setCurrentStatus(unsigned char &status, int value) { status = static_cast(status & ~(15 << 4)); status = static_cast(status | (value << 4)); } inline void setInitialStatus(unsigned char &status) { status = static_cast(CLP_FEASIBLE | (CLP_SAME << 4)); } inline void setSameStatus(unsigned char &status) { status = static_cast(status & ~(15 << 4)); status = static_cast(status | (CLP_SAME << 4)); } // Use second version to get more speed //#define FAST_CLPNON #ifndef FAST_CLPNON #define CLP_METHOD1 ((method_&1)!=0) #define CLP_METHOD2 ((method_&2)!=0) #else #define CLP_METHOD1 (false) #define CLP_METHOD2 (true) #endif class ClpNonLinearCost { public: public: /**@name Constructors, destructor */ //@{ /// Default constructor. ClpNonLinearCost(); /** Constructor from simplex. This will just set up wasteful arrays for linear, but later may do dual analysis and even finding duplicate columns . */ ClpNonLinearCost(ClpSimplex * model, int method = 1); /** Constructor from simplex and list of non-linearities (columns only) First lower of each column has to match real lower Last lower has to be <= upper (if == then cost ignored) This could obviously be changed to make more user friendly */ ClpNonLinearCost(ClpSimplex * model, const int * starts, const double * lower, const double * cost); /// Destructor ~ClpNonLinearCost(); // Copy ClpNonLinearCost(const ClpNonLinearCost&); // Assignment ClpNonLinearCost& operator=(const ClpNonLinearCost&); //@} /**@name Actual work in primal */ //@{ /** Changes infeasible costs and computes number and cost of infeas Puts all non-basic (non free) variables to bounds and all free variables to zero if oldTolerance is non-zero - but does not move those <= oldTolerance away*/ void checkInfeasibilities(double oldTolerance = 0.0); /** Changes infeasible costs for each variable The indices are row indices and need converting to sequences */ void checkInfeasibilities(int numberInArray, const int * index); /** Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. On input array is empty (but indices exist). On exit just changed costs will be stored as normal CoinIndexedVector */ void checkChanged(int numberInArray, CoinIndexedVector * update); /** Goes through one bound for each variable. If multiplier*work[iRow]>0 goes down, otherwise up. The indices are row indices and need converting to sequences Temporary offsets may be set Rhs entries are increased */ void goThru(int numberInArray, double multiplier, const int * index, const double * work, double * rhs); /** Takes off last iteration (i.e. offsets closer to 0) */ void goBack(int numberInArray, const int * index, double * rhs); /** Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. At the end of this all temporary offsets are zero */ void goBackAll(const CoinIndexedVector * update); /// Temporary zeroing of feasible costs void zapCosts(); /// Refreshes costs always makes row costs zero void refreshCosts(const double * columnCosts); /// Puts feasible bounds into lower and upper void feasibleBounds(); /// Refresh - assuming regions OK void refresh(); /** Sets bounds and cost for one variable Returns change in cost May need to be inline for speed */ double setOne(int sequence, double solutionValue); /** Sets bounds and infeasible cost and true cost for one variable This is for gub and column generation etc */ void setOne(int sequence, double solutionValue, double lowerValue, double upperValue, double costValue = 0.0); /** Sets bounds and cost for outgoing variable may change value Returns direction */ int setOneOutgoing(int sequence, double &solutionValue); /// Returns nearest bound double nearest(int sequence, double solutionValue); /** Returns change in cost - one down if alpha >0.0, up if <0.0 Value is current - new */ inline double changeInCost(int sequence, double alpha) const { double returnValue = 0.0; if (CLP_METHOD1) { int iRange = whichRange_[sequence] + offset_[sequence]; if (alpha > 0.0) returnValue = cost_[iRange] - cost_[iRange-1]; else returnValue = cost_[iRange] - cost_[iRange+1]; } if (CLP_METHOD2) { returnValue = (alpha > 0.0) ? infeasibilityWeight_ : -infeasibilityWeight_; } return returnValue; } inline double changeUpInCost(int sequence) const { double returnValue = 0.0; if (CLP_METHOD1) { int iRange = whichRange_[sequence] + offset_[sequence]; if (iRange + 1 != start_[sequence+1] && !infeasible(iRange + 1)) returnValue = cost_[iRange] - cost_[iRange+1]; else returnValue = -1.0e100; } if (CLP_METHOD2) { returnValue = -infeasibilityWeight_; } return returnValue; } inline double changeDownInCost(int sequence) const { double returnValue = 0.0; if (CLP_METHOD1) { int iRange = whichRange_[sequence] + offset_[sequence]; if (iRange != start_[sequence] && !infeasible(iRange - 1)) returnValue = cost_[iRange] - cost_[iRange-1]; else returnValue = 1.0e100; } if (CLP_METHOD2) { returnValue = infeasibilityWeight_; } return returnValue; } /// This also updates next bound inline double changeInCost(int sequence, double alpha, double &rhs) { double returnValue = 0.0; #ifdef NONLIN_DEBUG double saveRhs = rhs; #endif if (CLP_METHOD1) { int iRange = whichRange_[sequence] + offset_[sequence]; if (alpha > 0.0) { assert(iRange - 1 >= start_[sequence]); offset_[sequence]--; rhs += lower_[iRange] - lower_[iRange-1]; returnValue = alpha * (cost_[iRange] - cost_[iRange-1]); } else { assert(iRange + 1 < start_[sequence+1] - 1); offset_[sequence]++; rhs += lower_[iRange+2] - lower_[iRange+1]; returnValue = alpha * (cost_[iRange] - cost_[iRange+1]); } } if (CLP_METHOD2) { #ifdef NONLIN_DEBUG double saveRhs1 = rhs; rhs = saveRhs; #endif unsigned char iStatus = status_[sequence]; int iWhere = currentStatus(iStatus); if (iWhere == CLP_SAME) iWhere = originalStatus(iStatus); // rhs always increases if (iWhere == CLP_FEASIBLE) { if (alpha > 0.0) { // going below iWhere = CLP_BELOW_LOWER; rhs = COIN_DBL_MAX; } else { // going above iWhere = CLP_ABOVE_UPPER; rhs = COIN_DBL_MAX; } } else if (iWhere == CLP_BELOW_LOWER) { assert (alpha < 0); // going feasible iWhere = CLP_FEASIBLE; rhs += bound_[sequence] - model_->upperRegion()[sequence]; } else { assert (iWhere == CLP_ABOVE_UPPER); // going feasible iWhere = CLP_FEASIBLE; rhs += model_->lowerRegion()[sequence] - bound_[sequence]; } setCurrentStatus(status_[sequence], iWhere); #ifdef NONLIN_DEBUG assert(saveRhs1 == rhs); #endif returnValue = fabs(alpha) * infeasibilityWeight_; } return returnValue; } /// Returns current lower bound inline double lower(int sequence) const { return lower_[whichRange_[sequence] + offset_[sequence]]; } /// Returns current upper bound inline double upper(int sequence) const { return lower_[whichRange_[sequence] + offset_[sequence] + 1]; } /// Returns current cost inline double cost(int sequence) const { return cost_[whichRange_[sequence] + offset_[sequence]]; } //@} /**@name Gets and sets */ //@{ /// Number of infeasibilities inline int numberInfeasibilities() const { return numberInfeasibilities_; } /// Change in cost inline double changeInCost() const { return changeCost_; } /// Feasible cost inline double feasibleCost() const { return feasibleCost_; } /// Feasible cost with offset and direction (i.e. for reporting) double feasibleReportCost() const; /// Sum of infeasibilities inline double sumInfeasibilities() const { return sumInfeasibilities_; } /// Largest infeasibility inline double largestInfeasibility() const { return largestInfeasibility_; } /// Average theta inline double averageTheta() const { return averageTheta_; } inline void setAverageTheta(double value) { averageTheta_ = value; } inline void setChangeInCost(double value) { changeCost_ = value; } inline void setMethod(int value) { method_ = value; } /// See if may want to look both ways inline bool lookBothWays() const { return bothWays_; } //@} ///@name Private functions to deal with infeasible regions inline bool infeasible(int i) const { return ((infeasible_[i>>5] >> (i & 31)) & 1) != 0; } inline void setInfeasible(int i, bool trueFalse) { unsigned int & value = infeasible_[i>>5]; int bit = i & 31; if (trueFalse) value |= (1 << bit); else value &= ~(1 << bit); } inline unsigned char * statusArray() const { return status_; } /// For debug void validate(); //@} private: /**@name Data members */ //@{ /// Change in cost because of infeasibilities double changeCost_; /// Feasible cost double feasibleCost_; /// Current infeasibility weight double infeasibilityWeight_; /// Largest infeasibility double largestInfeasibility_; /// Sum of infeasibilities double sumInfeasibilities_; /// Average theta - kept here as only for primal double averageTheta_; /// Number of rows (mainly for checking and copy) int numberRows_; /// Number of columns (mainly for checking and copy) int numberColumns_; /// Starts for each entry (columns then rows) int * start_; /// Range for each entry (columns then rows) int * whichRange_; /// Temporary range offset for each entry (columns then rows) int * offset_; /** Lower bound for each range (upper bound is next lower). For various reasons there is always an infeasible range at bottom - even if lower bound is - infinity */ double * lower_; /// Cost for each range double * cost_; /// Model ClpSimplex * model_; // Array to say which regions are infeasible unsigned int * infeasible_; /// Number of infeasibilities found int numberInfeasibilities_; // new stuff /// Contains status at beginning and current unsigned char * status_; /// Bound which has been replaced in lower_ or upper_ double * bound_; /// Feasible cost array double * cost2_; /// Method 1 old, 2 new, 3 both! int method_; /// If all non-linear costs convex bool convex_; /// If we should look both ways for djs bool bothWays_; //@} }; #endif Clp-1.15.10/src/MyEventHandler.cpp0000644000076600007660000000516211510657452015245 0ustar coincoin/* $Id: MyEventHandler.cpp 1665 2011-01-04 17:55:54Z 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) #pragma warning(disable:4786) #pragma warning(disable:4503) #endif #include "MyEventHandler.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- MyEventHandler::MyEventHandler () : ClpEventHandler() { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- MyEventHandler::MyEventHandler (const MyEventHandler & rhs) : ClpEventHandler(rhs) { } // Constructor with pointer to model MyEventHandler::MyEventHandler(ClpSimplex * model) : ClpEventHandler(model) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- MyEventHandler::~MyEventHandler () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- MyEventHandler & MyEventHandler::operator=(const MyEventHandler& rhs) { if (this != &rhs) { ClpEventHandler::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpEventHandler * MyEventHandler::clone() const { return new MyEventHandler(*this); } int MyEventHandler::event(Event whichEvent) { if (whichEvent == endOfValuesPass) return 0; // say optimal else return -1; // carry on #if 0 // This is how one can get some progress information at the end of each iteration. if (whichEvent == endOfIteration) { int numIter = model_->getIterationCount(); double sumDualInfeas = model_->sumDualInfeasibilities(); double sumPrimalInfeas = model_->sumPrimalInfeasibilities(); double obj = model_->getObjValue(); } // This is how one can tell CLP to stop now. // The value of cancelAsap needs to come from the application using CLP. if ( cancelAsap ) return 5; else return -1; #endif } Clp-1.15.10/src/ClpDualRowSteepest.cpp0000644000076600007660000012446111571121105016101 0ustar coincoin/* $Id: ClpDualRowSteepest.cpp 1732 2011-05-31 08:09: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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpDualRowSteepest.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "CoinHelperFunctions.hpp" #include //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //#define CLP_DEBUG 4 //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDualRowSteepest::ClpDualRowSteepest (int mode) : ClpDualRowPivot(), state_(-1), mode_(mode), persistence_(normal), weights_(NULL), infeasible_(NULL), alternateWeights_(NULL), savedWeights_(NULL), dubiousWeights_(NULL) { type_ = 2 + 64 * mode; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDualRowSteepest::ClpDualRowSteepest (const ClpDualRowSteepest & rhs) : ClpDualRowPivot(rhs) { state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; model_ = rhs.model_; if ((model_ && model_->whatsChanged() & 1) != 0) { int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_) { weights_ = new double[number]; ClpDisjointCopyN(rhs.weights_, number, weights_); } else { weights_ = NULL; } if (rhs.alternateWeights_) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } if (rhs.savedWeights_) { savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); } else { savedWeights_ = NULL; } if (rhs.dubiousWeights_) { assert(model_); int number = model_->numberRows(); dubiousWeights_ = new int[number]; ClpDisjointCopyN(rhs.dubiousWeights_, number, dubiousWeights_); } else { dubiousWeights_ = NULL; } } else { infeasible_ = NULL; weights_ = NULL; alternateWeights_ = NULL; savedWeights_ = NULL; dubiousWeights_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDualRowSteepest::~ClpDualRowSteepest () { delete [] weights_; delete [] dubiousWeights_; delete infeasible_; delete alternateWeights_; delete savedWeights_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDualRowSteepest & ClpDualRowSteepest::operator=(const ClpDualRowSteepest& rhs) { if (this != &rhs) { ClpDualRowPivot::operator=(rhs); state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; model_ = rhs.model_; delete [] weights_; delete [] dubiousWeights_; delete infeasible_; delete alternateWeights_; delete savedWeights_; assert(model_); int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_ != NULL) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_ != NULL) { weights_ = new double[number]; ClpDisjointCopyN(rhs.weights_, number, weights_); } else { weights_ = NULL; } if (rhs.alternateWeights_ != NULL) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } if (rhs.savedWeights_ != NULL) { savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); } else { savedWeights_ = NULL; } if (rhs.dubiousWeights_) { assert(model_); int number = model_->numberRows(); dubiousWeights_ = new int[number]; ClpDisjointCopyN(rhs.dubiousWeights_, number, dubiousWeights_); } else { dubiousWeights_ = NULL; } } return *this; } // Fill most values void ClpDualRowSteepest::fill(const ClpDualRowSteepest& rhs) { state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; assert (model_->numberRows() == rhs.model_->numberRows()); model_ = rhs.model_; assert(model_); int number = model_->numberRows(); if (rhs.savedWeights_) number = CoinMin(number, rhs.savedWeights_->capacity()); if (rhs.infeasible_ != NULL) { if (!infeasible_) infeasible_ = new CoinIndexedVector(rhs.infeasible_); else *infeasible_ = *rhs.infeasible_; } else { delete infeasible_; infeasible_ = NULL; } if (rhs.weights_ != NULL) { if (!weights_) weights_ = new double[number]; ClpDisjointCopyN(rhs.weights_, number, weights_); } else { delete [] weights_; weights_ = NULL; } if (rhs.alternateWeights_ != NULL) { if (!alternateWeights_) alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); else *alternateWeights_ = *rhs.alternateWeights_; } else { delete alternateWeights_; alternateWeights_ = NULL; } if (rhs.savedWeights_ != NULL) { if (!savedWeights_) savedWeights_ = new CoinIndexedVector(rhs.savedWeights_); else *savedWeights_ = *rhs.savedWeights_; } else { delete savedWeights_; savedWeights_ = NULL; } if (rhs.dubiousWeights_) { assert(model_); int number = model_->numberRows(); if (!dubiousWeights_) dubiousWeights_ = new int[number]; ClpDisjointCopyN(rhs.dubiousWeights_, number, dubiousWeights_); } else { delete [] dubiousWeights_; dubiousWeights_ = NULL; } } // Returns pivot row, -1 if none int ClpDualRowSteepest::pivotRow() { assert(model_); int i, iRow; double * infeas = infeasible_->denseVector(); double largest = 0.0; int * index = infeasible_->getIndices(); int number = infeasible_->getNumElements(); const int * pivotVariable = model_->pivotVariable(); int chosenRow = -1; int lastPivotRow = model_->pivotRow(); assert (lastPivotRow < model_->numberRows()); double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error // this coding has to mimic coding in checkPrimalSolution double error = CoinMin(1.0e-2, model_->largestPrimalError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // But cap tolerance = CoinMin(1000.0, tolerance); tolerance *= tolerance; // as we are using squares bool toleranceChanged = false; double * solution = model_->solutionRegion(); double * lower = model_->lowerRegion(); double * upper = model_->upperRegion(); // do last pivot row one here //#define CLP_DUAL_FIXED_COLUMN_MULTIPLIER 10.0 if (lastPivotRow >= 0 && lastPivotRow < model_->numberRows()) { #ifdef CLP_DUAL_COLUMN_MULTIPLIER int numberColumns = model_->numberColumns(); #endif int iPivot = pivotVariable[lastPivotRow]; double value = solution[iPivot]; double lower = model_->lower(iPivot); double upper = model_->upper(iPivot); if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif // store square in list if (infeas[lastPivotRow]) infeas[lastPivotRow] = value; // already there else infeasible_->quickAdd(lastPivotRow, value); } else if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif // store square in list if (infeas[lastPivotRow]) infeas[lastPivotRow] = value; // already there else infeasible_->add(lastPivotRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[lastPivotRow]) infeas[lastPivotRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } number = infeasible_->getNumElements(); } if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error if (model_->largestDualError() > model_->largestPrimalError()) { tolerance *= CoinMin(model_->largestDualError() / model_->largestPrimalError(), 1000.0); toleranceChanged = true; } } int numberWanted; if (mode_ < 2 ) { numberWanted = number + 1; } else if (mode_ == 2) { numberWanted = CoinMax(2000, number / 8); } else { int numberElements = model_->factorization()->numberElements(); double ratio = static_cast (numberElements) / static_cast (model_->numberRows()); numberWanted = CoinMax(2000, number / 8); if (ratio < 1.0) { numberWanted = CoinMax(2000, number / 20); } else if (ratio > 10.0) { ratio = number * (ratio / 80.0); if (ratio > number) numberWanted = number + 1; else numberWanted = CoinMax(2000, static_cast (ratio)); } } if (model_->largestPrimalError() > 1.0e-3) numberWanted = number + 1; // be safe int iPass; // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; //double largestWeight=0.0; //double smallestWeight=1.0e100; for (iPass = 0; iPass < 2; iPass++) { int end = start[2*iPass+1]; for (i = start[2*iPass]; i < end; i++) { iRow = index[i]; double value = infeas[iRow]; if (value > tolerance) { //#define OUT_EQ #ifdef OUT_EQ { int iSequence = pivotVariable[iRow]; if (upper[iSequence] == lower[iSequence]) value *= 2.0; } #endif double weight = CoinMin(weights_[iRow], 1.0e50); //largestWeight = CoinMax(largestWeight,weight); //smallestWeight = CoinMin(smallestWeight,weight); //double dubious = dubiousWeights_[iRow]; //weight *= dubious; //if (value>2.0*largest*weight||(value>0.5*largest*weight&&value*largestWeight>dubious*largest*weight)) { if (value > largest * weight) { // make last pivot row last resort choice if (iRow == lastPivotRow) { if (value * 1.0e-10 < largest * weight) continue; else value *= 1.0e-10; } int iSequence = pivotVariable[iRow]; if (!model_->flagged(iSequence)) { //#define CLP_DEBUG 3 #ifdef CLP_DEBUG double value2 = 0.0; if (solution[iSequence] > upper[iSequence] + tolerance) value2 = solution[iSequence] - upper[iSequence]; else if (solution[iSequence] < lower[iSequence] - tolerance) value2 = solution[iSequence] - lower[iSequence]; assert(fabs(value2 * value2 - infeas[iRow]) < 1.0e-8 * CoinMin(value2 * value2, infeas[iRow])); #endif if (solution[iSequence] > upper[iSequence] + tolerance || solution[iSequence] < lower[iSequence] - tolerance) { chosenRow = iRow; largest = value / weight; //largestWeight = dubious; } } else { // just to make sure we don't exit before got something numberWanted++; } } numberWanted--; if (!numberWanted) break; } } if (!numberWanted) break; } //printf("smallest %g largest %g\n",smallestWeight,largestWeight); if (chosenRow < 0 && toleranceChanged) { // won't line up with checkPrimalSolution - do again double saveError = model_->largestDualError(); model_->setLargestDualError(0.0); // can't loop chosenRow = pivotRow(); model_->setLargestDualError(saveError); } if (chosenRow < 0 && lastPivotRow < 0) { int nLeft = 0; for (int i = 0; i < number; i++) { int iRow = index[i]; if (fabs(infeas[iRow]) > 1.0e-50) { index[nLeft++] = iRow; } else { infeas[iRow] = 0.0; } } infeasible_->setNumElements(nLeft); model_->setNumberPrimalInfeasibilities(nLeft); } return chosenRow; } #if 0 static double ft_count = 0.0; static double up_count = 0.0; static double ft_count_in = 0.0; static double up_count_in = 0.0; static int xx_count = 0; #endif /* Updates weights and returns pivot alpha. Also does FT update */ double ClpDualRowSteepest::updateWeights(CoinIndexedVector * input, CoinIndexedVector * spare, CoinIndexedVector * spare2, CoinIndexedVector * updatedColumn) { //#define CLP_DEBUG 3 #if CLP_DEBUG>2 // Very expensive debug { int numberRows = model_->numberRows(); CoinIndexedVector * temp = new CoinIndexedVector(); temp->reserve(numberRows + model_->factorization()->maximumPivots()); double * array = alternateWeights_->denseVector(); int * which = alternateWeights_->getIndices(); alternateWeights_->clear(); int i; for (i = 0; i < numberRows; i++) { double value = 0.0; array[i] = 1.0; which[0] = i; alternateWeights_->setNumElements(1); model_->factorization()->updateColumnTranspose(temp, alternateWeights_); int number = alternateWeights_->getNumElements(); int j; for (j = 0; j < number; j++) { int iRow = which[j]; value += array[iRow] * array[iRow]; array[iRow] = 0.0; } alternateWeights_->setNumElements(0); double w = CoinMax(weights_[i], value) * .1; if (fabs(weights_[i] - value) > w) { printf("%d old %g, true %g\n", i, weights_[i], value); weights_[i] = value; // to reduce printout } //else //printf("%d matches %g\n",i,value); } delete temp; } #endif assert (input->packedMode()); if (!updatedColumn->packedMode()) { // I think this means empty #ifdef COIN_DEVELOP printf("updatedColumn not packed mode ClpDualRowSteepest::updateWeights\n"); #endif return 0.0; } double alpha = 0.0; if (!model_->factorization()->networkBasis()) { // clear other region alternateWeights_->clear(); double norm = 0.0; int i; double * work = input->denseVector(); int numberNonZero = input->getNumElements(); int * which = input->getIndices(); double * work2 = spare->denseVector(); int * which2 = spare->getIndices(); // ftran //permute and move indices into index array //also compute norm //int *regionIndex = alternateWeights_->getIndices ( ); const int *permute = model_->factorization()->permute(); //double * region = alternateWeights_->denseVector(); if (permute) { for ( i = 0; i < numberNonZero; i ++ ) { int iRow = which[i]; double value = work[i]; norm += value * value; iRow = permute[iRow]; work2[iRow] = value; which2[i] = iRow; } } else { for ( i = 0; i < numberNonZero; i ++ ) { int iRow = which[i]; double value = work[i]; norm += value * value; //iRow = permute[iRow]; work2[iRow] = value; which2[i] = iRow; } } spare->setNumElements ( numberNonZero ); // Do FT update #if 0 ft_count_in += updatedColumn->getNumElements(); up_count_in += spare->getNumElements(); #endif if (permute || true) { #if CLP_DEBUG>2 printf("REGION before %d els\n", spare->getNumElements()); spare->print(); #endif model_->factorization()->updateTwoColumnsFT(spare2, updatedColumn, spare, permute != NULL); #if CLP_DEBUG>2 printf("REGION after %d els\n", spare->getNumElements()); spare->print(); #endif } else { // Leave as old way model_->factorization()->updateColumnFT(spare2, updatedColumn); model_->factorization()->updateColumn(spare2, spare, false); } #undef CLP_DEBUG #if 0 ft_count += updatedColumn->getNumElements(); up_count += spare->getNumElements(); xx_count++; if ((xx_count % 1000) == 0) printf("zz %d ft %g up %g (in %g %g)\n", xx_count, ft_count, up_count, ft_count_in, up_count_in); #endif numberNonZero = spare->getNumElements(); // alternateWeights_ should still be empty int pivotRow = model_->pivotRow(); #ifdef CLP_DEBUG if ( model_->logLevel ( ) > 4 && fabs(norm - weights_[pivotRow]) > 1.0e-3 * (1.0 + norm)) printf("on row %d, true weight %g, old %g\n", pivotRow, sqrt(norm), sqrt(weights_[pivotRow])); #endif // could re-initialize here (could be expensive) norm /= model_->alpha() * model_->alpha(); assert(model_->alpha()); assert(norm); // pivot element alpha = 0.0; double multiplier = 2.0 / model_->alpha(); // look at updated column work = updatedColumn->denseVector(); numberNonZero = updatedColumn->getNumElements(); which = updatedColumn->getIndices(); int nSave = 0; double * work3 = alternateWeights_->denseVector(); int * which3 = alternateWeights_->getIndices(); const int * pivotColumn = model_->factorization()->pivotColumn(); for (i = 0; i < numberNonZero; i++) { int iRow = which[i]; double theta = work[i]; if (iRow == pivotRow) alpha = theta; double devex = weights_[iRow]; work3[nSave] = devex; // save old which3[nSave++] = iRow; // transform to match spare int jRow = permute ? pivotColumn[iRow] : iRow; double value = work2[jRow]; devex += theta * (theta * norm + value * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights_[iRow] = devex; } alternateWeights_->setPackedMode(true); alternateWeights_->setNumElements(nSave); if (norm < DEVEX_TRY_NORM) norm = DEVEX_TRY_NORM; // Try this to make less likely will happen again and stop cycling //norm *= 1.02; weights_[pivotRow] = norm; spare->clear(); #ifdef CLP_DEBUG spare->checkClear(); #endif } else { // Do FT update model_->factorization()->updateColumnFT(spare, updatedColumn); // clear other region alternateWeights_->clear(); double norm = 0.0; int i; double * work = input->denseVector(); int number = input->getNumElements(); int * which = input->getIndices(); double * work2 = spare->denseVector(); int * which2 = spare->getIndices(); for (i = 0; i < number; i++) { int iRow = which[i]; double value = work[i]; norm += value * value; work2[iRow] = value; which2[i] = iRow; } spare->setNumElements(number); // ftran #ifndef NDEBUG alternateWeights_->checkClear(); #endif model_->factorization()->updateColumn(alternateWeights_, spare); // alternateWeights_ should still be empty #ifndef NDEBUG alternateWeights_->checkClear(); #endif int pivotRow = model_->pivotRow(); #ifdef CLP_DEBUG if ( model_->logLevel ( ) > 4 && fabs(norm - weights_[pivotRow]) > 1.0e-3 * (1.0 + norm)) printf("on row %d, true weight %g, old %g\n", pivotRow, sqrt(norm), sqrt(weights_[pivotRow])); #endif // could re-initialize here (could be expensive) norm /= model_->alpha() * model_->alpha(); assert(norm); //if (norm < DEVEX_TRY_NORM) //norm = DEVEX_TRY_NORM; // pivot element alpha = 0.0; double multiplier = 2.0 / model_->alpha(); // look at updated column work = updatedColumn->denseVector(); number = updatedColumn->getNumElements(); which = updatedColumn->getIndices(); int nSave = 0; double * work3 = alternateWeights_->denseVector(); int * which3 = alternateWeights_->getIndices(); for (i = 0; i < number; i++) { int iRow = which[i]; double theta = work[i]; if (iRow == pivotRow) alpha = theta; double devex = weights_[iRow]; work3[nSave] = devex; // save old which3[nSave++] = iRow; double value = work2[iRow]; devex += theta * (theta * norm + value * multiplier); if (devex < DEVEX_TRY_NORM) devex = DEVEX_TRY_NORM; weights_[iRow] = devex; } if (!alpha) { // error - but carry on alpha = 1.0e-50; } alternateWeights_->setPackedMode(true); alternateWeights_->setNumElements(nSave); if (norm < DEVEX_TRY_NORM) norm = DEVEX_TRY_NORM; weights_[pivotRow] = norm; spare->clear(); } #ifdef CLP_DEBUG spare->checkClear(); #endif return alpha; } /* Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ void ClpDualRowSteepest::updatePrimalSolution( CoinIndexedVector * primalUpdate, double primalRatio, double & objectiveChange) { double * COIN_RESTRICT work = primalUpdate->denseVector(); int number = primalUpdate->getNumElements(); int * COIN_RESTRICT which = primalUpdate->getIndices(); int i; double changeObj = 0.0; double tolerance = model_->currentPrimalTolerance(); const int * COIN_RESTRICT pivotVariable = model_->pivotVariable(); double * COIN_RESTRICT infeas = infeasible_->denseVector(); double * COIN_RESTRICT solution = model_->solutionRegion(); const double * COIN_RESTRICT costModel = model_->costRegion(); const double * COIN_RESTRICT lowerModel = model_->lowerRegion(); const double * COIN_RESTRICT upperModel = model_->upperRegion(); #ifdef CLP_DUAL_COLUMN_MULTIPLIER int numberColumns = model_->numberColumns(); #endif if (primalUpdate->packedMode()) { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; double value = solution[iPivot]; double cost = costModel[iPivot]; double change = primalRatio * work[i]; work[i] = 0.0; value -= change; changeObj -= change * cost; double lower = lowerModel[iPivot]; double upper = upperModel[iPivot]; solution[iPivot] = value; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } } } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; double value = solution[iPivot]; double cost = costModel[iPivot]; double change = primalRatio * work[iRow]; value -= change; changeObj -= change * cost; double lower = lowerModel[iPivot]; double upper = upperModel[iPivot]; solution[iPivot] = value; if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list if (infeas[iRow]) infeas[iRow] = value; // already there else infeasible_->quickAdd(iRow, value); } else { // feasible - was it infeasible - if so set tiny if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } work[iRow] = 0.0; } } // Do pivot row { int iRow = model_->pivotRow(); // feasible - was it infeasible - if so set tiny //assert (infeas[iRow]); if (infeas[iRow]) infeas[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } primalUpdate->setNumElements(0); objectiveChange += changeObj; } /* Saves any weights round factorization as pivot rows may change 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights */ void ClpDualRowSteepest::saveWeights(ClpSimplex * model, int mode) { // alternateWeights_ is defined as indexed but is treated oddly model_ = model; int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); const int * pivotVariable = model_->pivotVariable(); int i; if (mode == 1) { if(weights_) { // Check if size has changed if (infeasible_->capacity() == numberRows) { alternateWeights_->clear(); // change from row numbers to sequence numbers int * which = alternateWeights_->getIndices(); for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; which[i] = iPivot; } state_ = 1; } else { // size has changed - clear everything delete [] weights_; weights_ = NULL; delete [] dubiousWeights_; dubiousWeights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete savedWeights_; savedWeights_ = NULL; state_ = -1; } } } else if (mode == 2 || mode == 4 || mode >= 5) { // restore if (!weights_ || state_ == -1 || mode == 5) { // initialize weights delete [] weights_; delete alternateWeights_; weights_ = new double[numberRows]; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization alternateWeights_->reserve(numberRows + model_->factorization()->maximumPivots()); if (mode_ != 1 || mode == 5) { // initialize to 1.0 (can we do better?) for (i = 0; i < numberRows; i++) { weights_[i] = 1.0; } } else { CoinIndexedVector * temp = new CoinIndexedVector(); temp->reserve(numberRows + model_->factorization()->maximumPivots()); double * array = alternateWeights_->denseVector(); int * which = alternateWeights_->getIndices(); for (i = 0; i < numberRows; i++) { double value = 0.0; array[0] = 1.0; which[0] = i; alternateWeights_->setNumElements(1); alternateWeights_->setPackedMode(true); model_->factorization()->updateColumnTranspose(temp, alternateWeights_); int number = alternateWeights_->getNumElements(); int j; for (j = 0; j < number; j++) { value += array[j] * array[j]; array[j] = 0.0; } alternateWeights_->setNumElements(0); weights_[i] = value; } delete temp; } // create saved weights (not really indexedvector) savedWeights_ = new CoinIndexedVector(); savedWeights_->reserve(numberRows); double * array = savedWeights_->denseVector(); int * which = savedWeights_->getIndices(); for (i = 0; i < numberRows; i++) { array[i] = weights_[i]; which[i] = pivotVariable[i]; } } else if (mode != 6) { int * which = alternateWeights_->getIndices(); CoinIndexedVector * rowArray3 = model_->rowArray(3); rowArray3->clear(); int * back = rowArray3->getIndices(); // In case something went wrong for (i = 0; i < numberRows + numberColumns; i++) back[i] = -1; if (mode != 4) { // save CoinMemcpyN(which, numberRows, savedWeights_->getIndices()); CoinMemcpyN(weights_, numberRows, savedWeights_->denseVector()); } else { // restore //memcpy(which,savedWeights_->getIndices(), // numberRows*sizeof(int)); //memcpy(weights_,savedWeights_->denseVector(), // numberRows*sizeof(double)); which = savedWeights_->getIndices(); } // restore (a bit slow - but only every re-factorization) double * array = savedWeights_->denseVector(); for (i = 0; i < numberRows; i++) { int iSeq = which[i]; back[iSeq] = i; } for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; iPivot = back[iPivot]; if (iPivot >= 0) { weights_[i] = array[iPivot]; if (weights_[i] < DEVEX_TRY_NORM) weights_[i] = DEVEX_TRY_NORM; // may need to check more } else { // odd weights_[i] = 1.0; } } } else { // mode 6 - scale back weights as primal errors double primalError = model_->largestPrimalError(); double allowed ; if (primalError > 1.0e3) allowed = 10.0; else if (primalError > 1.0e2) allowed = 50.0; else if (primalError > 1.0e1) allowed = 100.0; else allowed = 1000.0; double allowedInv = 1.0 / allowed; for (i = 0; i < numberRows; i++) { double value = weights_[i]; if (value < allowedInv) value = allowedInv; else if (value > allowed) value = allowed; weights_[i] = allowed; } } state_ = 0; // set up infeasibilities if (!infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberRows); } } if (mode >= 2) { // Get dubious weights //if (!dubiousWeights_) //dubiousWeights_=new int[numberRows]; //model_->factorization()->getWeights(dubiousWeights_); infeasible_->clear(); int iRow; const int * pivotVariable = model_->pivotVariable(); double tolerance = model_->currentPrimalTolerance(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = model_->solution(iPivot); double lower = model_->lower(iPivot); double upper = model_->upper(iPivot); if (value < lower - tolerance) { value -= lower; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } else if (value > upper + tolerance) { value -= upper; value *= value; #ifdef CLP_DUAL_COLUMN_MULTIPLIER if (iPivot < numberColumns) value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns #endif #ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER if (lower == upper) value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables #endif // store square in list infeasible_->quickAdd(iRow, value); } } } } // Gets rid of last update void ClpDualRowSteepest::unrollWeights() { double * saved = alternateWeights_->denseVector(); int number = alternateWeights_->getNumElements(); int * which = alternateWeights_->getIndices(); int i; if (alternateWeights_->packedMode()) { for (i = 0; i < number; i++) { int iRow = which[i]; weights_[iRow] = saved[i]; saved[i] = 0.0; } } else { for (i = 0; i < number; i++) { int iRow = which[i]; weights_[iRow] = saved[iRow]; saved[iRow] = 0.0; } } alternateWeights_->setNumElements(0); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpDualRowPivot * ClpDualRowSteepest::clone(bool CopyData) const { if (CopyData) { return new ClpDualRowSteepest(*this); } else { return new ClpDualRowSteepest(); } } // Gets rid of all arrays void ClpDualRowSteepest::clearArrays() { if (persistence_ == normal) { delete [] weights_; weights_ = NULL; delete [] dubiousWeights_; dubiousWeights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete savedWeights_; savedWeights_ = NULL; } state_ = -1; } // Returns true if would not find any row bool ClpDualRowSteepest::looksOptimal() const { int iRow; const int * pivotVariable = model_->pivotVariable(); double tolerance = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error // this coding has to mimic coding in checkPrimalSolution double error = CoinMin(1.0e-2, model_->largestPrimalError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // But cap tolerance = CoinMin(1000.0, tolerance); int numberRows = model_->numberRows(); int numberInfeasible = 0; for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = model_->solution(iPivot); double lower = model_->lower(iPivot); double upper = model_->upper(iPivot); if (value < lower - tolerance) { numberInfeasible++; } else if (value > upper + tolerance) { numberInfeasible++; } } return (numberInfeasible == 0); } // Called when maximum pivots changes void ClpDualRowSteepest::maximumPivotsChanged() { if (alternateWeights_ && alternateWeights_->capacity() != model_->numberRows() + model_->factorization()->maximumPivots()) { delete alternateWeights_; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization alternateWeights_->reserve(model_->numberRows() + model_->factorization()->maximumPivots()); } } Clp-1.15.10/src/CoinAbcFactorization4.cpp0000644000076600007660000000101712101105055016452 0ustar coincoin/* $Id: CoinAbcFactorization4.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization4.cpp" #endif Clp-1.15.10/src/AbcDualRowPivot.hpp0000644000076600007660000000730012101105055015346 0ustar coincoin/* $Id: AbcDualRowPivot.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcDualRowPivot_H #define AbcDualRowPivot_H #include "AbcCommon.hpp" class AbcSimplex; class CoinIndexedVector; //############################################################################# /** Dual Row Pivot Abstract Base Class Abstract Base Class for describing an interface to an algorithm to choose row pivot in dual simplex algorithm. For some algorithms e.g. Dantzig choice then some functions may be null. */ class AbcDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow() = 0; /** Does most of work for weights and returns pivot alpha. Also does FT update */ virtual double updateWeights1(CoinIndexedVector & input,CoinIndexedVector & updateColumn) = 0; virtual void updateWeightsOnly(CoinIndexedVector & input) = 0; virtual double updateWeights(CoinIndexedVector & input,CoinIndexedVector & updateColumn) = 0; /// Actually updates weights virtual void updateWeights2(CoinIndexedVector & input,CoinIndexedVector & updateColumn) = 0; /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Would be faster if we kept basic regions, but on other hand it means everything is always in sync */ virtual void updatePrimalSolution(CoinIndexedVector & updateColumn, double theta) = 0; virtual void updatePrimalSolutionAndWeights(CoinIndexedVector & weightsVector, CoinIndexedVector & updateColumn, double theta); /** Saves any weights round factorization as pivot rows may change Will be empty unless steepest edge (will save model) May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) for strong branching - initialize , infeasibilities */ virtual void saveWeights(AbcSimplex * model, int mode); /// Recompute infeasibilities virtual void recomputeInfeasibilities(); /// checks accuracy and may re-initialize (may be empty) virtual void checkAccuracy(); /// Gets rid of all arrays (may be empty) virtual void clearArrays(); /// Returns true if would not find any row virtual bool looksOptimal() const { return false; } //@} ///@name Constructors and destructors //@{ /// Default Constructor AbcDualRowPivot(); /// Copy constructor AbcDualRowPivot(const AbcDualRowPivot &); /// Assignment operator AbcDualRowPivot & operator=(const AbcDualRowPivot& rhs); /// Destructor virtual ~AbcDualRowPivot (); /// Clone virtual AbcDualRowPivot * clone(bool copyData = true) const = 0; //@} ///@name Other //@{ /// Returns model inline AbcSimplex * model() { return model_; } /// Sets model (normally to NULL) inline void setModel(AbcSimplex * newmodel) { model_ = newmodel; } /// Returns type (above 63 is extra information) inline int type() { return type_; } //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Pointer to model AbcSimplex * model_; /// Type of row pivot algorithm int type_; //@} }; #ifndef CLP_DUAL_COLUMN_MULTIPLIER //#define CLP_DUAL_COLUMN_MULTIPLIER 0.99999 #endif #endif Clp-1.15.10/src/AbcSimplexPrimal.cpp0000644000076600007660000042554412252354371015564 0ustar coincoin/* $Id: AbcSimplexPrimal.cpp 2006 2013-12-12 15:40:41Z forrest $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Notes on implementation of primal simplex algorithm. When primal feasible(A): If dual feasible, we are optimal. Otherwise choose an infeasible basic variable to enter basis from a bound (B). We now need to find an outgoing variable which will leave problem primal feasible so we get the column of the tableau corresponding to the incoming variable (with the correct sign depending if variable will go up or down). We now perform a ratio test to determine which outgoing variable will preserve primal feasibility (C). If no variable found then problem is unbounded (in primal sense). If there is a variable, we then perform pivot and repeat. Trivial? ------------------------------------------- A) How do we get primal feasible? All variables have fake costs outside their feasible region so it is trivial to declare problem feasible. OSL did not have a phase 1/phase 2 approach but instead effectively put an extra cost on infeasible basic variables I am taking the same approach here, although it is generalized to allow for non-linear costs and dual information. In OSL, this weight was changed heuristically, here at present it is only increased if problem looks finished. If problem is feasible I check for unboundedness. If not unbounded we could play with going into dual. As long as weights increase any algorithm would be finite. B) Which incoming variable to choose is a virtual base class. For difficult problems steepest edge is preferred while for very easy (large) problems we will need partial scan. C) Sounds easy, but this is hardest part of algorithm. 1) Instead of stopping at first choice, we may be able to allow that variable to go through bound and if objective still improving choose again. These mini iterations can increase speed by orders of magnitude but we may need to go to more of a bucket choice of variable rather than looking at them one by one (for speed). 2) Accuracy. Basic infeasibilities may be less than tolerance. Pivoting on these makes objective go backwards. OSL modified cost so a zero move was made, Gill et al modified so a strictly positive move was made. The two problems are that re-factorizations can change rinfeasibilities above and below tolerances and that when finished we need to reset costs and try again. 3) Degeneracy. Gill et al helps but may not be enough. We may need more. Also it can improve speed a lot if we perturb the rhs and bounds significantly. References: Forrest and Goldfarb, Steepest-edge simplex algorithms for linear programming - Mathematical Programming 1992 Forrest and Tomlin, Implementing the simplex method for the Optimization Subroutine Library - IBM Systems Journal 1992 Gill, Murray, Saunders, Wright A Practical Anti-Cycling Procedure for Linear and Nonlinear Programming SOL report 1988 TODO: a) Better recovery procedures. At present I never check on forward progress. There is checkpoint/restart with reducing re-factorization frequency, but this is only on singular factorizations. b) Fast methods for large easy problems (and also the option for the code to automatically choose which method). c) We need to be able to stop in various ways for OSI - this is fairly easy. */ #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "AbcSimplexPrimal.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcNonLinearCost.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "AbcPrimalColumnPivot.hpp" #include "ClpMessage.hpp" #include "ClpEventHandler.hpp" #include #include #include #include #include #ifdef CLP_USER_DRIVEN1 /* Returns true if variable sequenceOut can leave basis when model->sequenceIn() enters. This function may be entered several times for each sequenceOut. The first time realAlpha will be positive if going to lower bound and negative if going to upper bound (scaled bounds in lower,upper) - then will be zero. currentValue is distance to bound. currentTheta is current theta. alpha is fabs(pivot element). Variable will change theta if currentValue - currentTheta*alpha < 0.0 */ bool userChoiceValid1(const AbcSimplex * model, int sequenceOut, double currentValue, double currentTheta, double alpha, double realAlpha); /* This returns true if chosen in/out pair valid. The main thing to check would be variable flipping bounds may be OK. This would be signaled by reasonable theta_ and valueOut_. If you return false sequenceIn_ will be flagged as ineligible. */ bool userChoiceValid2(const AbcSimplex * model); /* If a good pivot then you may wish to unflag some variables. */ void userChoiceWasGood(AbcSimplex * model); #endif #ifdef TRY_SPLIT_VALUES_PASS static double valuesChunk=-10.0; static double valuesRatio=0.1; static int valuesStop=-1; static int keepValuesPass=-1; static int doOrdinaryVariables=-1; #endif // primal int AbcSimplexPrimal::primal (int ifValuesPass , int /*startFinishOptions*/) { /* Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of infeasibilityCost_ being given to getting primal feasible. In this version I have tried to be clever in a stupid way. The idea of fake bounds in dual seems to work so the primal analogue would be that of getting bounds on reduced costs (by a presolve approach) and using these for being above or below feasible region. I decided to waste memory and keep these explicitly. This allows for non-linear costs! The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find incoming variable for Dantzig row choice. For steepest edge we keep an updated list of dual infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure of the exact details. The flow of primal is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by changing bounds so primal feasible. If looks finished check fake primal bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot column (incoming variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot column in tableau Choose outgoing row. If we don't find one then we look primal unbounded so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find outgoing row, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve changing bounds on variables to stay primal feasible. } } At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot in option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. */ algorithm_ = +1; moreSpecialOptions_ &= ~16; // clear check replaceColumn accuracy #if ABC_PARALLEL>0 if (parallelMode()) { // extra regions // for moment allow for ordered factorization int length=2*numberRows_+abcFactorization_->maximumPivots(); for (int i = 0; i < 6; i++) { delete rowArray_[i]; rowArray_[i] = new CoinIndexedVector(); rowArray_[i]->reserve(length); delete columnArray_[i]; columnArray_[i] = new CoinIndexedVector(); columnArray_[i]->reserve(length); } } #endif // save data ClpDataSave data = saveData(); dualTolerance_ = dblParam_[ClpDualTolerance]; primalTolerance_ = dblParam_[ClpPrimalTolerance]; currentDualTolerance_=dualTolerance_; //nextCleanNonBasicIteration_=baseIteration_+numberRows_; // Save so can see if doing after dual int initialStatus = problemStatus_; int initialIterations = numberIterations_; int initialNegDjs = -1; // copy bounds to perturbation CoinAbcMemcpy(abcPerturbation_,abcLower_,numberTotal_); CoinAbcMemcpy(abcPerturbation_+numberTotal_,abcUpper_,numberTotal_); #if 0 if (numberRows_>80000&&numberRows_<90000) { FILE * fp = fopen("save.stuff", "rb"); if (fp) { fread(internalStatus_,sizeof(char),numberTotal_,fp); fread(abcSolution_,sizeof(double),numberTotal_,fp); } else { printf("can't open save.stuff\n"); abort(); } fclose(fp); } #endif // initialize - maybe values pass and algorithm_ is +1 /// Initial coding here if (nonLinearCost_ == NULL && algorithm_ > 0) { // get a valid nonlinear cost function abcNonLinearCost_ = new AbcNonLinearCost(this); } statusOfProblemInPrimal(0); /*if (!startup(ifValuesPass))*/ { // Set average theta abcNonLinearCost_->setAverageTheta(1.0e3); // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // This says whether to restore things etc int factorType = 0; if (problemStatus_ < 0 && perturbation_ < 100 && !ifValuesPass) { perturb(0); if (perturbation_!=100) { // Can't get here if values pass assert (!ifValuesPass); gutsOfPrimalSolution(3); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } } // Start check for cycles abcProgress_.fillFromModel(this); abcProgress_.startCheck(); double pivotTolerance=abcFactorization_->pivotTolerance(); /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible -5 - looks unbounded */ while (problemStatus_ < 0) { // clear all arrays clearArrays(-1); // If getting nowhere - why not give it a kick #if 1 if (perturbation_ < 101 && numberIterations_ ==6078/*> 2 * (numberRows_ + numberColumns_)*/ && (specialOptions_ & 4) == 0 && initialStatus != 10) { perturb(1); } #endif // If we have done no iterations - special if (lastGoodIteration_ == numberIterations_ && factorType) factorType = 3; if(pivotTolerancepivotTolerance()) { // force factorization pivotTolerance = abcFactorization_->pivotTolerance(); factorType=5; } // may factorize, checks if problem finished if (factorType) statusOfProblemInPrimal(factorType); if (problemStatus_==10 && (moreSpecialOptions_ & 2048) != 0) { problemStatus_=0; } if (initialStatus == 10) { initialStatus=-1; // cleanup phase if(initialIterations != numberIterations_) { if (numberDualInfeasibilities_ > 10000 && numberDualInfeasibilities_ > 10 * initialNegDjs) { // getting worse - try perturbing if (perturbation_ < 101 && (specialOptions_ & 4) == 0) { perturb(1); statusOfProblemInPrimal(factorType); } } } else { // save number of negative djs if (!numberPrimalInfeasibilities_) initialNegDjs = numberDualInfeasibilities_; // make sure weight won't be changed if (infeasibilityCost_ == 1.0e10) infeasibilityCost_ = 1.000001e10; } } // Say good factorization factorType = 1; // Say no pivot has occurred (for steepest edge and updates) pivotRow_ = -2; // exit if victory declared if (problemStatus_ >= 0) { #ifdef CLP_USER_DRIVEN int status = eventHandler_->event(ClpEventHandler::endInPrimal); if (status>=0&&status<10) { // carry on problemStatus_=-1; if (status==0) continue; // re-factorize } else if (status>=10) { problemStatus_=status-10; break; } else { break; } #else break; #endif } // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && firstFree_ < 0)) { problemStatus_ = 3; break; } if (firstFree_ < 0) { if (ifValuesPass) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } //#define FEB_TRY #if 1 //def FEB_TRY if (perturbation_ < 100 #ifdef TRY_SPLIT_VALUES_PASS &&valuesStop<0 #endif ) perturb(0); #endif } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Iterate whileIterating(ifValuesPass ? 1 : 0); } } // if infeasible get real values //printf("XXXXY final cost %g\n",infeasibilityCost_); abcProgress_.initialWeight_ = 0.0; if (problemStatus_ == 1 && secondaryStatus_ != 6) { infeasibilityCost_ = 0.0; copyFromSaved(); delete abcNonLinearCost_; abcNonLinearCost_ = new AbcNonLinearCost(this); abcNonLinearCost_->checkInfeasibilities(0.0); sumPrimalInfeasibilities_ = abcNonLinearCost_->sumInfeasibilities(); numberPrimalInfeasibilities_ = abcNonLinearCost_->numberInfeasibilities(); // and get good feasible duals gutsOfPrimalSolution(1); } // clean up unflag(); abcProgress_.clearTimesFlagged(); #if ABC_PARALLEL>0 if (parallelMode()) { for (int i = 0; i < 6; i++) { delete rowArray_[i]; rowArray_[i] = NULL; delete columnArray_[i]; columnArray_[i] = NULL; } } #endif //finish(startFinishOptions); restoreData(data); setObjectiveValue(abcNonLinearCost_->feasibleReportCost()+objectiveOffset_); // clean up if (problemStatus_==10) abcNonLinearCost_->checkInfeasibilities(0.0); delete abcNonLinearCost_; abcNonLinearCost_=NULL; #if 0 if (numberRows_>80000&&numberRows_<90000) { FILE * fp = fopen("save.stuff", "wb"); if (fp) { fwrite(internalStatus_,sizeof(char),numberTotal_,fp); fwrite(abcSolution_,sizeof(double),numberTotal_,fp); } else { printf("can't open save.stuff\n"); abort(); } fclose(fp); } #endif return problemStatus_; } /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) -4 end of values pass and done iterations +0 looks optimal (might be infeasible - but we will investigate) +2 looks unbounded +3 max iterations */ int AbcSimplexPrimal::whileIterating(int valuesOption) { #if 1 #define DELAYED_UPDATE arrayForBtran_=0; //setUsedArray(arrayForBtran_); arrayForFtran_=1; setUsedArray(arrayForFtran_); arrayForFlipBounds_=2; setUsedArray(arrayForFlipBounds_); arrayForTableauRow_=3; setUsedArray(arrayForTableauRow_); //arrayForDualColumn_=4; //setUsedArray(arrayForDualColumn_); #if ABC_PARALLEL<2 arrayForReplaceColumn_=4; //4; #else arrayForReplaceColumn_=6; //4; setUsedArray(arrayForReplaceColumn_); #endif //arrayForFlipRhs_=5; //setUsedArray(arrayForFlipRhs_); #endif // Say if values pass int ifValuesPass = (firstFree_ >= 0) ? 1 : 0; int returnCode = -1; int superBasicType = 1; if (valuesOption > 1) superBasicType = 3; int numberStartingInfeasibilities=abcNonLinearCost_->numberInfeasibilities(); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int numberFlaggedStart =abcProgress_.timesFlagged(); while (problemStatus_ == -1) { if (!ifValuesPass) { // choose column to come in // can use pivotRow_ to update weights // pass in list of cost changes so can do row updates (rowArray_[1]) // NOTE rowArray_[0] is used by computeDuals which is a // slow way of getting duals but might be used int saveSequence=sequenceIn_; primalColumn(&usefulArray_[arrayForFtran_], &usefulArray_[arrayForTableauRow_], &usefulArray_[arrayForFlipBounds_]); if (saveSequence>=0&&saveSequence!=sequenceOut_) { if (getInternalStatus(saveSequence)==basic) abcDj_[saveSequence]=0.0; } #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel()==63) { for (int i=0;i1.0e2) assert (getInternalStatus(i)!=basic); } double largestCost=0.0; double largestDj=0.0; double largestGoodDj=0.0; int iLargest=-1; int numberInfeasibilities=0; double sum=0.0; for (int i=0;iabcUpper_[i]+primalTolerance_) { numberInfeasibilities++; sum += abcSolution_[i]-abcUpper_[i]-primalTolerance_; } else if (abcSolution_[i]=numberRows_) { xx='C'; kLargest=iLargest-numberRows_; } else { xx='R'; kLargest=iLargest; } printf("largest cost %g, largest dj %g best %g (%d==%c%d) - %d infeasible (sum %g) nonlininf %d\n", largestCost,largestDj,largestGoodDj,iLargest,xx,kLargest,numberInfeasibilities,sum, abcNonLinearCost_->numberInfeasibilities()); assert (getInternalStatus(iLargest)!=basic); } #endif } else { // in values pass for (int i=0;i<4;i++) multipleSequenceIn_[i]=-1; int sequenceIn = nextSuperBasic(superBasicType, &usefulArray_[arrayForFlipBounds_]); if (valuesOption > 1) superBasicType = 2; if (sequenceIn < 0) { // end of values pass - initialize weights etc sequenceIn_=-1; handler_->message(CLP_END_VALUES_PASS, messages_) << numberIterations_; stateOfProblem_ &= ~VALUES_PASS; #ifdef TRY_SPLIT_VALUES_PASS valuesStop=numberIterations_+doOrdinaryVariables; #endif abcPrimalColumnPivot_->saveWeights(this, 5); problemStatus_ = -2; // factorize now pivotRow_ = -1; // say no weights update returnCode = -4; // Clean up for (int i = 0; i < numberTotal_; i++) { if (getInternalStatus(i) == atLowerBound || getInternalStatus(i) == isFixed) abcSolution_[i] = abcLower_[i]; else if (getInternalStatus(i) == atUpperBound) abcSolution_[i] = abcUpper_[i]; } break; } else { // normal sequenceIn_ = sequenceIn; valueIn_ = abcSolution_[sequenceIn_]; lowerIn_ = abcLower_[sequenceIn_]; upperIn_ = abcUpper_[sequenceIn_]; dualIn_ = abcDj_[sequenceIn_]; // see if any more if (maximumIterations()==100000) { multipleSequenceIn_[0]=sequenceIn; for (int i=1;i<4;i++) { int sequenceIn = nextSuperBasic(superBasicType, &usefulArray_[arrayForFlipBounds_]); if (sequenceIn>=0) multipleSequenceIn_[i]=sequenceIn; else break; } } } } pivotRow_ = -1; sequenceOut_ = -1; usefulArray_[arrayForFtran_].clear(); if (sequenceIn_ >= 0) { // we found a pivot column assert (!flagged(sequenceIn_)); //#define MULTIPLE_PRICE // do second half of iteration if (multipleSequenceIn_[1]==-1||maximumIterations()!=100000) { returnCode = pivotResult(ifValuesPass); } else { if (multipleSequenceIn_[0]<0) multipleSequenceIn_[0]=sequenceIn_; returnCode = pivotResult4(ifValuesPass); #ifdef MULTIPLE_PRICE if (sequenceIn_>=0) returnCode = pivotResult(ifValuesPass); #endif } if(numberStartingInfeasibilities&&!abcNonLinearCost_->numberInfeasibilities()) { //if (abcFactorization_->pivots()>200&&numberIterations_>2*(numberRows_+numberColumns_)) if (abcFactorization_->pivots()>2&&numberIterations_>(numberRows_+numberColumns_)&&(stateOfProblem_&PESSIMISTIC)!=0) returnCode=-2; // refactorize - maybe just after n iterations } if (returnCode < -1 && returnCode > -5) { problemStatus_ = -2; // } else if (returnCode == -5) { if (abcProgress_.timesFlagged()>10+numberFlaggedStart) problemStatus_ =-2; if ((moreSpecialOptions_ & 16) == 0 && abcFactorization_->pivots()) { moreSpecialOptions_ |= 16; problemStatus_ = -2; } // otherwise something flagged - continue; } else if (returnCode == 2) { problemStatus_ = -5; // looks unbounded } else if (returnCode == 4) { problemStatus_ = -2; // looks unbounded but has iterated } else if (returnCode != -1) { assert(returnCode == 3); if (problemStatus_ != 5) problemStatus_ = 3; } } else { // no pivot column #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (abcNonLinearCost_->numberInfeasibilities()) problemStatus_ = -4; // might be infeasible // Force to re-factorize early next time int numberPivots = abcFactorization_->pivots(); returnCode = 0; #ifdef CLP_USER_DRIVEN // If large number of pivots trap later? if (problemStatus_==-1 && numberPivots<13000) { int status = eventHandler_->event(ClpEventHandler::noCandidateInPrimal); if (status>=0&&status<10) { // carry on problemStatus_=-1; if (status==0) break; } else if (status>=10) { problemStatus_=status-10; break; } else { forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); break; } } #else forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); break; #endif } } if (valuesOption > 1) usefulArray_[arrayForFlipBounds_].setNumElements(0); return returnCode; } /* Checks if finished. Updates status */ void AbcSimplexPrimal::statusOfProblemInPrimal(int type) { int saveFirstFree = firstFree_; // number of pivots done int numberPivots = abcFactorization_->pivots(); #if 0 printf("statusOf %d pivots type %d pstatus %d forceFac %d dont %d\n", numberPivots,type,problemStatus_,forceFactorization_,dontFactorizePivots_); #endif //int saveType=type; if (type>=4) { // force factorization type &= 3; numberPivots=9999999; } #ifndef TRY_ABC_GUS bool doFactorization = (type != 3&&(numberPivots>dontFactorizePivots_||numberIterations_==baseIteration_||problemStatus_==10)); #else bool doFactorization = (type != 3&&(numberPivots>dontFactorizePivots_||numberIterations_==baseIteration_)); #endif bool doWeights = doFactorization||problemStatus_==10; if (type == 2) { // trouble - restore solution restoreGoodStatus(1); forceFactorization_ = 1; // a bit drastic but .. pivotRow_ = -1; // say no weights update changeMade_++; // say change made } int tentativeStatus = problemStatus_; double lastSumInfeasibility = COIN_DBL_MAX; int lastNumberInfeasibility = 1; #ifndef CLP_CAUTION #define CLP_CAUTION 1 #endif #if CLP_CAUTION double lastAverageInfeasibility = sumDualInfeasibilities_ / static_cast(numberDualInfeasibilities_ + 1); #endif if (numberIterations_&&type) { lastSumInfeasibility = abcNonLinearCost_->sumInfeasibilities(); lastNumberInfeasibility = abcNonLinearCost_->numberInfeasibilities(); } else { lastAverageInfeasibility=1.0e10; } bool ifValuesPass=(stateOfProblem_&VALUES_PASS)!=0; bool takenAction=false; double sumInfeasibility=0.0; if (problemStatus_ > -3 || problemStatus_ == -4) { // factorize // later on we will need to recover from singularities // also we could skip if first time // do weights // This may save pivotRow_ for use if (doFactorization) abcPrimalColumnPivot_->saveWeights(this, 1); if (!type) { // be optimistic stateOfProblem_ &= ~PESSIMISTIC; // but use 0.1 double newTolerance = CoinMax(0.1, saveData_.pivotTolerance_); abcFactorization_->pivotTolerance(newTolerance); } if (doFactorization) { // is factorization okay? int solveType = ifValuesPass ? 11 :1; if (!type) solveType++; int factorStatus = internalFactorize(solveType); if (factorStatus) { if (type != 1 || largestPrimalError_ > 1.0e3 || largestDualError_ > 1.0e3) { #if ABC_NORMAL_DEBUG>0 printf("Bad initial basis\n"); #endif internalFactorize(2); } else { // no - restore previous basis // Keep any flagged variables for (int i = 0; i < numberTotal_; i++) { if (flagged(i)) internalStatusSaved_[i] |= 64; //say flagged } restoreGoodStatus(1); if (numberPivots <= 1) { // throw out something if (sequenceIn_ >= 0 && getInternalStatus(sequenceIn_) != basic) { setFlagged(sequenceIn_); } else if (sequenceOut_ >= 0 && getInternalStatus(sequenceOut_) != basic) { setFlagged(sequenceOut_); } abcProgress_.incrementTimesFlagged(); double newTolerance = CoinMax(0.5 + 0.499 * randomNumberGenerator_.randomDouble(), abcFactorization_->pivotTolerance()); abcFactorization_->pivotTolerance(newTolerance); } else { // Go to safe abcFactorization_->pivotTolerance(0.99); } forceFactorization_ = 1; // a bit drastic but .. type = 2; abcNonLinearCost_->checkInfeasibilities(); if (internalFactorize(2) != 0) { largestPrimalError_ = 1.0e4; // force other type } } changeMade_++; // say change made } } if (problemStatus_ != -4) problemStatus_ = -3; // at this stage status is -3 or -5 if looks unbounded // get primal and dual solutions // put back original costs and then check // createRim(4); // costs do not change if (ifValuesPass&&numberIterations_==baseIteration_) { abcNonLinearCost_->checkInfeasibilities(primalTolerance_); lastSumInfeasibility = abcNonLinearCost_->largestInfeasibility(); } #ifdef CLP_USER_DRIVEN int status = eventHandler_->event(ClpEventHandler::goodFactorization); if (status >= 0) { lastSumInfeasibility = COIN_DBL_MAX; } #endif if (ifValuesPass&&numberIterations_==baseIteration_) { double * save = new double[numberRows_]; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; save[iRow] = abcSolution_[iPivot]; } int numberOut = 1; while (numberOut) { gutsOfPrimalSolution(2); double badInfeasibility = abcNonLinearCost_->largestInfeasibility(); numberOut = 0; // But may be very large rhs etc double useError = CoinMin(largestPrimalError_, 1.0e5 / CoinAbcMaximumAbsElement(abcSolution_, numberTotal_)); if ((lastSumInfeasibility < incomingInfeasibility_ || badInfeasibility > (CoinMax(10.0, 100.0 * lastSumInfeasibility))) && (badInfeasibility > 10.0 ||useError > 1.0e-3)) { //printf("Original largest infeas %g, now %g, primalError %g\n", // lastSumInfeasibility,abcNonLinearCost_->largestInfeasibility(), // largestPrimalError_); // throw out up to 1000 structurals int * sort = new int[numberRows_]; // first put back solution and store difference for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; double difference = fabs(abcSolution_[iPivot] - save[iRow]); abcSolution_[iPivot] = save[iRow]; save[iRow] = difference; } abcNonLinearCost_->checkInfeasibilities(primalTolerance_); printf("Largest infeasibility %g\n",abcNonLinearCost_->largestInfeasibility()); int numberBasic = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = abcPivotVariable_[iRow]; if (iPivot >= numberRows_) { // column double difference = save[iRow]; if (difference > 1.0e-4) { sort[numberOut] = iRow; save[numberOut++] = -difference; if (getInternalStatus(iPivot) == basic) numberBasic++; } } } if (!numberBasic) { //printf("no errors on basic - going to all slack - numberOut %d\n",numberOut); // allow numberOut = 0; } CoinSort_2(save, save + numberOut, sort); numberOut = CoinMin(1000, numberOut); // for now bring in any slack int jRow=0; for (int i = 0; i < numberOut; i++) { int iRow = sort[i]; int iColumn = abcPivotVariable_[iRow]; assert (getInternalStatus(iColumn)==basic); setInternalStatus(iColumn, superBasic); while (getInternalStatus(jRow)==basic) jRow++; setInternalStatus(jRow, basic); abcPivotVariable_[iRow] = jRow; if (fabs(abcSolution_[iColumn]) > 1.0e10) { if (abcUpper_[iColumn] < 0.0) { abcSolution_[iColumn] = abcUpper_[iColumn]; } else if (abcLower_[iColumn] > 0.0) { abcSolution_[iColumn] = abcLower_[iColumn]; } else { abcSolution_[iColumn] = 0.0; } } } delete [] sort; } if (numberOut) { int factorStatus = internalFactorize(12); assert (!factorStatus); } } delete [] save; } gutsOfPrimalSolution(3); sumInfeasibility = abcNonLinearCost_->sumInfeasibilities(); int reason2 = 0; #if CLP_CAUTION #if CLP_CAUTION==2 double test2 = 1.0e5; #else double test2 = 1.0e-1; #endif if (!lastSumInfeasibility && sumInfeasibility>1.0e3*primalTolerance_ && lastAverageInfeasibility < test2 && numberPivots > 10&&!ifValuesPass) reason2 = 3; if (lastSumInfeasibility < 1.0e-6 && sumInfeasibility > 1.0e-3 && numberPivots > 10&&!ifValuesPass) reason2 = 4; #endif if ((sumInfeasibility > 1.0e7 && sumInfeasibility > 100.0 * lastSumInfeasibility && abcFactorization_->pivotTolerance() < 0.11) || (largestPrimalError_ > 1.0e10 && largestDualError_ > 1.0e10)) reason2 = 2; if (reason2) { takenAction=true; problemStatus_ = tentativeStatus; doFactorization = true; if (numberPivots) { // go back // trouble - restore solution restoreGoodStatus(1); sequenceIn_=-1; sequenceOut_=-1; abcNonLinearCost_->checkInfeasibilities(); if (reason2 < 3) { // Go to safe abcFactorization_->pivotTolerance(CoinMin(0.99, 1.01 * abcFactorization_->pivotTolerance())); forceFactorization_ = 1; // a bit drastic but .. } else if (forceFactorization_ < 0) { forceFactorization_ = CoinMin(numberPivots / 4, 100); } else { forceFactorization_ = CoinMin(forceFactorization_, CoinMax(3, numberPivots / 4)); } pivotRow_ = -1; // say no weights update changeMade_++; // say change made if (numberPivots == 1) { // throw out something if (sequenceIn_ >= 0 && getInternalStatus(sequenceIn_) != basic) { setFlagged(sequenceIn_); } else if (sequenceOut_ >= 0 && getInternalStatus(sequenceOut_) != basic) { setFlagged(sequenceOut_); } abcProgress_.incrementTimesFlagged(); } type = 2; // so will restore weights if (internalFactorize(2) != 0) { largestPrimalError_ = 1.0e4; // force other type } numberPivots = 0; gutsOfPrimalSolution(3); sumInfeasibility = abcNonLinearCost_->sumInfeasibilities(); } } } // Double check reduced costs if no action if (abcProgress_.lastIterationNumber(0) == numberIterations_) { if (abcPrimalColumnPivot_->looksOptimal()) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; } } // If in primal and small dj give up if ((specialOptions_ & 1024) != 0 && !numberPrimalInfeasibilities_ && numberDualInfeasibilities_) { double average = sumDualInfeasibilities_ / (static_cast (numberDualInfeasibilities_)); if (numberIterations_ > 300 && average < 1.0e-4) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; } } // Check if looping int loop; ifValuesPass=firstFree_>=0; if (type != 2 && !ifValuesPass) loop = abcProgress_.looping(); else loop = -1; if ((moreSpecialOptions_ & 2048) != 0 && !numberPrimalInfeasibilities_ && numberDualInfeasibilities_) { double average = sumDualInfeasibilities_ / (static_cast (numberDualInfeasibilities_)); if (abcProgress_.lastIterationNumber(2)==numberIterations_&& ((abcProgress_.timesFlagged()>2&&average < 1.0e-1)|| abcProgress_.timesFlagged()>20)) { numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; problemStatus_=3; loop=0; } } if (loop >= 0) { if (!problemStatus_) { // declaring victory numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; } else { problemStatus_ = loop; //exit if in loop problemStatus_ = 10; // instead - try other algorithm numberPrimalInfeasibilities_ = abcNonLinearCost_->numberInfeasibilities(); } problemStatus_ = 10; // instead - try other algorithm return ; } else if (loop < -1) { // Is it time for drastic measures if (abcNonLinearCost_->numberInfeasibilities() && abcProgress_.badTimes() > 5 && abcProgress_.oddState() < 10 && abcProgress_.oddState() >= 0) { abcProgress_.newOddState(); abcNonLinearCost_->zapCosts(); } // something may have changed gutsOfPrimalSolution(3); } // If progress then reset costs if (loop == -1 && !abcNonLinearCost_->numberInfeasibilities() && abcProgress_.oddState() < 0) { copyFromSaved(); // costs back delete abcNonLinearCost_; abcNonLinearCost_ = new AbcNonLinearCost(this); abcProgress_.endOddState(); gutsOfPrimalSolution(3); } abcProgress_.modifyObjective(abcNonLinearCost_->feasibleReportCost()); if (!lastNumberInfeasibility && sumInfeasibility && numberPivots > 1&&!ifValuesPass&& !takenAction&& abcProgress_.lastObjective(0)>=abcProgress_.lastObjective(CLP_PROGRESS-1)) { // first increase minimumThetaMovement_; // be more careful //abcFactorization_->saferTolerances (-0.99, -1.002); #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("thought feasible but sum is %g force %d minimum theta %g\n", sumInfeasibility, forceFactorization_,minimumThetaMovement_); #endif stateOfProblem_ |= PESSIMISTIC; if (minimumThetaMovement_<1.0e-10) { minimumThetaMovement_ *= 1.1; } else if (0) { int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 2)); if (handler_->logLevel() == 63) printf("Reducing factorization frequency to %d\n", forceFactorization_); } } } // Flag to say whether to go to dual to clean up bool goToDual = false; // really for free variables in //if((progressFlag_&2)!=0) //problemStatus_=-1;; progressFlag_ = 0; //reset progress flag handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << abcNonLinearCost_->feasibleReportCost()+objectiveOffset_; handler_->printing(abcNonLinearCost_->numberInfeasibilities() > 0) << abcNonLinearCost_->sumInfeasibilities() << abcNonLinearCost_->numberInfeasibilities(); handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; if (!primalFeasible()) { abcNonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfPrimalSolution(2); abcNonLinearCost_->checkInfeasibilities(primalTolerance_); } if (abcNonLinearCost_->numberInfeasibilities() > 0 && !abcProgress_.initialWeight_ && !ifValuesPass && infeasibilityCost_ == 1.0e10 #ifdef TRY_SPLIT_VALUES_PASS && valuesStop<0 #endif ) { // first time infeasible - start up weight computation // compute with original costs CoinAbcMemcpy(djSaved_,abcDj_,numberTotal_); CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_); gutsOfPrimalSolution(1); int numberSame = 0; int numberDifferent = 0; int numberZero = 0; int numberFreeSame = 0; int numberFreeDifferent = 0; int numberFreeZero = 0; int n = 0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) != basic && !flagged(iSequence)) { // not basic double distanceUp = abcUpper_[iSequence] - abcSolution_[iSequence]; double distanceDown = abcSolution_[iSequence] - abcLower_[iSequence]; double feasibleDj = abcDj_[iSequence]; double infeasibleDj = djSaved_[iSequence] - feasibleDj; double value = feasibleDj * infeasibleDj; if (distanceUp > primalTolerance_) { // Check if "free" if (distanceDown > primalTolerance_) { // free if (value > dualTolerance_) { numberFreeSame++; } else if(value < -dualTolerance_) { numberFreeDifferent++; abcDj_[n++] = feasibleDj / infeasibleDj; } else { numberFreeZero++; } } else { // should not be negative if (value > dualTolerance_) { numberSame++; } else if(value < -dualTolerance_) { numberDifferent++; abcDj_[n++] = feasibleDj / infeasibleDj; } else { numberZero++; } } } else if (distanceDown > primalTolerance_) { // should not be positive if (value > dualTolerance_) { numberSame++; } else if(value < -dualTolerance_) { numberDifferent++; abcDj_[n++] = feasibleDj / infeasibleDj; } else { numberZero++; } } } abcProgress_.initialWeight_ = -1.0; } //printf("XXXX %d same, %d different, %d zero, -- free %d %d %d\n", // numberSame,numberDifferent,numberZero, // numberFreeSame,numberFreeDifferent,numberFreeZero); // we want most to be same if (n) { double most = 0.95; std::sort(abcDj_, abcDj_ + n); int which = static_cast ((1.0 - most) * static_cast (n)); double take = -abcDj_[which] * infeasibilityCost_; //printf("XXXXZ inf cost %g take %g (range %g %g)\n",infeasibilityCost_,take,-abcDj_[0]*infeasibilityCost_,-abcDj_[n-1]*infeasibilityCost_); take = -abcDj_[0] * infeasibilityCost_; infeasibilityCost_ = CoinMin(CoinMax(1000.0 * take, 1.0e8), 1.0000001e10);; //printf("XXXX increasing weight to %g\n",infeasibilityCost_); } abcNonLinearCost_->checkInfeasibilities(0.0); gutsOfPrimalSolution(3); } double trueInfeasibility = abcNonLinearCost_->sumInfeasibilities(); if (!abcNonLinearCost_->numberInfeasibilities() && infeasibilityCost_ == 1.0e10 && !ifValuesPass && true) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; // relax if default infeasibilityCost_ = CoinMin(CoinMax(100.0 * sumDualInfeasibilities_, 1.0e8), 1.00000001e10); // reset looping criterion abcProgress_.reset(); trueInfeasibility = 1.123456e10; } if (trueInfeasibility > 1.0) { // If infeasibility going up may change weights double testValue = trueInfeasibility - 1.0e-4 * (10.0 + trueInfeasibility); double lastInf = abcProgress_.lastInfeasibility(1); double lastInf3 = abcProgress_.lastInfeasibility(3); double thisObj = abcProgress_.lastObjective(0); double thisInf = abcProgress_.lastInfeasibility(0); thisObj += infeasibilityCost_ * 2.0 * thisInf; double lastObj = abcProgress_.lastObjective(1); lastObj += infeasibilityCost_ * 2.0 * lastInf; double lastObj3 = abcProgress_.lastObjective(3); lastObj3 += infeasibilityCost_ * 2.0 * lastInf3; if (lastObj < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj)) - 1.0e-7 && firstFree_ < 0) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("lastobj %g this %g force %d\n", lastObj, thisObj, forceFactorization_); #endif int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 2)); #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("Reducing factorization frequency to %d\n", forceFactorization_); #endif } } else if (lastObj3 < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj3)) - 1.0e-7 && firstFree_ < 0) { #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("lastobj3 %g this3 %g force %d\n", lastObj3, thisObj, forceFactorization_); #endif int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ * 2) / 3); #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("Reducing factorization frequency to %d\n", forceFactorization_); #endif } } else if(lastInf < testValue || trueInfeasibility == 1.123456e10) { if (infeasibilityCost_ < 1.0e14) { infeasibilityCost_ *= 1.5; // reset looping criterion abcProgress_.reset(); #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() == 63) printf("increasing weight to %g\n", infeasibilityCost_); #endif gutsOfPrimalSolution(3); } } } // we may wish to say it is optimal even if infeasible bool alwaysOptimal = (specialOptions_ & 1) != 0; #if CLP_CAUTION // If twice nearly there ... if (lastAverageInfeasibility<2.0*dualTolerance_) { double averageInfeasibility = sumDualInfeasibilities_ / static_cast(numberDualInfeasibilities_ + 1); printf("last av %g now %g\n",lastAverageInfeasibility, averageInfeasibility); if (averageInfeasibility<2.0*dualTolerance_) sumOfRelaxedDualInfeasibilities_ = 0.0; } #endif // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say been feasible abcState_ |= CLP_ABC_BEEN_FEASIBLE; // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; // But if real primal infeasibilities nonzero carry on if (abcNonLinearCost_->numberInfeasibilities()) { // most likely to happen if infeasible double relaxedToleranceP = primalTolerance_; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, largestPrimalError_); // allow tolerance at least slightly bigger than standard relaxedToleranceP = relaxedToleranceP + error; int ninfeas = abcNonLinearCost_->numberInfeasibilities(); double sum = abcNonLinearCost_->sumInfeasibilities(); double average = sum / static_cast (ninfeas); #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() > 0) printf("nonLinearCost says infeasible %d summing to %g\n", ninfeas, sum); #endif if (average > relaxedToleranceP) { sumOfRelaxedPrimalInfeasibilities_ = sum; numberPrimalInfeasibilities_ = ninfeas; sumPrimalInfeasibilities_ = sum; #if ABC_NORMAL_DEBUG>3 bool unflagged = #endif unflag(); abcProgress_.clearTimesFlagged(); #if ABC_NORMAL_DEBUG>3 if (unflagged && handler_->logLevel() > 0) printf(" - but flagged variables\n"); #endif } } } //double saveSum=sumOfRelaxedDualInfeasibilities_; // had ||(type==3&&problemStatus_!=-5) -- ??? why ???? if ((dualFeasible() || problemStatus_ == -4) && !ifValuesPass) { // see if extra helps if (abcNonLinearCost_->numberInfeasibilities() && (abcNonLinearCost_->sumInfeasibilities() > 1.0e-3 || sumOfRelaxedPrimalInfeasibilities_) && !alwaysOptimal) { //may need infeasiblity cost changed // we can see if we can construct a ray // do twice to make sure Primal solution has settled // put non-basics to bounds in case tolerance moved // put back original costs CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; abcNonLinearCost_->checkInfeasibilities(0.0); gutsOfPrimalSolution(3); // put back original costs CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; abcNonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfPrimalSolution(3); // may have fixed infeasibilities - double check if (abcNonLinearCost_->numberInfeasibilities() == 0) { // carry on problemStatus_ = -1; abcNonLinearCost_->checkInfeasibilities(primalTolerance_); } else { if ((infeasibilityCost_ >= 1.0e18 || numberDualInfeasibilities_ == 0) && perturbation_ == 101 && (specialOptions_&8192)==0) { goToDual = unPerturb(); // stop any further perturbation #ifndef TRY_ABC_GUS if (abcNonLinearCost_->sumInfeasibilities() > 1.0e-1) goToDual = false; #endif numberDualInfeasibilities_ = 1; // carry on problemStatus_ = -1; } else if (numberDualInfeasibilities_ == 0 && largestDualError_ > 1.0e-2 #ifndef TRY_ABC_GUS &&((moreSpecialOptions_ & 256) == 0&&(specialOptions_ & 8192) == 0) #else &&(specialOptions_ & 8192) == 0 #endif ) { goToDual = true; abcFactorization_->pivotTolerance(CoinMax(0.5, abcFactorization_->pivotTolerance())); } if (!goToDual) { if (infeasibilityCost_ >= 1.0e20 || numberDualInfeasibilities_ == 0) { // we are infeasible - use as ray delete [] ray_; ray_ = new double [numberRows_]; CoinMemcpyN(dual_, numberRows_, ray_); // and get feasible duals infeasibilityCost_ = 0.0; CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; abcNonLinearCost_->checkInfeasibilities(primalTolerance_); gutsOfPrimalSolution(3); // so will exit infeasibilityCost_ = 1.0e30; // reset infeasibilities sumPrimalInfeasibilities_ = abcNonLinearCost_->sumInfeasibilities();; numberPrimalInfeasibilities_ = abcNonLinearCost_->numberInfeasibilities(); } if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; // reset looping criterion abcProgress_.reset(); changeMade_++; // say change made handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; abcNonLinearCost_->checkInfeasibilities(0.0); gutsOfPrimalSolution(3); problemStatus_ = -1; //continue #ifndef TRY_ABC_GUS goToDual = false; #else if((specialOptions_&8192)==0&&!sumOfRelaxedDualInfeasibilities_) goToDual=true; #endif } else { // say infeasible problemStatus_ = 1; } } } } else { // may be optimal if (perturbation_ == 101) { goToDual = unPerturb(); // stop any further perturbation #ifndef TRY_ABC_GUS if ((numberRows_ > 20000 || numberDualInfeasibilities_) && !numberTimesOptimal_) #else if ((specialOptions_&8192)!=0) #endif goToDual = false; // Better to carry on a bit longer lastCleaned_ = -1; // carry on } bool unflagged = (unflag() != 0); abcProgress_.clearTimesFlagged(); if ( lastCleaned_ != numberIterations_ || unflagged) { handler_->message(CLP_PRIMAL_OPTIMAL, messages_) << primalTolerance_ << CoinMessageEol; if (numberTimesOptimal_ < 4) { numberTimesOptimal_++; changeMade_++; // say change made if (numberTimesOptimal_ == 1) { // better to have small tolerance even if slower abcFactorization_->zeroTolerance(CoinMin(abcFactorization_->zeroTolerance(), 1.0e-15)); } lastCleaned_ = numberIterations_; if (primalTolerance_ != dblParam_[ClpPrimalTolerance]) handler_->message(CLP_PRIMAL_ORIGINAL, messages_) << CoinMessageEol; double oldTolerance = primalTolerance_; primalTolerance_ = dblParam_[ClpPrimalTolerance]; // put back original costs and then check #if 0 //ndef NDEBUG double largestDifference=0.0; for (int i=0;ilogLevel()==63) printf("largest change in cost %g\n",largestDifference); #endif CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; abcNonLinearCost_->checkInfeasibilities(oldTolerance); gutsOfPrimalSolution(3); if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; goToDual=false; } if (dualFeasible() && !abcNonLinearCost_->numberInfeasibilities() && lastCleaned_ >= 0) problemStatus_ = 0; else problemStatus_ = -1; } else { problemStatus_ = 0; // optimal if (lastCleaned_ < numberIterations_) { handler_->message(CLP_SIMPLEX_GIVINGUP, messages_) << CoinMessageEol; } } } else { if (!alwaysOptimal || !sumOfRelaxedPrimalInfeasibilities_) problemStatus_ = 0; // optimal else problemStatus_ = 1; // infeasible } } } else { // see if looks unbounded if (problemStatus_ == -5) { if (abcNonLinearCost_->numberInfeasibilities()) { if (infeasibilityCost_ > 1.0e18 && perturbation_ == 101) { // back off weight infeasibilityCost_ = 1.0e13; // reset looping criterion abcProgress_.reset(); unPerturb(); // stop any further perturbation } //we need infeasiblity cost changed if (infeasibilityCost_ < 1.0e20) { infeasibilityCost_ *= 5.0; // reset looping criterion abcProgress_.reset(); changeMade_++; // say change made handler_->message(CLP_PRIMAL_WEIGHT, messages_) << infeasibilityCost_ << CoinMessageEol; // put back original costs and then check CoinAbcMemcpy(abcCost_,costSaved_,numberTotal_);; gutsOfPrimalSolution(3); problemStatus_ = -1; //continue } else { // say infeasible problemStatus_ = 1; // we are infeasible - use as ray delete [] ray_; ray_ = new double [numberRows_]; CoinMemcpyN(dual_, numberRows_, ray_); } } else { // say unbounded problemStatus_ = 2; } } else { // carry on problemStatus_ = -1; if(type == 3 && !ifValuesPass) { //bool unflagged = unflag(); abcProgress_.clearTimesFlagged(); if (sumDualInfeasibilities_ < 1.0e-3 || (sumDualInfeasibilities_ / static_cast (numberDualInfeasibilities_)) < 1.0e-5 || abcProgress_.lastIterationNumber(0) == numberIterations_) { if (!numberPrimalInfeasibilities_) { if (numberTimesOptimal_ < 4) { numberTimesOptimal_++; changeMade_++; // say change made } else { problemStatus_ = 0; secondaryStatus_ = 5; } } } } } } if (problemStatus_ == 0) { double objVal = (abcNonLinearCost_->feasibleCost() + objective_->nonlinearOffset()); objVal /= (objectiveScale_ * rhsScale_); double tol = 1.0e-10 * CoinMax(fabs(objVal), fabs(objectiveValue_)) + 1.0e-8; if (fabs(objVal - objectiveValue_) > tol) { #if ABC_NORMAL_DEBUG>3 if (handler_->logLevel() > 0) printf("nonLinearCost has feasible obj of %g, objectiveValue_ is %g\n", objVal, objectiveValue_); #endif objectiveValue_ = objVal; } } if (type == 0 || type == 1) { saveGoodStatus(); } // see if in Cbc etc bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; bool disaster = false; if (disasterArea_ && inCbcOrOther && disasterArea_->check()) { disasterArea_->saveInfo(); disaster = true; } if (disaster) problemStatus_ = 3; if (problemStatus_ < 0 && !changeMade_) { problemStatus_ = 4; // unknown } lastGoodIteration_ = numberIterations_; if (numberIterations_ > lastBadIteration_ + 100) moreSpecialOptions_ &= ~16; // clear check accuracy flag #ifndef TRY_ABC_GUS if ((moreSpecialOptions_ & 256) != 0||saveSum||(specialOptions_ & 8192) != 0) goToDual=false; #else if ((specialOptions_ & 8192) != 0) goToDual=false; #endif if (goToDual || (numberIterations_ > 1000+baseIteration_ && largestPrimalError_ > 1.0e6 && largestDualError_ > 1.0e6)) { problemStatus_ = 10; // try dual // See if second call if ((moreSpecialOptions_ & 256) != 0||abcNonLinearCost_->sumInfeasibilities()>1.0e20) { numberPrimalInfeasibilities_ = abcNonLinearCost_->numberInfeasibilities(); sumPrimalInfeasibilities_ = abcNonLinearCost_->sumInfeasibilities(); // say infeasible if (numberPrimalInfeasibilities_&&(abcState_&CLP_ABC_BEEN_FEASIBLE)==0) problemStatus_ = 1; } } // make sure first free monotonic if (firstFree_ >= 0 && saveFirstFree >= 0) { firstFree_ = (numberIterations_) ? saveFirstFree : -1; nextSuperBasic(1, NULL); } #ifdef TRY_SPLIT_VALUES_PASS if (valuesChunk>0) { bool doFixing=firstFree_<0; if (numberIterations_==baseIteration_&& numberDualInfeasibilitiesWithoutFree_+1000((1.01*numberSuperBasic)/valuesChunk); doOrdinaryVariables=static_cast(valuesRatio*keepValuesPass); } else if (valuesStop>0) { if (numberIterations_>=valuesStop||problemStatus_>=0) { gutsOfSolution(3); abcNonLinearCost_->refreshFromPerturbed(primalTolerance_); gutsOfSolution(3); int numberSuperBasic=0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) == isFixed) { if (abcUpper_[iSequence]>abcLower_[iSequence]) { setInternalStatus(iSequence,superBasic); numberSuperBasic++; } } } if (numberSuperBasic) { stateOfProblem_ |= VALUES_PASS; problemStatus_=-1; gutsOfSolution(3); } else { doFixing=false; } valuesStop=-1; } else { doFixing=false; } } if (doFixing) { abcNonLinearCost_->refreshFromPerturbed(primalTolerance_); int numberSuperBasic=0; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) == isFixed) { if (abcUpper_[iSequence]>abcLower_[iSequence]) setInternalStatus(iSequence,superBasic); } if (getInternalStatus(iSequence) == superBasic) numberSuperBasic++; } int numberFixed=0; firstFree_=-1; if (numberSuperBasic) { double threshold = static_cast(keepValuesPass)/numberSuperBasic; if (1.1*keepValuesPass>numberSuperBasic) threshold=1.1; for (int iSequence = 0; iSequence < numberTotal_; iSequence++) { if (getInternalStatus(iSequence) == superBasic) { if (randomNumberGenerator_.randomDouble() -3) abcPrimalColumnPivot_->saveWeights(this, (type < 2) ? 2 : 4); else abcPrimalColumnPivot_->saveWeights(this, 3); } } // Computes solutions - 1 do duals, 2 do primals, 3 both int AbcSimplex::gutsOfPrimalSolution(int type) { //work space int whichArray[2]; for (int i=0;i<2;i++) whichArray[i]=getAvailableArray(); CoinIndexedVector * array1 = &usefulArray_[whichArray[0]]; CoinIndexedVector * array2 = &usefulArray_[whichArray[1]]; // do work and check int numberRefinements=0; if ((type&2)!=0) { numberRefinements=computePrimals(array1,array2); if (algorithm_ > 0 && abcNonLinearCost_ != NULL) { // primal algorithm // get correct bounds on all variables abcNonLinearCost_->checkInfeasibilities(primalTolerance_); if (abcNonLinearCost_->numberInfeasibilities()) if (handler_->detail(CLP_SIMPLEX_NONLINEAR, messages_) < 100) { handler_->message(CLP_SIMPLEX_NONLINEAR, messages_) << abcNonLinearCost_->changeInCost() << abcNonLinearCost_->numberInfeasibilities() << CoinMessageEol; } } checkPrimalSolution(true); } if ((type&1)!=0 #if CAN_HAVE_ZERO_OBJ>1 &&(specialOptions_&2097152)==0 #endif ) { numberRefinements+=computeDuals(NULL,array1,array2); checkDualSolution(); } for (int i=0;i<2;i++) setAvailableArray(whichArray[i]); rawObjectiveValue_ +=sumNonBasicCosts_; //computeObjective(); // ? done in checkDualSolution?? setClpSimplexObjectiveValue(); if (handler_->logLevel() > 3 || (largestPrimalError_ > 1.0e-2 || largestDualError_ > 1.0e-2)) handler_->message(CLP_SIMPLEX_ACCURACY, messages_) << largestPrimalError_ << largestDualError_ << CoinMessageEol; if ((largestPrimalError_ > 1.0e1||largestDualError_>1.0e1) && numberRows_ > 100 && numberIterations_) { #if ABC_NORMAL_DEBUG>0 printf("Large errors - primal %g dual %g\n", largestPrimalError_,largestDualError_); #endif // Change factorization tolerance //if (abcFactorization_->zeroTolerance() > 1.0e-18) //abcFactorization_->zeroTolerance(1.0e-18); } return numberRefinements; } /* Row array has pivot column This chooses pivot row. For speed, we may need to go to a bucket approach when many variables go through bounds On exit rhsArray will have changes in costs of basic variables */ void AbcSimplexPrimal::primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, int valuesPass) { #if 1 for (int iRow=0;iRowdenseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; dualIn_ -= alpha * costBasic_[iRow]; } // determine direction here if (dualIn_ < -dualTolerance_) { directionIn_ = 1; } else if (dualIn_ > dualTolerance_) { directionIn_ = -1; } else { // towards nearest bound if (valueIn_ - lowerIn_ < upperIn_ - valueIn_) { directionIn_ = -1; dualIn_ = dualTolerance_; } else { directionIn_ = 1; dualIn_ = -dualTolerance_; } } } // sequence stays as row number until end pivotRow_ = -1; int numberRemaining = 0; double totalThru = 0.0; // for when variables flip // Allow first few iterations to take tiny double acceptablePivot = 1.0e-1 * acceptablePivot_; if (numberIterations_ > 100) acceptablePivot = acceptablePivot_; if (abcFactorization_->pivots() > 10) acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (abcFactorization_->pivots() > 5) acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (abcFactorization_->pivots()) acceptablePivot = acceptablePivot_; // relax double bestEverPivot = acceptablePivot; int lastPivotRow = -1; double lastPivot = 0.0; double lastTheta = 1.0e50; // use spareArrays to put ones looked at in // First one is list of candidates // We could compress if we really know we won't need any more // Second array has current set of pivot candidates // with a backup list saved in double * part of indexed vector // pivot elements double * spare; // indices int * index; spareArray->clear(); spare = spareArray->denseVector(); index = spareArray->getIndices(); // we also need somewhere for effective rhs double * rhs = rhsArray->denseVector(); // and we can use indices to point to alpha // that way we can store fabs(alpha) int * indexPoint = rhsArray->getIndices(); //int numberFlip=0; // Those which may change if flips /* First we get a list of possible pivots. We can also see if the problem looks unbounded. At first we increase theta and see what happens. We start theta at a reasonable guess. If in right area then we do bit by bit. We save possible pivot candidates */ // do first pass to get possibles // We can also see if unbounded double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); // we need to swap sign if coming in from ub double way = directionIn_; double maximumMovement; if (way > 0.0) maximumMovement = CoinMin(1.0e30, upperIn_ - valueIn_); else maximumMovement = CoinMin(1.0e30, valueIn_ - lowerIn_); double averageTheta = abcNonLinearCost_->averageTheta(); double tentativeTheta = CoinMin(10.0 * averageTheta, maximumMovement); double upperTheta = maximumMovement; if (tentativeTheta > 0.5 * maximumMovement) tentativeTheta = maximumMovement; bool thetaAtMaximum = tentativeTheta == maximumMovement; // In case tiny bounds increase if (maximumMovement < 1.0) tentativeTheta *= 1.1; double dualCheck = fabs(dualIn_); // but make a bit more pessimistic dualCheck = CoinMax(dualCheck - 100.0 * dualTolerance_, 0.99 * dualCheck); int iIndex; //#define CLP_DEBUG #if ABC_NORMAL_DEBUG>3 if (numberIterations_ == 1369 || numberIterations_ == -3840) { double dj = abcCost_[sequenceIn_]; printf("cost in on %d is %g, dual in %g\n", sequenceIn_, dj, dualIn_); for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; int iPivot = abcPivotVariable_[iRow]; dj -= alpha * costBasic_[iRow]; printf("row %d var %d current %g %g %g, alpha %g so sol => %g (cost %g, dj %g)\n", iRow, iPivot, lowerBasic_[iRow], solutionBasic_[iRow], upperBasic_[iRow], alpha, solutionBasic_[iRow] - 1.0e9 * alpha, costBasic_[iRow], dj); } } #endif while (true) { totalThru = 0.0; // We also re-compute reduced cost numberRemaining = 0; dualIn_ = abcCost_[sequenceIn_]; #ifndef NDEBUG //double tolerance = primalTolerance_ * 1.002; #endif for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; dualIn_ -= alpha * costBasic_[iRow]; alpha *= way; double oldValue = solutionBasic_[iRow]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) bool possible; // do computation same way as later on in primal if (alpha > 0.0) { // basic variable going towards lower bound double bound = lowerBasic_[iRow]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) <= bound + primalTolerance_; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upperBasic_[iRow]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) >= bound - primalTolerance_; oldValue = bound - oldValue; alpha = - alpha; } double value; //assert (oldValue >= -10.0*tolerance); if (possible) { value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 if(!userChoiceValid1(this,iPivot,oldValue, upperTheta,alpha,work[iRow]*way)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; } // add to list spare[numberRemaining] = alpha; rhs[numberRemaining] = oldValue; indexPoint[numberRemaining] = iIndex; index[numberRemaining++] = iRow; totalThru += alpha; setActive(iRow); //} else if (value= 1.0001 * dualCheck) { // Can pivot here break; } else if (!thetaAtMaximum) { //printf("Going round with average theta of %g\n",averageTheta); tentativeTheta = maximumMovement; thetaAtMaximum = true; // seems to be odd compiler error } else { break; } } totalThru = 0.0; theta_ = maximumMovement; bool goBackOne = false; if (objective_->type() > 1) dualIn_ = saveDj; //printf("%d remain out of %d\n",numberRemaining,number); int iTry = 0; #define MAXTRY 1000 if (numberRemaining && upperTheta < maximumMovement) { // First check if previously chosen one will work // first get ratio with tolerance for ( ; iTry < MAXTRY; iTry++) { upperTheta = maximumMovement; int iBest = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 int sequenceOut=abcPivotVariable_[index[iIndex]]; if(!userChoiceValid1(this,sequenceOut,oldValue, upperTheta,alpha, 0.0)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; iBest = iIndex; // just in case weird numbers } } // now look at best in this lot // But also see how infeasible small pivots will make double sumInfeasibilities = 0.0; double bestPivot = acceptablePivot; pivotRow_ = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { int iRow = index[iIndex]; double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; if (value <= 0 || iBest == iIndex) { // how much would it cost to go thru and modify bound double trueAlpha = way * work[iRow]; totalThru += abcNonLinearCost_->changeInCost(iRow, trueAlpha, rhs[iIndex]); setActive(iRow); if (alpha > bestPivot) { bestPivot = alpha; theta_ = oldValue / bestPivot; pivotRow_ = iRow; } else if (alpha < acceptablePivot #ifdef CLP_USER_DRIVEN1 ||!userChoiceValid1(this,abcPivotVariable_[index[iIndex]], oldValue,upperTheta,alpha,0.0) #endif ) { if (value < -primalTolerance_) sumInfeasibilities += -value - primalTolerance_; } } } if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && bestPivot < 1.0e-3) { // back to previous one goBackOne = true; break; } else if (pivotRow_ == -1 && upperTheta > largeValue_) { if (lastPivot > acceptablePivot) { // back to previous one goBackOne = true; } else { // can only get here if all pivots so far too small } break; } else if (totalThru >= dualCheck) { if (sumInfeasibilities > primalTolerance_ && !abcNonLinearCost_->numberInfeasibilities()) { // Looks a bad choice if (lastPivot > acceptablePivot) { goBackOne = true; } else { // say no good dualIn_ = 0.0; } } break; // no point trying another loop } else { lastPivotRow = pivotRow_; lastTheta = theta_; if (bestPivot > bestEverPivot) bestEverPivot = bestPivot; } } // can get here without pivotRow_ set but with lastPivotRow if (goBackOne || (pivotRow_ < 0 && lastPivotRow >= 0)) { // back to previous one pivotRow_ = lastPivotRow; theta_ = lastTheta; } } else if (pivotRow_ < 0 && maximumMovement > 1.0e20) { // looks unbounded valueOut_ = COIN_DBL_MAX; // say odd if (abcNonLinearCost_->numberInfeasibilities()) { // but infeasible?? // move variable but don't pivot tentativeTheta = 1.0e50; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; alpha *= way; double oldValue = solutionBasic_[iRow]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) if (alpha > 0.0) { // basic variable going towards lower bound double bound = lowerBasic_[iRow]; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upperBasic_[iRow]; oldValue = bound - oldValue; alpha = - alpha; } if (oldValue - tentativeTheta * alpha < 0.0) { tentativeTheta = oldValue / alpha; } } // If free in then see if we can get to 0.0 if (lowerIn_ < -1.0e20 && upperIn_ > 1.0e20) { if (dualIn_ * valueIn_ > 0.0) { if (fabs(valueIn_) < 1.0e-2 && (tentativeTheta < fabs(valueIn_) || tentativeTheta > 1.0e20)) { tentativeTheta = fabs(valueIn_); } } } if (tentativeTheta < 1.0e10) valueOut_ = valueIn_ + way * tentativeTheta; } } //if (iTry>50) //printf("** %d tries\n",iTry); if (pivotRow_ >= 0) { alpha_ = work[pivotRow_]; // translate to sequence sequenceOut_ = abcPivotVariable_[pivotRow_]; valueOut_ = solution(sequenceOut_); lowerOut_ = abcLower_[sequenceOut_]; upperOut_ = abcUpper_[sequenceOut_]; //#define MINIMUMTHETA 1.0e-11 // Movement should be minimum for anti-degeneracy - unless // fixed variable out double minimumTheta; if (upperOut_ > lowerOut_) minimumTheta = minimumThetaMovement_; else minimumTheta = 0.0; // But can't go infeasible double distance; if (alpha_ * way > 0.0) distance = valueOut_ - lowerOut_; else distance = upperOut_ - valueOut_; if (distance - minimumTheta * fabs(alpha_) < -primalTolerance_) minimumTheta = CoinMax(0.0, (distance + 0.5 * primalTolerance_) / fabs(alpha_)); // will we need to increase tolerance //#define CLP_DEBUG double largestInfeasibility = primalTolerance_; if (theta_ < minimumTheta && (specialOptions_ & 4) == 0 && !valuesPass) { theta_ = minimumTheta; for (iIndex = 0; iIndex < numberRemaining - numberRemaining; iIndex++) { largestInfeasibility = CoinMax(largestInfeasibility, -(rhs[iIndex] - spare[iIndex] * theta_)); } //#define CLP_DEBUG #if ABC_NORMAL_DEBUG>3 if (largestInfeasibility > primalTolerance_ && (handler_->logLevel() & 32) > -1) printf("Primal tolerance increased from %g to %g\n", primalTolerance_, largestInfeasibility); #endif //#undef CLP_DEBUG primalTolerance_ = CoinMax(primalTolerance_, largestInfeasibility); } // Need to look at all in some cases if (theta_ > tentativeTheta) { for (iIndex = 0; iIndex < number; iIndex++) setActive(which[iIndex]); } if (way < 0.0) theta_ = - theta_; double newValue = valueOut_ - theta_ * alpha_; // If 4 bit set - Force outgoing variables to exact bound (primal) if (alpha_ * way < 0.0) { directionOut_ = -1; // to upper bound if (fabs(theta_) > 1.0e-6 || (specialOptions_ & 4) != 0) { upperOut_ = abcNonLinearCost_->nearest(pivotRow_, newValue); } else { upperOut_ = newValue; } } else { directionOut_ = 1; // to lower bound if (fabs(theta_) > 1.0e-6 || (specialOptions_ & 4) != 0) { lowerOut_ = abcNonLinearCost_->nearest(pivotRow_, newValue); } else { lowerOut_ = newValue; } } dualOut_ = reducedCost(sequenceOut_); } else if (maximumMovement < 1.0e20) { // flip pivotRow_ = -2; // so we can tell its a flip sequenceOut_ = sequenceIn_; valueOut_ = valueIn_; dualOut_ = dualIn_; lowerOut_ = lowerIn_; upperOut_ = upperIn_; alpha_ = 0.0; if (way < 0.0) { directionOut_ = 1; // to lower bound theta_ = lowerOut_ - valueOut_; } else { directionOut_ = -1; // to upper bound theta_ = upperOut_ - valueOut_; } } double theta1 = CoinMax(theta_, 1.0e-12); double theta2 = numberIterations_ * abcNonLinearCost_->averageTheta(); // Set average theta abcNonLinearCost_->setAverageTheta((theta1 + theta2) / (static_cast (numberIterations_ + 1))); //if (numberIterations_%1000==0) //printf("average theta is %g\n",abcNonLinearCost_->averageTheta()); // clear arrays CoinZeroN(spare, numberRemaining); CoinZeroN(rhs, numberRemaining); // put back original bounds etc CoinMemcpyN(index, numberRemaining, rhsArray->getIndices()); rhsArray->setNumElements(numberRemaining); //rhsArray->setPacked(); abcNonLinearCost_->goBackAll(rhsArray); rhsArray->clear(); } /* Row array has pivot column This chooses pivot row. For speed, we may need to go to a bucket approach when many variables go through bounds On exit rhsArray will have changes in costs of basic variables */ void AbcSimplexPrimal::primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, pivotStruct & stuff) { int valuesPass=stuff.valuesPass_; double dualIn=stuff.dualIn_; double lowerIn=stuff.lowerIn_; double upperIn=stuff.upperIn_; double valueIn=stuff.valueIn_; int sequenceIn=stuff.sequenceIn_; int directionIn=stuff.directionIn_; int pivotRow=-1; int sequenceOut=-1; double dualOut=0.0; double lowerOut=0.0; double upperOut=0.0; double valueOut=0.0; double theta; double alpha; int directionOut=0; if (valuesPass) { dualIn = abcCost_[sequenceIn]; double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; dualIn -= alpha * costBasic_[iRow]; } // determine direction here if (dualIn < -dualTolerance_) { directionIn = 1; } else if (dualIn > dualTolerance_) { directionIn = -1; } else { // towards nearest bound if (valueIn - lowerIn < upperIn - valueIn) { directionIn = -1; dualIn = dualTolerance_; } else { directionIn = 1; dualIn = -dualTolerance_; } } } // sequence stays as row number until end pivotRow = -1; int numberRemaining = 0; double totalThru = 0.0; // for when variables flip // Allow first few iterations to take tiny double acceptablePivot = 1.0e-1 * acceptablePivot_; if (numberIterations_ > 100) acceptablePivot = acceptablePivot_; if (abcFactorization_->pivots() > 10) acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (abcFactorization_->pivots() > 5) acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (abcFactorization_->pivots()) acceptablePivot = acceptablePivot_; // relax double bestEverPivot = acceptablePivot; int lastPivotRow = -1; double lastPivot = 0.0; double lastTheta = 1.0e50; // use spareArrays to put ones looked at in // First one is list of candidates // We could compress if we really know we won't need any more // Second array has current set of pivot candidates // with a backup list saved in double * part of indexed vector // pivot elements double * spare; // indices int * index; spareArray->clear(); spare = spareArray->denseVector(); index = spareArray->getIndices(); // we also need somewhere for effective rhs double * rhs = rhsArray->denseVector(); // and we can use indices to point to alpha // that way we can store fabs(alpha) int * indexPoint = rhsArray->getIndices(); //int numberFlip=0; // Those which may change if flips /* First we get a list of possible pivots. We can also see if the problem looks unbounded. At first we increase theta and see what happens. We start theta at a reasonable guess. If in right area then we do bit by bit. We save possible pivot candidates */ // do first pass to get possibles // We can also see if unbounded double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); // we need to swap sign if coming in from ub double way = directionIn; double maximumMovement; if (way > 0.0) maximumMovement = CoinMin(1.0e30, upperIn - valueIn); else maximumMovement = CoinMin(1.0e30, valueIn - lowerIn); double averageTheta = abcNonLinearCost_->averageTheta(); double tentativeTheta = CoinMin(10.0 * averageTheta, maximumMovement); double upperTheta = maximumMovement; if (tentativeTheta > 0.5 * maximumMovement) tentativeTheta = maximumMovement; bool thetaAtMaximum = tentativeTheta == maximumMovement; // In case tiny bounds increase if (maximumMovement < 1.0) tentativeTheta *= 1.1; double dualCheck = fabs(dualIn); // but make a bit more pessimistic dualCheck = CoinMax(dualCheck - 100.0 * dualTolerance_, 0.99 * dualCheck); int iIndex; while (true) { totalThru = 0.0; // We also re-compute reduced cost numberRemaining = 0; dualIn = abcCost_[sequenceIn]; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; dualIn -= alpha * costBasic_[iRow]; alpha *= way; double oldValue = solutionBasic_[iRow]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) bool possible; // do computation same way as later on in primal if (alpha > 0.0) { // basic variable going towards lower bound double bound = lowerBasic_[iRow]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) <= bound + primalTolerance_; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upperBasic_[iRow]; // must be exactly same as when used double change = tentativeTheta * alpha; possible = (oldValue - change) >= bound - primalTolerance_; oldValue = bound - oldValue; alpha = - alpha; } double value; if (possible) { value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 if(!userChoiceValid1(this,iPivot,oldValue, upperTheta,alpha,work[iRow]*way)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; } // add to list spare[numberRemaining] = alpha; rhs[numberRemaining] = oldValue; indexPoint[numberRemaining] = iIndex; index[numberRemaining++] = iRow; totalThru += alpha; setActive(iRow); } } if (upperTheta < maximumMovement && totalThru*infeasibilityCost_ >= 1.0001 * dualCheck) { // Can pivot here break; } else if (!thetaAtMaximum) { //printf("Going round with average theta of %g\n",averageTheta); tentativeTheta = maximumMovement; thetaAtMaximum = true; // seems to be odd compiler error } else { break; } } totalThru = 0.0; theta = maximumMovement; bool goBackOne = false; //printf("%d remain out of %d\n",numberRemaining,number); int iTry = 0; if (numberRemaining && upperTheta < maximumMovement) { // First check if previously chosen one will work // first get ratio with tolerance for ( ; iTry < MAXTRY; iTry++) { upperTheta = maximumMovement; int iBest = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; #ifdef CLP_USER_DRIVEN1 int sequenceOut=abcPivotVariable_[index[iIndex]]; if(!userChoiceValid1(this,sequenceOut,oldValue, upperTheta,alpha, 0.0)) value =0.0; // say can't use #endif if (value < -primalTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + primalTolerance_) / alpha; iBest = iIndex; // just in case weird numbers } } // now look at best in this lot // But also see how infeasible small pivots will make double sumInfeasibilities = 0.0; double bestPivot = acceptablePivot; pivotRow = -1; for (iIndex = 0; iIndex < numberRemaining; iIndex++) { int iRow = index[iIndex]; double alpha = spare[iIndex]; double oldValue = rhs[iIndex]; double value = oldValue - upperTheta * alpha; if (value <= 0 || iBest == iIndex) { // how much would it cost to go thru and modify bound double trueAlpha = way * work[iRow]; totalThru += abcNonLinearCost_->changeInCost(iRow, trueAlpha, rhs[iIndex]); setActive(iRow); if (alpha > bestPivot) { bestPivot = alpha; theta = oldValue / bestPivot; pivotRow = iRow; } else if (alpha < acceptablePivot #ifdef CLP_USER_DRIVEN1 ||!userChoiceValid1(this,abcPivotVariable_[index[iIndex]], oldValue,upperTheta,alpha,0.0) #endif ) { if (value < -primalTolerance_) sumInfeasibilities += -value - primalTolerance_; } } } if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && bestPivot < 1.0e-3) { // back to previous one goBackOne = true; break; } else if (pivotRow == -1 && upperTheta > largeValue_) { if (lastPivot > acceptablePivot) { // back to previous one goBackOne = true; } else { // can only get here if all pivots so far too small } break; } else if (totalThru >= dualCheck) { if (sumInfeasibilities > primalTolerance_ && !abcNonLinearCost_->numberInfeasibilities()) { // Looks a bad choice if (lastPivot > acceptablePivot) { goBackOne = true; } else { // say no good dualIn = 0.0; } } break; // no point trying another loop } else { lastPivotRow = pivotRow; lastTheta = theta; if (bestPivot > bestEverPivot) bestEverPivot = bestPivot; } } // can get here without pivotRow set but with lastPivotRow if (goBackOne || (pivotRow < 0 && lastPivotRow >= 0)) { // back to previous one pivotRow = lastPivotRow; theta = lastTheta; } } else if (pivotRow < 0 && maximumMovement > 1.0e20) { // looks unbounded valueOut = COIN_DBL_MAX; // say odd if (abcNonLinearCost_->numberInfeasibilities()) { // but infeasible?? // move variable but don't pivot tentativeTheta = 1.0e50; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; alpha *= way; double oldValue = solutionBasic_[iRow]; // get where in bound sequence // note that after this alpha is actually fabs(alpha) if (alpha > 0.0) { // basic variable going towards lower bound double bound = lowerBasic_[iRow]; oldValue -= bound; } else { // basic variable going towards upper bound double bound = upperBasic_[iRow]; oldValue = bound - oldValue; alpha = - alpha; } if (oldValue - tentativeTheta * alpha < 0.0) { tentativeTheta = oldValue / alpha; } } // If free in then see if we can get to 0.0 if (lowerIn < -1.0e20 && upperIn > 1.0e20) { if (dualIn * valueIn > 0.0) { if (fabs(valueIn) < 1.0e-2 && (tentativeTheta < fabs(valueIn) || tentativeTheta > 1.0e20)) { tentativeTheta = fabs(valueIn); } } } if (tentativeTheta < 1.0e10) valueOut = valueIn + way * tentativeTheta; } } if (pivotRow >= 0) { alpha = work[pivotRow]; // translate to sequence sequenceOut = abcPivotVariable_[pivotRow]; valueOut = solutionBasic_[pivotRow]; lowerOut = lowerBasic_[pivotRow]; upperOut = upperBasic_[pivotRow]; // Movement should be minimum for anti-degeneracy - unless // fixed variable out double minimumTheta; if (upperOut > lowerOut) minimumTheta = minimumThetaMovement_; else minimumTheta = 0.0; // But can't go infeasible double distance; if (alpha * way > 0.0) distance = valueOut - lowerOut; else distance = upperOut - valueOut; if (distance - minimumTheta * fabs(alpha) < -primalTolerance_) minimumTheta = CoinMax(0.0, (distance + 0.5 * primalTolerance_) / fabs(alpha)); // will we need to increase tolerance //double largestInfeasibility = primalTolerance_; if (theta < minimumTheta && (specialOptions_ & 4) == 0 && !valuesPass) { theta = minimumTheta; //for (iIndex = 0; iIndex < numberRemaining - numberRemaining; iIndex++) { //largestInfeasibility = CoinMax(largestInfeasibility, // -(rhs[iIndex] - spare[iIndex] * theta)); //} //primalTolerance_ = CoinMax(primalTolerance_, largestInfeasibility); } // Need to look at all in some cases if (theta > tentativeTheta) { for (iIndex = 0; iIndex < number; iIndex++) setActive(which[iIndex]); } if (way < 0.0) theta = - theta; double newValue = valueOut - theta * alpha; // If 4 bit set - Force outgoing variables to exact bound (primal) if (alpha * way < 0.0) { directionOut = -1; // to upper bound if (fabs(theta) > 1.0e-6 || (specialOptions_ & 4) != 0) { upperOut = abcNonLinearCost_->nearest(pivotRow, newValue); } else { upperOut = newValue; } } else { directionOut = 1; // to lower bound if (fabs(theta) > 1.0e-6 || (specialOptions_ & 4) != 0) { lowerOut = abcNonLinearCost_->nearest(pivotRow, newValue); } else { lowerOut = newValue; } } dualOut = reducedCost(sequenceOut); } else if (maximumMovement < 1.0e20) { // flip pivotRow = -2; // so we can tell its a flip sequenceOut = sequenceIn; valueOut = valueIn; dualOut = dualIn; lowerOut = lowerIn; upperOut = upperIn; alpha = 0.0; if (way < 0.0) { directionOut = 1; // to lower bound theta = lowerOut - valueOut; } else { directionOut = -1; // to upper bound theta = upperOut - valueOut; } } // clear arrays CoinZeroN(spare, numberRemaining); CoinZeroN(rhs, numberRemaining); // put back original bounds etc CoinMemcpyN(index, numberRemaining, rhsArray->getIndices()); rhsArray->setNumElements(numberRemaining); abcNonLinearCost_->goBackAll(rhsArray); rhsArray->clear(); stuff.theta_=theta; stuff.alpha_=alpha; stuff.dualIn_=dualIn; stuff.dualOut_=dualOut; stuff.lowerOut_=lowerOut; stuff.upperOut_=upperOut; stuff.valueOut_=valueOut; stuff.sequenceOut_=sequenceOut; stuff.directionOut_=directionOut; stuff.pivotRow_=pivotRow; } /* Chooses primal pivot column updateArray has cost updates (also use pivotRow_ from last iteration) Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first columns we look at */ void AbcSimplexPrimal::primalColumn(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1) { for (int i=0;i<4;i++) multipleSequenceIn_[i]=-1; sequenceIn_ = abcPrimalColumnPivot_->pivotColumn(updates, spareRow2, spareColumn1); if (sequenceIn_ >= 0) { valueIn_ = abcSolution_[sequenceIn_]; dualIn_ = abcDj_[sequenceIn_]; lowerIn_ = abcLower_[sequenceIn_]; upperIn_ = abcUpper_[sequenceIn_]; if (dualIn_ > 0.0) directionIn_ = -1; else directionIn_ = 1; } else { sequenceIn_ = -1; } } /* The primals are updated by the given array. Returns number of infeasibilities. After rowArray will have list of cost changes */ int AbcSimplexPrimal::updatePrimalsInPrimal(CoinIndexedVector * rowArray, double theta, double & objectiveChange, int valuesPass) { // Cost on pivot row may change - may need to change dualIn double oldCost = 0.0; if (pivotRow_ >= 0) oldCost = abcCost_[sequenceOut_]; double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); int newNumber = 0; abcNonLinearCost_->setChangeInCost(0.0); // allow for case where bound+tolerance == bound //double tolerance = 0.999999*primalTolerance_; double relaxedTolerance = 1.001 * primalTolerance_; int iIndex; if (!valuesPass) { for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; work[iRow] = 0.0; int iPivot = abcPivotVariable_[iRow]; double change = theta * alpha; double value = abcSolution_[iPivot] - change; abcSolution_[iPivot] = value; value = solutionBasic_[iRow] - change; solutionBasic_[iRow] = value; #ifndef NDEBUG // check if not active then okay if (!active(iRow) && (specialOptions_ & 4) == 0 && pivotRow_ != -1) { // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= abcLower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value > abcLower_[iPivot] - relaxedTolerance) value = abcLower_[iPivot]; //double difference = abcNonLinearCost_->setOneBasic(iRow, value); //assert (!difference || fabs(change) > 1.0e9); } } else { // going up if (value >= abcUpper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < abcUpper_[iPivot] + relaxedTolerance) value = abcUpper_[iPivot]; //double difference = abcNonLinearCost_->setOneBasic(iRow, value); //assert (!difference || fabs(change) > 1.0e9); } } } #endif if (active(iRow) || theta_ < 0.0) { clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= abcLower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value >= abcLower_[iPivot] - relaxedTolerance) value = abcLower_[iPivot]; double difference = abcNonLinearCost_->setOneBasic(iRow, value); if (difference) { work[iRow] = difference; //change reduced cost on this //abcDj_[iPivot] = -difference; which[newNumber++] = iRow; } } } else { // going up if (value >= abcUpper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < abcUpper_[iPivot] + relaxedTolerance) value = abcUpper_[iPivot]; double difference = abcNonLinearCost_->setOneBasic(iRow, value); if (difference) { work[iRow] = difference; //change reduced cost on this //abcDj_[iPivot] = -difference; which[newNumber++] = iRow; } } } } } } else { // values pass so look at all for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; work[iRow] = 0.0; int iPivot = abcPivotVariable_[iRow]; double change = theta * alpha; double value = abcSolution_[iPivot] - change; abcSolution_[iPivot] = value; value = solutionBasic_[iRow] - change; solutionBasic_[iRow] = value; clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= abcLower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value > abcLower_[iPivot] - relaxedTolerance) value = abcLower_[iPivot]; double difference = abcNonLinearCost_->setOneBasic(iRow, value); if (difference) { work[iRow] = difference; //change reduced cost on this abcDj_[iPivot] = -difference; which[newNumber++] = iRow; } } } else { // going up if (value >= abcUpper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < abcUpper_[iPivot] + relaxedTolerance) value = abcUpper_[iPivot]; double difference = abcNonLinearCost_->setOneBasic(iRow, value); if (difference) { work[iRow] = difference; //change reduced cost on this abcDj_[iPivot] = -difference; which[newNumber++] = iRow; } } } } } objectiveChange += abcNonLinearCost_->changeInCost(); //rowArray->setPacked(); if (pivotRow_ >= 0) { double dualIn = dualIn_ + (oldCost - abcCost_[sequenceOut_]); // update change vector to include pivot if (!work[pivotRow_]) which[newNumber++] = pivotRow_; work[pivotRow_] -= dualIn; // above seems marginally better for updates - below should also work //work[pivotRow_] = -dualIn_; } rowArray->setNumElements(newNumber); return 0; } // Perturbs problem void AbcSimplexPrimal::perturb(int /*type*/) { if (perturbation_ > 100) return; //perturbed already if (perturbation_ == 100) perturbation_ = 50; // treat as normal int savePerturbation = perturbation_; int i; copyFromSaved(14); // copy bounds and costs // look at element range double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive); largestPositive = CoinMax(fabs(largestNegative), largestPositive); double elementRatio = largestPositive / smallestPositive; if ((!numberIterations_ ||initialSumInfeasibilities_==1.23456789e-5)&& perturbation_ == 50) { // See if we need to perturb int numberTotal = CoinMax(numberRows_, numberColumns_); double * sort = new double[numberTotal]; int nFixed = 0; for (i = 0; i < numberRows_; i++) { double lo = fabs(rowLower_[i]); double up = fabs(rowUpper_[i]); double value = 0.0; if (lo && lo < 1.0e20) { if (up && up < 1.0e20) { value = 0.5 * (lo + up); if (lo == up) nFixed++; } else { value = lo; } } else { if (up && up < 1.0e20) value = up; } sort[i] = value; } std::sort(sort, sort + numberRows_); int number = 1; double last = sort[0]; for (i = 1; i < numberRows_; i++) { if (last != sort[i]) number++; last = sort[i]; } #ifdef KEEP_GOING_IF_FIXED //printf("ratio number diff rhs %g (%d %d fixed), element ratio %g\n",((double)number)/((double) numberRows_), // numberRows_,nFixed,elementRatio); #endif if (number * 4 > numberRows_ || elementRatio > 1.0e12) { perturbation_ = 100; delete [] sort; // Make sure feasible bounds if (abcNonLinearCost_) { abcNonLinearCost_->refresh(); abcNonLinearCost_->checkInfeasibilities(); //abcNonLinearCost_->feasibleBounds(); } moveToBasic(); return; // good enough } number = 0; #ifdef KEEP_GOING_IF_FIXED if (!integerType_) { // look at columns nFixed = 0; for (i = 0; i < numberColumns_; i++) { double lo = fabs(columnLower_[i]); double up = fabs(columnUpper_[i]); double value = 0.0; if (lo && lo < 1.0e20) { if (up && up < 1.0e20) { value = 0.5 * (lo + up); if (lo == up) nFixed++; } else { value = lo; } } else { if (up && up < 1.0e20) value = up; } sort[i] = value; } std::sort(sort, sort + numberColumns_); number = 1; last = sort[0]; for (i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } //printf("cratio number diff bounds %g (%d %d fixed)\n",((double)number)/((double) numberColumns_), // numberColumns_,nFixed); } #endif delete [] sort; if (number * 4 > numberColumns_) { perturbation_ = 100; // Make sure feasible bounds if (abcNonLinearCost_) { abcNonLinearCost_->refresh(); abcNonLinearCost_->checkInfeasibilities(); //abcNonLinearCost_->feasibleBounds(); } moveToBasic(); return; // good enough } } // primal perturbation double perturbation = 1.0e-20; double bias = 1.0; int numberNonZero = 0; // maximum fraction of rhs/bounds to perturb double maximumFraction = 1.0e-5; double overallMultiplier= (perturbation_==50||perturbation_>54) ? 2.0 : 0.2; #ifdef HEAVY_PERTURBATION if (perturbation_==50) perturbation_=HEAVY_PERTURBATION; #endif if (perturbation_ >= 50) { perturbation = 1.0e-4; for (i = 0; i < numberColumns_ + numberRows_; i++) { if (abcUpper_[i] > abcLower_[i] + primalTolerance_) { double lowerValue, upperValue; if (abcLower_[i] > -1.0e20) lowerValue = fabs(abcLower_[i]); else lowerValue = 0.0; if (abcUpper_[i] < 1.0e20) upperValue = fabs(abcUpper_[i]); else upperValue = 0.0; double value = CoinMax(fabs(lowerValue), fabs(upperValue)); value = CoinMin(value, abcUpper_[i] - abcLower_[i]); #if 1 if (value) { perturbation += value; numberNonZero++; } #else perturbation = CoinMax(perturbation, value); #endif } } if (numberNonZero) perturbation /= static_cast (numberNonZero); else perturbation = 1.0e-1; if (perturbation_ > 50 && perturbation_ < 55) { // reduce while (perturbation_ < 55) { perturbation_++; perturbation *= 0.25; bias *= 0.25; } perturbation_ = 50; } else if (perturbation_ >= 55 && perturbation_ < 60) { // increase while (perturbation_ > 55) { overallMultiplier *= 1.2; perturbation_--; perturbation *= 4.0; } perturbation_ = 50; } } else if (perturbation_ < 100) { perturbation = pow(10.0, perturbation_); // user is in charge maximumFraction = 1.0; } double largestZero = 0.0; double largest = 0.0; double largestPerCent = 0.0; bool printOut = (handler_->logLevel() == 63); printOut = false; //off // Check if all slack int number = 0; int iSequence; for (iSequence = 0; iSequence < numberRows_; iSequence++) { if (getInternalStatus(iSequence) == basic) number++; } if (rhsScale_ > 100.0) { // tone down perturbation maximumFraction *= 0.1; } if (savePerturbation==51) { perturbation = CoinMin(0.1,perturbation); maximumFraction *=0.1; } //if (number != numberRows_) //type = 1; // modify bounds // Change so at least 1.0e-5 and no more than 0.1 // For now just no more than 0.1 // printf("Pert type %d perturbation %g, maxF %g\n",type,perturbation,maximumFraction); // seems much slower??? //const double * COIN_RESTRICT perturbationArray = perturbationSaved_; // Make sure feasible bounds if (abcNonLinearCost_&&true) { abcNonLinearCost_->refresh(); abcNonLinearCost_->checkInfeasibilities(primalTolerance_); //abcNonLinearCost_->feasibleBounds(); } double tolerance = 100.0 * primalTolerance_; int numberChanged=0; //double multiplier = perturbation*maximumFraction; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { if (getInternalStatus(iSequence) == basic) { double lowerValue = abcLower_[iSequence]; double upperValue = abcUpper_[iSequence]; if (upperValue > lowerValue + tolerance) { double solutionValue = abcSolution_[iSequence]; double difference = upperValue - lowerValue; difference = CoinMin(difference, perturbation); difference = CoinMin(difference, fabs(solutionValue) + 1.0); double value = maximumFraction * (difference + bias); value = CoinMin(value, 0.1); value = CoinMax(value,primalTolerance_); double perturbationValue=overallMultiplier*randomNumberGenerator_.randomDouble(); value *= perturbationValue; if (solutionValue - lowerValue <= primalTolerance_) { abcLower_[iSequence] -= value; // change correct saved value if (abcNonLinearCost_->getCurrentStatus(iSequence)==CLP_FEASIBLE) abcPerturbation_[iSequence]=abcLower_[iSequence]; else abcPerturbation_[iSequence+numberTotal_]=abcLower_[iSequence]; } else if (upperValue - solutionValue <= primalTolerance_) { abcUpper_[iSequence] += value; // change correct saved value if (abcNonLinearCost_->getCurrentStatus(iSequence)==CLP_FEASIBLE) abcPerturbation_[iSequence+numberTotal_]=abcUpper_[iSequence]; else abcPerturbation_[iSequence]=abcUpper_[iSequence]; } else { #if 0 if (iSequence >= numberColumns_) { // may not be at bound - but still perturb (unless free) if (upperValue > 1.0e30 && lowerValue < -1.0e30) value = 0.0; else value = - value; // as -1.0 in matrix } else { value = 0.0; } #else value = 0.0; #endif } if (value) { numberChanged++; if (printOut) printf("col %d lower from %g to %g, upper from %g to %g\n", iSequence, abcLower_[iSequence], lowerValue, abcUpper_[iSequence], upperValue); if (solutionValue) { largest = CoinMax(largest, value); if (value > (fabs(solutionValue) + 1.0)*largestPerCent) largestPerCent = value / (fabs(solutionValue) + 1.0); } else { largestZero = CoinMax(largestZero, value); } } } } } if (!numberChanged) { // do non basic columns? for (iSequence = 0; iSequence < maximumAbcNumberRows_ + numberColumns_; iSequence++) { if (getInternalStatus(iSequence) != basic) { double lowerValue = abcLower_[iSequence]; double upperValue = abcUpper_[iSequence]; if (upperValue > lowerValue + tolerance) { double solutionValue = abcSolution_[iSequence]; double difference = upperValue - lowerValue; difference = CoinMin(difference, perturbation); difference = CoinMin(difference, fabs(solutionValue) + 1.0); double value = maximumFraction * (difference + bias); value = CoinMin(value, 0.1); value = CoinMax(value,primalTolerance_); double perturbationValue=overallMultiplier*randomNumberGenerator_.randomDouble(); value *= perturbationValue; if (solutionValue - lowerValue <= primalTolerance_) { abcLower_[iSequence] -= value; // change correct saved value if (abcNonLinearCost_->getCurrentStatus(iSequence)==CLP_FEASIBLE) abcPerturbation_[iSequence]=abcLower_[iSequence]; else abcPerturbation_[iSequence+numberTotal_]=abcLower_[iSequence]; } else if (upperValue - solutionValue <= primalTolerance_) { abcUpper_[iSequence] += value; // change correct saved value if (abcNonLinearCost_->getCurrentStatus(iSequence)==CLP_FEASIBLE) abcPerturbation_[iSequence+numberTotal_]=abcUpper_[iSequence]; else abcPerturbation_[iSequence]=abcUpper_[iSequence]; } else { value = 0.0; } if (value) { if (printOut) printf("col %d lower from %g to %g, upper from %g to %g\n", iSequence, abcLower_[iSequence], lowerValue, abcUpper_[iSequence], upperValue); if (solutionValue) { largest = CoinMax(largest, value); if (value > (fabs(solutionValue) + 1.0)*largestPerCent) largestPerCent = value / (fabs(solutionValue) + 1.0); } else { largestZero = CoinMax(largestZero, value); } } } } } } // Clean up for (i = 0; i < numberColumns_ + numberRows_; i++) { switch(getInternalStatus(i)) { case basic: break; case atUpperBound: abcSolution_[i] = abcUpper_[i]; break; case isFixed: case atLowerBound: abcSolution_[i] = abcLower_[i]; break; case isFree: break; case superBasic: break; } } handler_->message(CLP_SIMPLEX_PERTURB, messages_) << 100.0 * maximumFraction << perturbation << largest << 100.0 * largestPerCent << largestZero << CoinMessageEol; // redo nonlinear costs //delete abcNonLinearCost_;abcNonLinearCost_=new AbcNonLinearCost(this);//abort();// something elseabcNonLinearCost_->refresh(); moveToBasic(); if (!numberChanged) { // we changed nonbasic gutsOfPrimalSolution(3); // Make sure feasible bounds if (abcNonLinearCost_) { //abcNonLinearCost_->refresh(); abcNonLinearCost_->checkInfeasibilities(primalTolerance_); //abcNonLinearCost_->feasibleBounds(); } abcPrimalColumnPivot_->saveWeights(this, 3); } // say perturbed perturbation_ = 101; } // un perturb bool AbcSimplexPrimal::unPerturb() { if (perturbation_ != 101) return false; // put back original bounds and costs copyFromSaved(); // copy bounds to perturbation CoinAbcMemcpy(abcPerturbation_,abcLower_,numberTotal_); CoinAbcMemcpy(abcPerturbation_+numberTotal_,abcUpper_,numberTotal_); //sanityCheck(); // unflag unflag(); abcProgress_.clearTimesFlagged(); // get a valid nonlinear cost function delete abcNonLinearCost_; abcNonLinearCost_ = new AbcNonLinearCost(this); perturbation_ = 102; // stop any further perturbation // move non basic variables to new bounds abcNonLinearCost_->checkInfeasibilities(0.0); gutsOfSolution(3); abcNonLinearCost_->checkInfeasibilities(primalTolerance_); // Try using dual return abcNonLinearCost_->sumInfeasibilities()!=0.0; } // Unflag all variables and return number unflagged int AbcSimplexPrimal::unflag() { int i; int number = numberRows_ + numberColumns_; int numberFlagged = 0; // we can't really trust infeasibilities if there is dual error // allow tolerance bigger than standard to check on duals double relaxedToleranceD = dualTolerance_ + CoinMin(1.0e-2, 10.0 * largestDualError_); for (i = 0; i < number; i++) { if (flagged(i)) { clearFlagged(i); // only say if reasonable dj if (fabs(abcDj_[i]) > relaxedToleranceD) numberFlagged++; } } #if ABC_NORMAL_DEBUG>0 if (handler_->logLevel() > 2 && numberFlagged && objective_->type() > 1) printf("%d unflagged\n", numberFlagged); #endif return numberFlagged; } // Do not change infeasibility cost and always say optimal void AbcSimplexPrimal::alwaysOptimal(bool onOff) { if (onOff) specialOptions_ |= 1; else specialOptions_ &= ~1; } bool AbcSimplexPrimal::alwaysOptimal() const { return (specialOptions_ & 1) != 0; } // Flatten outgoing variables i.e. - always to exact bound void AbcSimplexPrimal::exactOutgoing(bool onOff) { if (onOff) specialOptions_ |= 4; else specialOptions_ &= ~4; } bool AbcSimplexPrimal::exactOutgoing() const { return (specialOptions_ & 4) != 0; } /* Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done) */ int AbcSimplexPrimal::pivotResult(int ifValuesPass) { bool roundAgain = true; int returnCode = -1; // loop round if user setting and doing refactorization while (roundAgain) { roundAgain = false; returnCode = -1; pivotRow_ = -1; sequenceOut_ = -1; usefulArray_[arrayForFtran_].clear(); // we found a pivot column // update the incoming column unpack(usefulArray_[arrayForFtran_]); // save reduced cost double saveDj = dualIn_; abcFactorization_->updateColumnFT(usefulArray_[arrayForFtran_]); // do ratio test and re-compute dj #ifdef CLP_USER_DRIVEN if ((moreSpecialOptions_ & 512) == 0) { #endif primalRow(&usefulArray_[arrayForFtran_], &usefulArray_[arrayForFlipBounds_], &usefulArray_[arrayForTableauRow_], ifValuesPass); #ifdef CLP_USER_DRIVEN // user can tell which use it is int status = eventHandler_->event(ClpEventHandler::pivotRow); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::pivotRow; break; } } else { int status = eventHandler_->event(ClpEventHandler::pivotRow); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::pivotRow; break; } } #endif if (ifValuesPass) { saveDj = dualIn_; //assert (fabs(alpha_)>=1.0e-5||(objective_->type()<2||!objective_->activated())||pivotRow_==-2); if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { if(fabs(dualIn_) < 1.0e2 * dualTolerance_ && objective_->type() < 2) { // try other way directionIn_ = -directionIn_; primalRow(&usefulArray_[arrayForFtran_], &usefulArray_[arrayForFlipBounds_], &usefulArray_[arrayForTableauRow_], 0); } if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { // reject it char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; returnCode = -5; break; } } } double checkValue = 1.0e-2; if (largestDualError_ > 1.0e-5) checkValue = 1.0e-1; double test2 = dualTolerance_; double test1 = 1.0e-20; #if 0 //def FEB_TRY if (abcFactorization_->pivots() < 1) { test1 = -1.0e-4; if ((saveDj < 0.0 && dualIn_ < -1.0e-5 * dualTolerance_) || (saveDj > 0.0 && dualIn_ > 1.0e-5 * dualTolerance_)) test2 = 0.0; // allow through } #endif if (!ifValuesPass && (saveDj * dualIn_ < test1 || fabs(saveDj - dualIn_) > checkValue*(1.0 + fabs(saveDj)) || fabs(dualIn_) < test2)) { if (!(saveDj * dualIn_ > 0.0 && CoinMin(fabs(saveDj), fabs(dualIn_)) > 1.0e5)) { char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_PRIMAL_DJ, messages_) << x << sequenceWithin(sequenceIn_) << saveDj << dualIn_ << CoinMessageEol; if(lastGoodIteration_ != numberIterations_) { clearAll(); pivotRow_ = -1; // say no weights update returnCode = -4; if(lastGoodIteration_ + 1 == numberIterations_) { // not looking wonderful - try cleaning bounds // put non-basics to bounds in case tolerance moved abcNonLinearCost_->checkInfeasibilities(0.0); } sequenceOut_ = -1; sequenceIn_=-1; if (abcFactorization_->pivots()<10&&abcFactorization_->pivotTolerance()<0.25) abcFactorization_->saferTolerances(1.0,-1.03); break; } else { // take on more relaxed criterion if (saveDj * dualIn_ < test1 || fabs(saveDj - dualIn_) > 2.0e-1 * (1.0 + fabs(dualIn_)) || fabs(dualIn_) < test2) { // need to reject something char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); #if 1 //def FEB_TRY // Make safer? double tolerance=abcFactorization_->pivotTolerance(); abcFactorization_->saferTolerances (1.0, -1.03); #endif abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; returnCode = -5; if(tolerancepivotTolerance()) returnCode=-4; sequenceOut_ = -1; sequenceIn_=-1; break; } } } else { //printf("%d %g %g\n",numberIterations_,saveDj,dualIn_); } } if (pivotRow_ >= 0) { #ifdef CLP_USER_DRIVEN1 // Got good pivot - may need to unflag stuff userChoiceWasGood(this); #endif // if stable replace in basis // check update //abcFactorization_->checkReplacePart1a(&usefulArray_[arrayForReplaceColumn_],pivotRow_); //usefulArray_[arrayForReplaceColumn_].print(); ftAlpha_=abcFactorization_->checkReplacePart1(&usefulArray_[arrayForReplaceColumn_],pivotRow_); int updateStatus=abcFactorization_->checkReplacePart2(pivotRow_,btranAlpha_,alpha_,ftAlpha_); abcFactorization_->replaceColumnPart3(this, &usefulArray_[arrayForReplaceColumn_], &usefulArray_[arrayForFtran_], pivotRow_, ftAlpha_?ftAlpha_:alpha_); // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (abcFactorization_->pivots() > 5 || updateStatus == 4) { returnCode = -3; } } else if (updateStatus == 2) { // major error // better to have small tolerance even if slower abcFactorization_->zeroTolerance(CoinMin(abcFactorization_->zeroTolerance(), 1.0e-15)); int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); } // later we may need to unwind more e.g. fake bounds if(lastGoodIteration_ != numberIterations_) { clearAll(); pivotRow_ = -1; sequenceIn_ = -1; sequenceOut_ = -1; returnCode = -4; break; } else { // need to reject something char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; sequenceIn_ = -1; sequenceOut_ = -1; returnCode = -5; break; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (abcFactorization_->pivots() < 0.5 * abcFactorization_->maximumPivots() && abcFactorization_->pivots() < 200) abcFactorization_->areaFactor( abcFactorization_->areaFactor() * 1.1); returnCode = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } // here do part of steepest - ready for next iteration if (!ifValuesPass) abcPrimalColumnPivot_->updateWeights(&usefulArray_[arrayForFtran_]); } else { if (pivotRow_ == -1) { // no outgoing row is valid if (valueOut_ != COIN_DBL_MAX) { double objectiveChange = 0.0; theta_ = valueOut_ - valueIn_; updatePrimalsInPrimal(&usefulArray_[arrayForFtran_], theta_, objectiveChange, ifValuesPass); abcSolution_[sequenceIn_] += theta_; } #ifdef CLP_USER_DRIVEN1 /* Note if valueOut_ < COIN_DBL_MAX and theta_ reasonable then this may be a valid sub flip */ if(!userChoiceValid2(this)) { if (abcFactorization_->pivots()<5) { // flag variable char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); abcProgress_.clearBadTimes(); roundAgain = true; continue; } else { // try refactorizing first returnCode = 4; //say looks odd but has iterated break; } } #endif if (!abcFactorization_->pivots() && acceptablePivot_ <= 1.0e-8) { returnCode = 2; //say looks unbounded // do ray primalRay(&usefulArray_[arrayForFtran_]); } else { acceptablePivot_ = 1.0e-8; returnCode = 4; //say looks unbounded but has iterated } break; } else { // flipping from bound to bound } } double oldCost = 0.0; if (sequenceOut_ >= 0) oldCost = abcCost_[sequenceOut_]; // update primal solution double objectiveChange = 0.0; // after this usefulArray_[arrayForFtran_] is not empty - used to update djs #ifdef CLP_USER_DRIVEN if (theta_<0.0) { if (theta_>=-1.0e-12) theta_=0.0; //else //printf("negative theta %g\n",theta_); } #endif updatePrimalsInPrimal(&usefulArray_[arrayForFtran_], theta_, objectiveChange, ifValuesPass); double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ -= fabs(theta_); } else { valueIn_ = lowerIn_; } } else { // as if from lower bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ += fabs(theta_); } else { valueIn_ = upperIn_; } } objectiveChange += dualIn_ * (valueIn_ - oldValue); // outgoing if (sequenceIn_ != sequenceOut_) { if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } if(valueOut_ < abcLower_[sequenceOut_] - primalTolerance_) valueOut_ = abcLower_[sequenceOut_] - 0.9 * primalTolerance_; else if (valueOut_ > abcUpper_[sequenceOut_] + primalTolerance_) valueOut_ = abcUpper_[sequenceOut_] + 0.9 * primalTolerance_; // may not be exactly at bound and bounds may have changed // Make sure outgoing looks feasible directionOut_ = abcNonLinearCost_->setOneOutgoing(pivotRow_, valueOut_); // May have got inaccurate //if (oldCost!=abcCost_[sequenceOut_]) //printf("costchange on %d from %g to %g\n",sequenceOut_, // oldCost,abcCost_[sequenceOut_]); abcDj_[sequenceOut_] = abcCost_[sequenceOut_] - oldCost; // normally updated next iteration abcSolution_[sequenceOut_] = valueOut_; } // change cost and bounds on incoming if primal abcNonLinearCost_->setOne(sequenceIn_, valueIn_); int whatNext = housekeeping(/*objectiveChange*/); swapPrimalStuff(); if (whatNext == 1) { returnCode = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent returnCode = 3; } else if(numberIterations_ == lastGoodIteration_ + 2 * abcFactorization_->maximumPivots()) { // done a lot of flips - be safe returnCode = -2; // refactorize } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 3; } } } return returnCode; } /* Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done) */ int AbcSimplexPrimal::pivotResult4(int ifValuesPass) { int returnCode = -1; int numberMinor=0; int numberDone=0; CoinIndexedVector * vector[16]; pivotStruct stuff[4]; vector[0]=&usefulArray_[arrayForFtran_]; vector[1]=&usefulArray_[arrayForFlipBounds_]; vector[2]=&usefulArray_[arrayForTableauRow_]; vector[3]=&usefulArray_[arrayForBtran_]; /* For pricing we need to get a vector with difference in costs later we could modify code so only costBasic changed and store in first [4*x+1] array to go out the indices of changed plus at most four for pivots */ //double * saveCosts=CoinCopyOfArray(costBasic_,numberRows_); //double saveCostsIn[4]; for (int iMinor=0;iMinor<4;iMinor++) { int sequenceIn=multipleSequenceIn_[iMinor]; if (sequenceIn<0) break; stuff[iMinor].valuesPass_=ifValuesPass; stuff[iMinor].lowerIn_=abcLower_[sequenceIn]; stuff[iMinor].upperIn_=abcUpper_[sequenceIn]; stuff[iMinor].valueIn_=abcSolution_[sequenceIn]; stuff[iMinor].sequenceIn_=sequenceIn; //saveCostsIn[iMinor]=abcCost_[sequenceIn]; numberMinor++; if (iMinor) { vector[4*iMinor]=rowArray_[2*iMinor-2]; vector[4*iMinor+1]=rowArray_[2*iMinor-1]; vector[4*iMinor+2]=columnArray_[2*iMinor-2]; vector[4*iMinor+3]=columnArray_[2*iMinor-1]; } for (int i=0;i<4;i++) vector[4*iMinor+i]->checkClear(); unpack(*vector[4*iMinor],sequenceIn); } int numberLeft=numberMinor; // parallel (with cpu) for (int iMinor=1;iMinorupdateColumnFT(*vector[4*iMinor],*vector[4*iMinor+3],iMinor); } abcFactorization_->updateColumnFT(*vector[0],*vector[+3],0); cilk_sync; for (int iMinor=0;iMinorclear(); vector[4*jMinor+i]=vector[4*numberDo+i]; vector[4*numberDo+i]=NULL; } stuff[jMinor]=stuff[numberDo]; } } for (int jMinor=0;jMinorbestMovement) { bestMovement=movement; iBest=jMinor; } } #if 0 //ndef MULTIPLE_PRICE if (maximumIterations()!=100000) iBest=0; #endif if (iBest>=0) { dualIn_=stuff[iBest].dualIn_; dualOut_=stuff[iBest].dualOut_; lowerOut_=stuff[iBest].lowerOut_; upperOut_=stuff[iBest].upperOut_; valueOut_=stuff[iBest].valueOut_; sequenceOut_=stuff[iBest].sequenceOut_; sequenceIn_=stuff[iBest].sequenceIn_; lowerIn_=stuff[iBest].lowerIn_; upperIn_=stuff[iBest].upperIn_; valueIn_=stuff[iBest].valueIn_; directionIn_=stuff[iBest].directionIn_; directionOut_=stuff[iBest].directionOut_; pivotRow_=stuff[iBest].pivotRow_; theta_=stuff[iBest].theta_; alpha_=stuff[iBest].alpha_; #ifdef MULTIPLE_PRICE for (int i=0;i<4*numberLeft;i++) vector[i]->clear(); return 0; #endif // maybe do this on more? double theta1 = CoinMax(theta_, 1.0e-12); double theta2 = numberIterations_ * abcNonLinearCost_->averageTheta(); // Set average theta abcNonLinearCost_->setAverageTheta((theta1 + theta2) / (static_cast (numberIterations_ + 1))); if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { if(fabs(dualIn_) < 1.0e2 * dualTolerance_) { // try other way stuff[iBest].directionIn_ = -directionIn_; stuff[iBest].valuesPass_=0; primalRow(vector[4*iBest],vector[4*iBest+1],vector[4*iBest+2],stuff[iBest]); dualIn_=stuff[iBest].dualIn_; dualOut_=stuff[iBest].dualOut_; lowerOut_=stuff[iBest].lowerOut_; upperOut_=stuff[iBest].upperOut_; valueOut_=stuff[iBest].valueOut_; sequenceOut_=stuff[iBest].sequenceOut_; sequenceIn_=stuff[iBest].sequenceIn_; lowerIn_=stuff[iBest].lowerIn_; upperIn_=stuff[iBest].upperIn_; valueIn_=stuff[iBest].valueIn_; directionIn_=stuff[iBest].directionIn_; directionOut_=stuff[iBest].directionOut_; pivotRow_=stuff[iBest].pivotRow_; theta_=stuff[iBest].theta_; alpha_=stuff[iBest].alpha_; } if (pivotRow_ == -1 || (pivotRow_ >= 0 && fabs(alpha_) < 1.0e-5)) { // reject it char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious clearAll(); pivotRow_ = -1; returnCode = -5; break; } } CoinIndexedVector * bestUpdate=NULL; if (pivotRow_ >= 0) { // Normal pivot // if stable replace in basis // check update CoinIndexedVector * tempVector[4]; memcpy(tempVector,vector+4*iBest,4*sizeof(CoinIndexedVector *)); returnCode = cilk_spawn doFTUpdate(tempVector); bestUpdate=tempVector[0]; // after this bestUpdate is not empty - used to update djs ?? cilk_spawn updatePrimalsInPrimal(*bestUpdate, theta_, ifValuesPass); numberDone++; numberLeft--; // throw away for (int i=0;i<4;i++) { vector[4*iBest+i]=vector[4*numberLeft+i]; vector[4*numberLeft+i]=NULL; } stuff[iBest]=stuff[numberLeft]; // update pi and other vectors and FT stuff // parallel (can go 8 way?) for (int jMinor=0;jMinorclear(); if (returnCode<-3) { clearAll(); break; } // end Normal pivot } else { // start Flip vector[4*iBest+3]->clear(); if (pivotRow_ == -1) { // no outgoing row is valid if (valueOut_ != COIN_DBL_MAX) { theta_ = valueOut_ - valueIn_; updatePrimalsInPrimal(*vector[4*iBest], theta_, ifValuesPass); abcSolution_[sequenceIn_] += theta_; } if (!abcFactorization_->pivots() && acceptablePivot_ <= 1.0e-8) { returnCode = 2; //say looks unbounded // do ray primalRay(vector[4*iBest]); } else { acceptablePivot_ = 1.0e-8; returnCode = 4; //say looks unbounded but has iterated } break; } else { // flipping from bound to bound bestUpdate=vector[4*iBest]; // after this bestUpdate is not empty - used to update djs ?? updatePrimalsInPrimal(*bestUpdate, theta_, ifValuesPass); // throw away best BUT remember we are updating costs somehow numberDone++; numberLeft--; // throw away for (int i=0;i<4;i++) { if (i) vector[4*iBest+i]->clear(); vector[4*iBest+i]=vector[4*numberLeft+i]; vector[4*numberLeft+i]=NULL; } stuff[iBest]=stuff[numberLeft]; // parallel for (int jMinor=0;jMinorclear(); // as only works in values pass if (directionIn_ == -1) { // as if from upper bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ -= fabs(theta_); } else { valueIn_ = lowerIn_; } } else { // as if from lower bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ += fabs(theta_); } else { valueIn_ = upperIn_; } } // outgoing if (sequenceIn_ != sequenceOut_) { if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } if(valueOut_ < abcLower_[sequenceOut_] - primalTolerance_) valueOut_ = abcLower_[sequenceOut_] - 0.9 * primalTolerance_; else if (valueOut_ > abcUpper_[sequenceOut_] + primalTolerance_) valueOut_ = abcUpper_[sequenceOut_] + 0.9 * primalTolerance_; // may not be exactly at bound and bounds may have changed // Make sure outgoing looks feasible directionOut_ = abcNonLinearCost_->setOneOutgoing(pivotRow_, valueOut_); abcSolution_[sequenceOut_] = valueOut_; } // change cost and bounds on incoming if primal abcNonLinearCost_->setOne(sequenceIn_, valueIn_); int whatNext = housekeeping(/*objectiveChange*/); swapPrimalStuff(); if (whatNext == 1) { returnCode = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent returnCode = 3; } else if(numberIterations_ == lastGoodIteration_ + 2 * abcFactorization_->maximumPivots()) { // done a lot of flips - be safe returnCode = -2; // refactorize } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 3; } } } if (returnCode!=-1) break; } for (int i=0;i<16;i++) { if (vector[i]) vector[i]->clear(); if (vector[i]) vector[i]->checkClear(); } //delete [] saveCosts; return returnCode; } // Do FT update as separate function for minor iterations (nonzero return code on problems) int AbcSimplexPrimal::doFTUpdate(CoinIndexedVector * vector[4]) { ftAlpha_=abcFactorization_->checkReplacePart1(&usefulArray_[arrayForReplaceColumn_], vector[3],pivotRow_); int updateStatus=abcFactorization_->checkReplacePart2(pivotRow_,btranAlpha_,alpha_,ftAlpha_); if (!updateStatus) abcFactorization_->replaceColumnPart3(this, &usefulArray_[arrayForReplaceColumn_], vector[0], vector[3], pivotRow_, ftAlpha_?ftAlpha_:alpha_); else vector[3]->clear(); int returnCode=0; // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (abcFactorization_->pivots() > 5 || updateStatus == 4) { returnCode = -3; } } else if (updateStatus == 2) { // major error // better to have small tolerance even if slower abcFactorization_->zeroTolerance(CoinMin(abcFactorization_->zeroTolerance(), 1.0e-15)); int maxFactor = abcFactorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); } // later we may need to unwind more e.g. fake bounds if(lastGoodIteration_ != numberIterations_) { pivotRow_ = -1; sequenceIn_ = -1; sequenceOut_ = -1; returnCode = -4; } else { // need to reject something char x = isColumn(sequenceIn_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceIn_) << CoinMessageEol; setFlagged(sequenceIn_); abcProgress_.incrementTimesFlagged(); abcProgress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious pivotRow_ = -1; sequenceIn_ = -1; sequenceOut_ = -1; returnCode = -5; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (abcFactorization_->pivots() < 0.5 * abcFactorization_->maximumPivots() && abcFactorization_->pivots() < 200) abcFactorization_->areaFactor( abcFactorization_->areaFactor() * 1.1); returnCode = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now returnCode=-2; } return returnCode; } /* The primals are updated by the given array. costs are changed */ void AbcSimplexPrimal::updatePrimalsInPrimal(CoinIndexedVector & rowArray, double theta,bool valuesPass) { // Cost on pivot row may change - may need to change dualIn //double oldCost = 0.0; //if (pivotRow_ >= 0) //oldCost = abcCost_[sequenceOut_]; double * work = rowArray.denseVector(); int number = rowArray.getNumElements(); int * which = rowArray.getIndices(); // allow for case where bound+tolerance == bound //double tolerance = 0.999999*primalTolerance_; double relaxedTolerance = 1.001 * primalTolerance_; int iIndex; if (!valuesPass) { for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; //work[iRow] = 0.0; int iPivot = abcPivotVariable_[iRow]; double change = theta * alpha; double value = abcSolution_[iPivot] - change; abcSolution_[iPivot] = value; value = solutionBasic_[iRow] - change; solutionBasic_[iRow] = value; if (active(iRow) || theta_ < 0.0) { clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= abcLower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value >= abcLower_[iPivot] - relaxedTolerance) value = abcLower_[iPivot]; abcNonLinearCost_->setOneBasic(iRow, value); } } else { // going up if (value >= abcUpper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < abcUpper_[iPivot] + relaxedTolerance) value = abcUpper_[iPivot]; abcNonLinearCost_->setOneBasic(iRow, value); } } } } } else { // values pass so look at all for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; double alpha = work[iRow]; //work[iRow] = 0.0; int iPivot = abcPivotVariable_[iRow]; double change = theta * alpha; double value = abcSolution_[iPivot] - change; abcSolution_[iPivot] = value; value = solutionBasic_[iRow] - change; solutionBasic_[iRow] = value; clearActive(iRow); // But make sure one going out is feasible if (change > 0.0) { // going down if (value <= abcLower_[iPivot] + primalTolerance_) { if (iPivot == sequenceOut_ && value > abcLower_[iPivot] - relaxedTolerance) value = abcLower_[iPivot]; abcNonLinearCost_->setOneBasic(iRow, value); } } else { // going up if (value >= abcUpper_[iPivot] - primalTolerance_) { if (iPivot == sequenceOut_ && value < abcUpper_[iPivot] + relaxedTolerance) value = abcUpper_[iPivot]; abcNonLinearCost_->setOneBasic(iRow, value); } } } } //rowArray.setNumElements(0); } /* After rowArray will have cost changes for use next major iteration */ void AbcSimplexPrimal::createUpdateDuals(CoinIndexedVector & rowArray, const double * originalCost, const double extraCost[4], double & /*objectiveChange*/, int /*valuesPass*/) { int number=0; double * work = rowArray.denseVector(); int * which = rowArray.getIndices(); for (int iRow=0;iRow(abcFactorization_->factorization()); if (factorization) factorization->updatePartialUpdate(partialUpdate); } // Create primal ray void AbcSimplexPrimal::primalRay(CoinIndexedVector * rowArray) { delete [] ray_; ray_ = new double [numberColumns_]; CoinZeroN(ray_, numberColumns_); int number = rowArray->getNumElements(); int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); double way = -directionIn_; int i; double zeroTolerance = 1.0e-12; if (sequenceIn_ < numberColumns_) ray_[sequenceIn_] = directionIn_; for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = abcPivotVariable_[iRow]; double arrayValue = array[iRow]; if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance) ray_[iPivot] = way * arrayValue; } } /* Get next superbasic -1 if none, Normal type is 1 If type is 3 then initializes sorted list if 2 uses list. */ int AbcSimplexPrimal::nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray) { int returnValue = -1; bool finished = false; while (!finished) { returnValue = firstFree_; int iColumn = firstFree_ + 1; if (superBasicType > 1) { if (superBasicType > 2) { // Initialize list // Wild guess that lower bound more natural than upper int number = 0; double * work = columnArray->denseVector(); int * which = columnArray->getIndices(); for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (getInternalStatus(iColumn) == superBasic) { if (fabs(abcSolution_[iColumn] - abcLower_[iColumn]) <= primalTolerance_) { abcSolution_[iColumn] = abcLower_[iColumn]; setInternalStatus(iColumn, atLowerBound); } else if (fabs(abcSolution_[iColumn] - abcUpper_[iColumn]) <= primalTolerance_) { abcSolution_[iColumn] = abcUpper_[iColumn]; setInternalStatus(iColumn, atUpperBound); } else if (abcLower_[iColumn] < -1.0e20 && abcUpper_[iColumn] > 1.0e20) { setInternalStatus(iColumn, isFree); break; } else if (!flagged(iColumn)) { // put ones near bounds at end after sorting work[number] = - CoinMin(0.1 * (abcSolution_[iColumn] - abcLower_[iColumn]), abcUpper_[iColumn] - abcSolution_[iColumn]); which[number++] = iColumn; } } } } CoinSort_2(work, work + number, which); columnArray->setNumElements(number); CoinZeroN(work, number); } int * which = columnArray->getIndices(); int number = columnArray->getNumElements(); if (!number) { // finished iColumn = numberRows_ + numberColumns_; returnValue = -1; } else { number--; returnValue = which[number]; iColumn = returnValue; columnArray->setNumElements(number); } } else { for (; iColumn < numberRows_ + numberColumns_; iColumn++) { if (!flagged(iColumn)) { if (getInternalStatus(iColumn) == superBasic|| getInternalStatus(iColumn) == isFree) { if (fabs(abcSolution_[iColumn] - abcLower_[iColumn]) <= primalTolerance_) { abcSolution_[iColumn] = abcLower_[iColumn]; setInternalStatus(iColumn, atLowerBound); } else if (fabs(abcSolution_[iColumn] - abcUpper_[iColumn]) <= primalTolerance_) { abcSolution_[iColumn] = abcUpper_[iColumn]; setInternalStatus(iColumn, atUpperBound); } else if (abcLower_[iColumn] < -1.0e20 && abcUpper_[iColumn] > 1.0e20) { setInternalStatus(iColumn, isFree); if (fabs(abcDj_[iColumn])>10.0*dualTolerance_) break; } else { break; } } } } } firstFree_ = iColumn; finished = true; if (firstFree_ == numberRows_ + numberColumns_) firstFree_ = -1; if (returnValue >= 0 && getInternalStatus(returnValue) != superBasic && getInternalStatus(returnValue) != isFree) finished = false; // somehow picked up odd one } return returnValue; } void AbcSimplexPrimal::clearAll() { int number = usefulArray_[arrayForFtran_].getNumElements(); int * which = usefulArray_[arrayForFtran_].getIndices(); int iIndex; for (iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; clearActive(iRow); } usefulArray_[arrayForFtran_].clear(); for (int i=0;i<6;i++) { if (rowArray_[i]) rowArray_[i]->clear(); if (columnArray_[i]) columnArray_[i]->clear(); } } Clp-1.15.10/src/ClpNetworkMatrix.cpp0000644000076600007660000013211611510657452015635 0ustar coincoin/* $Id: ClpNetworkMatrix.cpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). #include #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinPackedVector.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" // at end to get min/max! #include "ClpNetworkMatrix.hpp" #include "ClpPlusMinusOneMatrix.hpp" #include "ClpMessage.hpp" #include #include //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNetworkMatrix::ClpNetworkMatrix () : ClpMatrixBase() { setType(11); matrix_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = 0; numberColumns_ = 0; trueNetwork_ = false; } /* Constructor from two arrays */ ClpNetworkMatrix::ClpNetworkMatrix(int numberColumns, const int * head, const int * tail) : ClpMatrixBase() { setType(11); matrix_ = NULL; lengths_ = NULL; indices_ = new int[2*numberColumns];; numberRows_ = -1; numberColumns_ = numberColumns; trueNetwork_ = true; int iColumn; CoinBigIndex j = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { int iRow = head[iColumn]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j] = iRow; iRow = tail[iColumn]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j+1] = iRow; } numberRows_++; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNetworkMatrix::ClpNetworkMatrix (const ClpNetworkMatrix & rhs) : ClpMatrixBase(rhs) { matrix_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; trueNetwork_ = rhs.trueNetwork_; if (numberColumns_) { indices_ = new int [ 2*numberColumns_]; CoinMemcpyN(rhs.indices_, 2 * numberColumns_, indices_); } int numberRows = getNumRows(); if (rhs.rhsOffset_ && numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_, numberRows); } else { rhsOffset_ = NULL; } } ClpNetworkMatrix::ClpNetworkMatrix (const CoinPackedMatrix & rhs) : ClpMatrixBase() { setType(11); matrix_ = NULL; lengths_ = NULL; indices_ = NULL; int iColumn; assert (rhs.isColOrdered()); // get matrix data pointers const int * row = rhs.getIndices(); const CoinBigIndex * columnStart = rhs.getVectorStarts(); const int * columnLength = rhs.getVectorLengths(); const double * elementByColumn = rhs.getElements(); numberColumns_ = rhs.getNumCols(); int goodNetwork = 1; numberRows_ = -1; indices_ = new int[2*numberColumns_]; CoinBigIndex j = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { CoinBigIndex k = columnStart[iColumn]; int iRow; switch (columnLength[iColumn]) { case 0: goodNetwork = -1; // not classic network indices_[j] = -1; indices_[j+1] = -1; break; case 1: goodNetwork = -1; // not classic network if (fabs(elementByColumn[k] - 1.0) < 1.0e-10) { indices_[j] = -1; iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j+1] = iRow; } else if (fabs(elementByColumn[k] + 1.0) < 1.0e-10) { indices_[j+1] = -1; iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j] = iRow; } else { goodNetwork = 0; // not a network } break; case 2: if (fabs(elementByColumn[k] - 1.0) < 1.0e-10) { if (fabs(elementByColumn[k+1] + 1.0) < 1.0e-10) { iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j+1] = iRow; iRow = row[k+1]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j] = iRow; } else { goodNetwork = 0; // not a network } } else if (fabs(elementByColumn[k] + 1.0) < 1.0e-10) { if (fabs(elementByColumn[k+1] - 1.0) < 1.0e-10) { iRow = row[k]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j] = iRow; iRow = row[k+1]; numberRows_ = CoinMax(numberRows_, iRow); indices_[j+1] = iRow; } else { goodNetwork = 0; // not a network } } else { goodNetwork = 0; // not a network } break; default: goodNetwork = 0; // not a network break; } if (!goodNetwork) break; } if (!goodNetwork) { delete [] indices_; // put in message printf("Not a network - can test if indices_ null\n"); indices_ = NULL; numberRows_ = 0; numberColumns_ = 0; } else { numberRows_ ++; // correct trueNetwork_ = goodNetwork > 0; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNetworkMatrix::~ClpNetworkMatrix () { delete matrix_; delete [] lengths_; delete [] indices_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNetworkMatrix & ClpNetworkMatrix::operator=(const ClpNetworkMatrix& rhs) { if (this != &rhs) { ClpMatrixBase::operator=(rhs); delete matrix_; delete [] lengths_; delete [] indices_; matrix_ = NULL; lengths_ = NULL; indices_ = NULL; numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; trueNetwork_ = rhs.trueNetwork_; if (numberColumns_) { indices_ = new int [ 2*numberColumns_]; CoinMemcpyN(rhs.indices_, 2 * numberColumns_, indices_); } } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpNetworkMatrix::clone() const { return new ClpNetworkMatrix(*this); } /* Returns a new matrix in reverse order without gaps */ ClpMatrixBase * ClpNetworkMatrix::reverseOrderedCopy() const { // count number in each row CoinBigIndex * tempP = new CoinBigIndex [numberRows_]; CoinBigIndex * tempN = new CoinBigIndex [numberRows_]; memset(tempP, 0, numberRows_ * sizeof(CoinBigIndex)); memset(tempN, 0, numberRows_ * sizeof(CoinBigIndex)); CoinBigIndex j = 0; int i; for (i = 0; i < numberColumns_; i++, j += 2) { int iRow = indices_[j]; tempN[iRow]++; iRow = indices_[j+1]; tempP[iRow]++; } int * newIndices = new int [2*numberColumns_]; CoinBigIndex * newP = new CoinBigIndex [numberRows_+1]; CoinBigIndex * newN = new CoinBigIndex[numberRows_]; int iRow; j = 0; // do starts for (iRow = 0; iRow < numberRows_; iRow++) { newP[iRow] = j; j += tempP[iRow]; tempP[iRow] = newP[iRow]; newN[iRow] = j; j += tempN[iRow]; tempN[iRow] = newN[iRow]; } newP[numberRows_] = j; j = 0; for (i = 0; i < numberColumns_; i++, j += 2) { int iRow = indices_[j]; CoinBigIndex put = tempN[iRow]; newIndices[put++] = i; tempN[iRow] = put; iRow = indices_[j+1]; put = tempP[iRow]; newIndices[put++] = i; tempP[iRow] = put; } delete [] tempP; delete [] tempN; ClpPlusMinusOneMatrix * newCopy = new ClpPlusMinusOneMatrix(); newCopy->passInCopy(numberRows_, numberColumns_, false, newIndices, newP, newN); return newCopy; } //unscaled versions void ClpNetworkMatrix::times(double scalar, const double * x, double * y) const { int iColumn; CoinBigIndex j = 0; if (trueNetwork_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = scalar * x[iColumn]; if (value) { int iRowM = indices_[j]; int iRowP = indices_[j+1]; y[iRowM] -= value; y[iRowP] += value; } } } else { // skip negative rows for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = scalar * x[iColumn]; if (value) { int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) y[iRowM] -= value; if (iRowP >= 0) y[iRowP] += value; } } } } void ClpNetworkMatrix::transposeTimes(double scalar, const double * x, double * y) const { int iColumn; CoinBigIndex j = 0; if (trueNetwork_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = y[iColumn]; int iRowM = indices_[j]; int iRowP = indices_[j+1]; value -= scalar * x[iRowM]; value += scalar * x[iRowP]; y[iColumn] = value; } } else { // skip negative rows for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = y[iColumn]; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) value -= scalar * x[iRowM]; if (iRowP >= 0) value += scalar * x[iRowP]; y[iColumn] = value; } } } void ClpNetworkMatrix::times(double scalar, const double * x, double * y, const double * /*rowScale*/, const double * /*columnScale*/) const { // we know it is not scaled times(scalar, x, y); } void ClpNetworkMatrix::transposeTimes( double scalar, const double * x, double * y, const double * /*rowScale*/, const double * /*columnScale*/, double * /*spare*/) const { // we know it is not scaled transposeTimes(scalar, x, y); } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpNetworkMatrix::transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { // we know it is not scaled columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); int numberRows = model->numberRows(); #ifndef NO_RTTI ClpPlusMinusOneMatrix* rowCopy = dynamic_cast< ClpPlusMinusOneMatrix*>(model->rowCopy()); #else ClpPlusMinusOneMatrix* rowCopy = static_cast< ClpPlusMinusOneMatrix*>(model->rowCopy()); #endif bool packed = rowArray->packedMode(); double factor = 0.3; // We may not want to do by row if there may be cache problems int numberColumns = model->numberColumns(); // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberColumns * sizeof(double) > 1000000) { if (numberRows * 10 < numberColumns) factor = 0.1; else if (numberRows * 4 < numberColumns) factor = 0.15; else if (numberRows * 2 < numberColumns) factor = 0.2; //if (model->numberIterations()%50==0) //printf("%d nonzero\n",numberInRowArray); } if (numberInRowArray > factor * numberRows || !rowCopy) { // do by column int iColumn; assert (!y->getNumElements()); CoinBigIndex j = 0; if (packed) { // need to expand pi into y assert(y->capacity() >= numberRows); double * piOld = pi; pi = y->denseVector(); const int * whichRow = rowArray->getIndices(); int i; // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i]; } if (trueNetwork_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = 0.0; int iRowM = indices_[j]; int iRowP = indices_[j+1]; value -= pi[iRowM]; value += pi[iRowP]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } else { // skip negative rows for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = 0.0; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) value -= pi[iRowM]; if (iRowP >= 0) value += pi[iRowP]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { if (trueNetwork_) { for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = 0.0; int iRowM = indices_[j]; int iRowP = indices_[j+1]; value -= scalar * pi[iRowM]; value += scalar * pi[iRowP]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } else { // skip negative rows for (iColumn = 0; iColumn < numberColumns_; iColumn++, j += 2) { double value = 0.0; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) value -= scalar * pi[iRowM]; if (iRowP >= 0) value += scalar * pi[iRowP]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } } columnArray->setNumElements(numberNonZero); } else { // do by row rowCopy->transposeTimesByRow(model, scalar, rowArray, y, columnArray); } } /* Return x *A in z but just for indices in y. */ void ClpNetworkMatrix::subsetTransposeTimes(const ClpSimplex * /*model*/, const CoinIndexedVector * rowArray, const CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); double * array = columnArray->denseVector(); int jColumn; int numberToDo = y->getNumElements(); const int * which = y->getIndices(); assert (!rowArray->packedMode()); columnArray->setPacked(); if (trueNetwork_) { for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; value -= pi[iRowM]; value += pi[iRowP]; array[jColumn] = value; } } else { // skip negative rows for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) value -= pi[iRowM]; if (iRowP >= 0) value += pi[iRowP]; array[jColumn] = value; } } } /// returns number of elements in column part of basis, CoinBigIndex ClpNetworkMatrix::countBasis( const int * whichColumn, int & numberColumnBasic) { int i; CoinBigIndex numberElements = 0; if (trueNetwork_) { numberElements = 2 * numberColumnBasic; } else { for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) numberElements ++; if (iRowP >= 0) numberElements ++; } } return numberElements; } void ClpNetworkMatrix::fillBasis(ClpSimplex * /*model*/, const int * whichColumn, int & numberColumnBasic, int * indexRowU, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * elementU) { int i; CoinBigIndex numberElements = start[0]; if (trueNetwork_) { for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; indexRowU[numberElements] = iRowM; rowCount[iRowM]++; elementU[numberElements] = -1.0; indexRowU[numberElements+1] = iRowP; rowCount[iRowP]++; elementU[numberElements+1] = 1.0; numberElements += 2; start[i+1] = numberElements; columnCount[i] = 2; } } else { for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) { indexRowU[numberElements] = iRowM; rowCount[iRowM]++; elementU[numberElements++] = -1.0; } if (iRowP >= 0) { indexRowU[numberElements] = iRowP; rowCount[iRowP]++; elementU[numberElements++] = 1.0; } start[i+1] = numberElements; columnCount[i] = numberElements - start[i]; } } } /* Unpacks a column into an CoinIndexedvector */ void ClpNetworkMatrix::unpack(const ClpSimplex * /*model*/, CoinIndexedVector * rowArray, int iColumn) const { CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) rowArray->add(iRowM, -1.0); if (iRowP >= 0) rowArray->add(iRowP, 1.0); } /* Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ void ClpNetworkMatrix::unpackPacked(ClpSimplex * /*model*/, CoinIndexedVector * rowArray, int iColumn) const { int * index = rowArray->getIndices(); double * array = rowArray->denseVector(); int number = 0; CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) { array[number] = -1.0; index[number++] = iRowM; } if (iRowP >= 0) { array[number] = 1.0; index[number++] = iRowP; } rowArray->setNumElements(number); rowArray->setPackedMode(true); } /* Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ void ClpNetworkMatrix::add(const ClpSimplex * /*model*/, CoinIndexedVector * rowArray, int iColumn, double multiplier) const { CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) rowArray->quickAdd(iRowM, -multiplier); if (iRowP >= 0) rowArray->quickAdd(iRowP, multiplier); } /* Adds multiple of a column into an array */ void ClpNetworkMatrix::add(const ClpSimplex * /*model*/, double * array, int iColumn, double multiplier) const { CoinBigIndex j = iColumn << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) array[iRowM] -= multiplier; if (iRowP >= 0) array[iRowP] += multiplier; } // Return a complete CoinPackedMatrix CoinPackedMatrix * ClpNetworkMatrix::getPackedMatrix() const { if (!matrix_) { assert (trueNetwork_); // fix later int numberElements = 2 * numberColumns_; double * elements = new double [numberElements]; CoinBigIndex i; for (i = 0; i < 2 * numberColumns_; i += 2) { elements[i] = -1.0; elements[i+1] = 1.0; } CoinBigIndex * starts = new CoinBigIndex [numberColumns_+1]; for (i = 0; i < numberColumns_ + 1; i++) { starts[i] = 2 * i; } // use assignMatrix to save space delete [] lengths_; lengths_ = NULL; matrix_ = new CoinPackedMatrix(); int * indices = CoinCopyOfArray(indices_, 2 * numberColumns_); matrix_->assignMatrix(true, numberRows_, numberColumns_, getNumElements(), elements, indices, starts, lengths_); assert(!elements); assert(!starts); assert (!indices); assert (!lengths_); } return matrix_; } /* A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ const double * ClpNetworkMatrix::getElements() const { if (!matrix_) getPackedMatrix(); return matrix_->getElements(); } const CoinBigIndex * ClpNetworkMatrix::getVectorStarts() const { if (!matrix_) getPackedMatrix(); return matrix_->getVectorStarts(); } /* The lengths of the major-dimension vectors. */ const int * ClpNetworkMatrix::getVectorLengths() const { assert (trueNetwork_); // fix later if (!lengths_) { lengths_ = new int [numberColumns_]; int i; for (i = 0; i < numberColumns_; i++) { lengths_[i] = 2; } } return lengths_; } /* Delete the columns whose indices are listed in indDel. */ void ClpNetworkMatrix::deleteCols(const int numDel, const int * indDel) { assert (trueNetwork_); int iColumn; int numberBad = 0; // Use array to make sure we can have duplicates char * which = new char[numberColumns_]; memset(which, 0, numberColumns_); int nDuplicate = 0; for (iColumn = 0; iColumn < numDel; iColumn++) { int jColumn = indDel[iColumn]; if (jColumn < 0 || jColumn >= numberColumns_) { numberBad++; } else { if (which[jColumn]) nDuplicate++; else which[jColumn] = 1; } } if (numberBad) throw CoinError("Indices out of range", "deleteCols", "ClpNetworkMatrix"); int newNumber = numberColumns_ - numDel + nDuplicate; // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; int newSize = 2 * newNumber; int * newIndices = new int [newSize]; newSize = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (!which[iColumn]) { CoinBigIndex start; CoinBigIndex i; start = 2 * iColumn; for (i = start; i < start + 2; i++) newIndices[newSize++] = indices_[i]; } } delete [] which; delete [] indices_; indices_ = newIndices; numberColumns_ = newNumber; } /* Delete the rows whose indices are listed in indDel. */ void ClpNetworkMatrix::deleteRows(const int numDel, const int * indDel) { int iRow; int numberBad = 0; // Use array to make sure we can have duplicates int * which = new int [numberRows_]; memset(which, 0, numberRows_ * sizeof(int)); for (iRow = 0; iRow < numDel; iRow++) { int jRow = indDel[iRow]; if (jRow < 0 || jRow >= numberRows_) { numberBad++; } else { which[jRow] = 1; } } if (numberBad) throw CoinError("Indices out of range", "deleteRows", "ClpNetworkMatrix"); // Only valid of all columns have 0 entries int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex start; CoinBigIndex i; start = 2 * iColumn; for (i = start; i < start + 2; i++) { int iRow = indices_[i]; if (which[iRow]) numberBad++; } } if (numberBad) throw CoinError("Row has entries", "deleteRows", "ClpNetworkMatrix"); int newNumber = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (!which[iRow]) which[iRow] = newNumber++; else which[iRow] = -1; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinBigIndex start; CoinBigIndex i; start = 2 * iColumn; for (i = start; i < start + 2; i++) { int iRow = indices_[i]; indices_[i] = which[iRow]; } } delete [] which; numberRows_ = newNumber; } /* Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ CoinBigIndex * ClpNetworkMatrix::dubiousWeights(const ClpSimplex * model, int * inputWeights) const { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int number = numberRows + numberColumns; CoinBigIndex * weights = new CoinBigIndex[number]; int i; for (i = 0; i < numberColumns; i++) { CoinBigIndex j = i << 1; CoinBigIndex count = 0; int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) { count += inputWeights[iRowM]; } if (iRowP >= 0) { count += inputWeights[iRowP]; } weights[i] = count; } for (i = 0; i < numberRows; i++) { weights[i+numberColumns] = inputWeights[i]; } return weights; } /* Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ void ClpNetworkMatrix::rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive) { smallestNegative = -1.0; largestNegative = -1.0; smallestPositive = 1.0; largestPositive = 1.0; } // Says whether it can do partial pricing bool ClpNetworkMatrix::canDoPartialPricing() const { return true; } // Partial pricing void ClpNetworkMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; int j; int start = static_cast (startFraction * numberColumns_); int end = CoinMin(static_cast (endFraction * numberColumns_ + 1), numberColumns_); double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); const double * cost = model->costRegion(); double bestDj; if (bestSequence >= 0) bestDj = fabs(reducedCost[bestSequence]); else bestDj = tolerance; int sequenceOut = model->sequenceOut(); int saveSequence = bestSequence; if (!trueNetwork_) { // Not true network int iSequence; for (iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; int iRowM, iRowP; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = cost[iSequence]; j = iSequence << 1; // skip negative rows iRowM = indices_[j]; iRowP = indices_[j+1]; if (iRowM >= 0) value += duals[iRowM]; if (iRowP >= 0) value -= duals[iRowP]; value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence]; j = iSequence << 1; // skip negative rows iRowM = indices_[j]; iRowP = indices_[j+1]; if (iRowM >= 0) value += duals[iRowM]; if (iRowP >= 0) value -= duals[iRowP]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = cost[iSequence]; j = iSequence << 1; // skip negative rows iRowM = indices_[j]; iRowP = indices_[j+1]; if (iRowM >= 0) value += duals[iRowM]; if (iRowP >= 0) value -= duals[iRowP]; value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = cost[bestSequence]; j = bestSequence << 1; // skip negative rows int iRowM = indices_[j]; int iRowP = indices_[j+1]; if (iRowM >= 0) value += duals[iRowM]; if (iRowP >= 0) value -= duals[iRowP]; reducedCost[bestSequence] = value; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } } else { // true network int iSequence; for (iSequence = start; iSequence < end; iSequence++) { if (iSequence != sequenceOut) { double value; int iRowM, iRowP; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = cost[iSequence]; j = iSequence << 1; iRowM = indices_[j]; iRowP = indices_[j+1]; value += duals[iRowM]; value -= duals[iRowP]; value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence]; j = iSequence << 1; iRowM = indices_[j]; iRowP = indices_[j+1]; value += duals[iRowM]; value -= duals[iRowP]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = cost[iSequence]; j = iSequence << 1; iRowM = indices_[j]; iRowP = indices_[j+1]; value += duals[iRowM]; value -= duals[iRowP]; value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } if (bestSequence != saveSequence) { // recompute dj double value = cost[bestSequence]; j = bestSequence << 1; int iRowM = indices_[j]; int iRowP = indices_[j+1]; value += duals[iRowM]; value -= duals[iRowP]; reducedCost[bestSequence] = value; savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } } currentWanted_ = numberWanted; } // Allow any parts of a created CoinMatrix to be deleted void ClpNetworkMatrix::releasePackedMatrix() const { delete matrix_; delete [] lengths_; matrix_ = NULL; lengths_ = NULL; } // Append Columns void ClpNetworkMatrix::appendCols(int number, const CoinPackedVectorBase * const * columns) { int iColumn; int numberBad = 0; for (iColumn = 0; iColumn < number; iColumn++) { int n = columns[iColumn]->getNumElements(); const double * element = columns[iColumn]->getElements(); if (n != 2) numberBad++; if (fabs(element[0]) != 1.0 || fabs(element[1]) != 1.0) numberBad++; else if (element[0]*element[1] != -1.0) numberBad++; } if (numberBad) throw CoinError("Not network", "appendCols", "ClpNetworkMatrix"); // Get rid of temporary arrays delete [] lengths_; lengths_ = NULL; delete matrix_; matrix_ = NULL; CoinBigIndex size = 2 * number; int * temp2 = new int [numberColumns_*2+size]; CoinMemcpyN(indices_, numberColumns_ * 2, temp2); delete [] indices_; indices_ = temp2; // now add size = 2 * numberColumns_; for (iColumn = 0; iColumn < number; iColumn++) { const int * row = columns[iColumn]->getIndices(); const double * element = columns[iColumn]->getElements(); if (element[0] == -1.0) { indices_[size++] = row[0]; indices_[size++] = row[1]; } else { indices_[size++] = row[1]; indices_[size++] = row[0]; } } numberColumns_ += number; } // Append Rows void ClpNetworkMatrix::appendRows(int number, const CoinPackedVectorBase * const * rows) { // must be zero arrays int numberBad = 0; int iRow; for (iRow = 0; iRow < number; iRow++) { numberBad += rows[iRow]->getNumElements(); } if (numberBad) throw CoinError("Not NULL rows", "appendRows", "ClpNetworkMatrix"); numberRows_ += number; } #ifndef SLIM_CLP /* Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ int ClpNetworkMatrix::appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int /*numberOther*/) { int numberErrors = 0; // make into CoinPackedVector CoinPackedVectorBase ** vectors = new CoinPackedVectorBase * [number]; int iVector; for (iVector = 0; iVector < number; iVector++) { int iStart = starts[iVector]; vectors[iVector] = new CoinPackedVector(starts[iVector+1] - iStart, index + iStart, element + iStart); } if (type == 0) { // rows appendRows(number, vectors); } else { // columns appendCols(number, vectors); } for (iVector = 0; iVector < number; iVector++) delete vectors[iVector]; delete [] vectors; return numberErrors; } #endif /* Subset clone (without gaps). Duplicates are allowed and order is as given */ ClpMatrixBase * ClpNetworkMatrix::subsetClone (int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const { return new ClpNetworkMatrix(*this, numberRows, whichRows, numberColumns, whichColumns); } /* Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpNetworkMatrix::ClpNetworkMatrix ( const ClpNetworkMatrix & rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn) : ClpMatrixBase(rhs) { setType(11); matrix_ = NULL; lengths_ = NULL; indices_ = new int[2*numberColumns];; numberRows_ = numberRows; numberColumns_ = numberColumns; trueNetwork_ = true; int iColumn; int numberBad = 0; int * which = new int [rhs.numberRows_]; int iRow; for (iRow = 0; iRow < rhs.numberRows_; iRow++) which[iRow] = -1; int n = 0; for (iRow = 0; iRow < numberRows; iRow++) { int jRow = whichRow[iRow]; assert (jRow >= 0 && jRow < rhs.numberRows_); which[jRow] = n++; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { CoinBigIndex start; CoinBigIndex i; start = 2 * iColumn; CoinBigIndex offset = 2 * whichColumn[iColumn] - start; for (i = start; i < start + 2; i++) { int iRow = rhs.indices_[i+offset]; iRow = which[iRow]; if (iRow < 0) numberBad++; else indices_[i] = iRow; } } if (numberBad) throw CoinError("Invalid rows", "subsetConstructor", "ClpNetworkMatrix"); } Clp-1.15.10/src/ClpLsqr.cpp0000644000076600007660000003256612131314313013732 0ustar coincoin/* $Id: ClpLsqr.cpp 1941 2013-04-10 16:52:27Z 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). #include "ClpLsqr.hpp" #include "ClpPdco.hpp" void ClpLsqr::do_lsqr( CoinDenseVector &b, double damp, double atol, double btol, double conlim, int itnlim, bool show, Info info, CoinDenseVector &x , int *istop, int *itn, Outfo *outfo, bool precon, CoinDenseVector &Pr) { /** Special version of LSQR for use with pdco.m. It continues with a reduced atol if a pdco-specific test isn't satisfied with the input atol. */ // Initialize. static char term_msg[8][80] = { "The exact solution is x = 0", "The residual Ax - b is small enough, given ATOL and BTOL", "The least squares error is small enough, given ATOL", "The estimated condition number has exceeded CONLIM", "The residual Ax - b is small enough, given machine precision", "The least squares error is small enough, given machine precision", "The estimated condition number has exceeded machine precision", "The iteration limit has been reached" }; // printf("***************** Entering LSQR *************\n"); assert (model_); char str1[100], str2[100], str3[100], str4[100], head1[100], head2[100]; int n = ncols_; // set m,n from lsqr object *itn = 0; *istop = 0; double ctol = 0; if (conlim > 0) ctol = 1 / conlim; double anorm = 0; double acond = 0; double ddnorm = 0; double xnorm = 0; double xxnorm = 0; double z = 0; double cs2 = -1; double sn2 = 0; // Set up the first vectors u and v for the bidiagonalization. // These satisfy beta*u = b, alfa*v = A'u. CoinDenseVector u(b); CoinDenseVector v(n, 0.0); x.clear(); double alfa = 0; double beta = u.twoNorm(); if (beta > 0) { u = (1 / beta) * u; matVecMult( 2, v, u ); if (precon) v = v * Pr; alfa = v.twoNorm(); } if (alfa > 0) { v.scale(1 / alfa); } CoinDenseVector w(v); double arnorm = alfa * beta; if (arnorm == 0) { printf(" %s\n\n", term_msg[0]); return; } double rhobar = alfa; double phibar = beta; double bnorm = beta; double rnorm = beta; sprintf(head1, " Itn x(1) Function"); sprintf(head2, " Compatible LS Norm A Cond A"); if (show) { printf(" %s%s\n", head1, head2); double test1 = 1; double test2 = alfa / beta; sprintf(str1, "%6d %12.5e %10.3e", *itn, x[0], rnorm ); sprintf(str2, " %8.1e %8.1e", test1, test2 ); printf("%s%s\n", str1, str2); } //---------------------------------------------------------------- // Main iteration loop. //---------------------------------------------------------------- while (*itn < itnlim) { *itn += 1; // Perform the next step of the bidiagonalization to obtain the // next beta, u, alfa, v. These satisfy the relations // beta*u = a*v - alfa*u, // alfa*v = A'*u - beta*v. u.scale((-alfa)); if (precon) { CoinDenseVector pv(v * Pr); matVecMult( 1, u, pv); } else { matVecMult( 1, u, v); } beta = u.twoNorm(); if (beta > 0) { u.scale((1 / beta)); anorm = sqrt(anorm * anorm + alfa * alfa + beta * beta + damp * damp); v.scale((-beta)); CoinDenseVector vv(n); vv.clear(); matVecMult( 2, vv, u ); if (precon) vv = vv * Pr; v = v + vv; alfa = v.twoNorm(); if (alfa > 0) v.scale((1 / alfa)); } // Use a plane rotation to eliminate the damping parameter. // This alters the diagonal (rhobar) of the lower-bidiagonal matrix. double rhobar1 = sqrt(rhobar * rhobar + damp * damp); double cs1 = rhobar / rhobar1; double sn1 = damp / rhobar1; double psi = sn1 * phibar; phibar *= cs1; // Use a plane rotation to eliminate the subdiagonal element (beta) // of the lower-bidiagonal matrix, giving an upper-bidiagonal matrix. double rho = sqrt(rhobar1 * rhobar1 + beta * beta); double cs = rhobar1 / rho; double sn = beta / rho; double theta = sn * alfa; rhobar = - cs * alfa; double phi = cs * phibar; phibar = sn * phibar; double tau = sn * phi; // Update x and w. double t1 = phi / rho; double t2 = - theta / rho; // dk = ((1/rho)*w); double w_norm = w.twoNorm(); x = x + t1 * w; w = v + t2 * w; ddnorm = ddnorm + (w_norm / rho) * (w_norm / rho); // if wantvar, var = var + dk.*dk; end // Use a plane rotation on the right to eliminate the // super-diagonal element (theta) of the upper-bidiagonal matrix. // Then use the result to estimate norm(x). double delta = sn2 * rho; double gambar = - cs2 * rho; double rhs = phi - delta * z; double zbar = rhs / gambar; xnorm = sqrt(xxnorm + zbar * zbar); double gamma = sqrt(gambar * gambar + theta * theta); cs2 = gambar / gamma; sn2 = theta / gamma; z = rhs / gamma; xxnorm = xxnorm + z * z; // Test for convergence. // First, estimate the condition of the matrix Abar, // and the norms of rbar and Abar'rbar. acond = anorm * sqrt( ddnorm ); double res1 = phibar * phibar; double res2 = res1 + psi * psi; rnorm = sqrt( res1 + res2 ); arnorm = alfa * fabs( tau ); // Now use these norms to estimate certain other quantities, // some of which will be small near a solution. double test1 = rnorm / bnorm; double test2 = arnorm / ( anorm * rnorm ); double test3 = 1 / acond; t1 = test1 / (1 + anorm * xnorm / bnorm); double rtol = btol + atol * anorm * xnorm / bnorm; // The following tests guard against extremely small values of // atol, btol or ctol. (The user may have set any or all of // the parameters atol, btol, conlim to 0.) // The effect is equivalent to the normal tests using // atol = eps, btol = eps, conlim = 1/eps. if (*itn >= itnlim) *istop = 7; if (1 + test3 <= 1) *istop = 6; if (1 + test2 <= 1) *istop = 5; if (1 + t1 <= 1) *istop = 4; // Allow for tolerances set by the user. if (test3 <= ctol) *istop = 3; if (test2 <= atol) *istop = 2; if (test1 <= rtol) *istop = 1; //------------------------------------------------------------------- // SPECIAL TEST THAT DEPENDS ON pdco.m. // Aname in pdco is iw in lsqr. // dy is x // Other stuff is in info. // We allow for diagonal preconditioning in pdDDD3. //------------------------------------------------------------------- if (*istop > 0) { double r3new = arnorm; double r3ratio = r3new / info.r3norm; double atolold = atol; double atolnew = atol; if (atol > info.atolmin) { if (r3ratio <= 0.1) { // dy seems good // Relax } else if (r3ratio <= 0.5) { // Accept dy but make next one more accurate. atolnew = atolnew * 0.1; } else { // Recompute dy more accurately if (show) { printf("\n "); printf(" \n"); printf(" %5.1f%7d%7.3f", log10(atolold), *itn, r3ratio); } atol = atol * 0.1; atolnew = atol; *istop = 0; } outfo->atolold = atolold; outfo->atolnew = atolnew; outfo->r3ratio = r3ratio; } //------------------------------------------------------------------- // See if it is time to print something. //------------------------------------------------------------------- int prnt = 0; if (n <= 40 ) prnt = 1; if (*itn <= 10 ) prnt = 1; if (*itn >= itnlim - 10) prnt = 1; if (*itn % 10 == 0 ) prnt = 1; if (test3 <= 2 * ctol ) prnt = 1; if (test2 <= 10 * atol ) prnt = 1; if (test1 <= 10 * rtol ) prnt = 1; if (*istop != 0 ) prnt = 1; if (prnt == 1) { if (show) { sprintf(str1, " %6d %12.5e %10.3e", *itn, x[0], rnorm ); sprintf(str2, " %8.1e %8.1e", test1, test2 ); sprintf(str3, " %8.1e %8.1e", anorm, acond ); printf("%s%s%s\n", str1, str2, str3); } } if (*istop > 0) break; } } // End of iteration loop. // Print the stopping condition. if (show) { printf("\n LSQR finished\n"); // disp(msg(istop+1,:)) // disp(' ') printf("%s\n", term_msg[*istop]); sprintf(str1, "istop =%8d itn =%8d", *istop, *itn ); sprintf(str2, "anorm =%8.1e acond =%8.1e", anorm, acond ); sprintf(str3, "rnorm =%8.1e arnorm =%8.1e", rnorm, arnorm ); sprintf(str4, "bnorm =%8.1e xnorm =%8.1e", bnorm, xnorm ); printf("%s %s\n", str1, str2); printf("%s %s\n", str3, str4); } } void ClpLsqr::matVecMult( int mode, CoinDenseVector *x, CoinDenseVector *y) { int n = model_->numberColumns(); int m = model_->numberRows(); CoinDenseVector *temp = new CoinDenseVector(n, 0.0); double *t_elts = temp->getElements(); double *x_elts = x->getElements(); double *y_elts = y->getElements(); ClpPdco * pdcoModel = (ClpPdco *) model_; if (mode == 1) { pdcoModel->matVecMult( 2, temp, y); for (int k = 0; k < n; k++) x_elts[k] += (diag1_[k] * t_elts[k]); for (int k = 0; k < m; k++) x_elts[n+k] += (diag2_ * y_elts[k]); } else { for (int k = 0; k < n; k++) t_elts[k] = diag1_[k] * y_elts[k]; pdcoModel->matVecMult( 1, x, temp); for (int k = 0; k < m; k++) x_elts[k] += diag2_ * y_elts[n+k]; } delete temp; return; } void ClpLsqr::matVecMult( int mode, CoinDenseVector &x, CoinDenseVector &y) { matVecMult( mode, &x, &y); return; } /* Default constructor */ ClpLsqr::ClpLsqr() : nrows_(0), ncols_(0), model_(NULL), diag1_(NULL), diag2_(0.0) {} /* Constructor for use with Pdco model (note modified for pdco!!!!) */ ClpLsqr::ClpLsqr(ClpInterior *model) : diag1_(NULL), diag2_(0.0) { model_ = model; nrows_ = model->numberRows() + model->numberColumns(); ncols_ = model->numberRows(); } /** Destructor */ ClpLsqr::~ClpLsqr() { // delete [] diag1_; no as we just borrowed it } bool ClpLsqr::setParam(char *parmName, int parmValue) { std::cout << "Set lsqr integer parameter " << parmName << "to " << parmValue << std::endl; if ( strcmp(parmName, "nrows") == 0) { nrows_ = parmValue; return 1; } else if ( strcmp(parmName, "ncols") == 0) { ncols_ = parmValue; return 1; } std::cout << "Attempt to set unknown integer parameter name " << parmName << std::endl; return 0; } ClpLsqr::ClpLsqr(const ClpLsqr &rhs) : nrows_(rhs.nrows_), ncols_(rhs.ncols_), model_(rhs.model_), diag2_(rhs.diag2_) { diag1_ = ClpCopyOfArray(rhs.diag1_, nrows_); } // Assignment operator. This copies the data ClpLsqr & ClpLsqr::operator=(const ClpLsqr & rhs) { if (this != &rhs) { delete [] diag1_; diag1_ = ClpCopyOfArray(rhs.diag1_, nrows_); nrows_ = rhs.nrows_; ncols_ = rhs.ncols_; model_ = rhs.model_; diag2_ = rhs.diag2_; } return *this; } Clp-1.15.10/src/Idiot.hpp0000644000076600007660000002437411510657452013443 0ustar coincoin/* $Id: Idiot.hpp 1665 2011-01-04 17:55:54Z 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). // "Idiot" as the name of this algorithm is copylefted. If you want to change // the name then it should be something equally stupid (but not "Stupid") or // even better something witty. #ifndef Idiot_H #define Idiot_H #ifndef OSI_IDIOT #include "ClpSimplex.hpp" #define OsiSolverInterface ClpSimplex #else #include "OsiSolverInterface.hpp" typedef int CoinBigIndex; #endif class CoinMessageHandler; class CoinMessages; /// for use internally typedef struct { double infeas; double objval; double dropThis; double weighted; double sumSquared; double djAtBeginning; double djAtEnd; int iteration; } IdiotResult; /** This class implements a very silly algorithm. It has no merit apart from the fact that it gets an approximate solution to some classes of problems. Better if vaguely homogeneous. It works on problems where volume algorithm works and often gets a better primal solution but it has no dual solution. It can also be used as a "crash" to get a problem started. This is probably its most useful function. It is based on the idea that algorithms with terrible convergence properties may be okay at first. Throw in some random dubious tricks and the resulting code may be worth keeping as long as you don't look at it. */ class Idiot { public: /**@name Constructors and destructor Just a pointer to model is kept */ //@{ /// Default constructor Idiot ( ); /// Constructor with model Idiot ( OsiSolverInterface & model ); /// Copy constructor. Idiot(const Idiot &); /// Assignment operator. This copies the data Idiot & operator=(const Idiot & rhs); /// Destructor ~Idiot ( ); //@} /**@name Algorithmic calls */ //@{ /// Get an approximate solution with the idiot code void solve(); /// Lightweight "crash" void crash(int numberPass, CoinMessageHandler * handler, const CoinMessages * messages, bool doCrossover = true); /** Use simplex to get an optimal solution mode is how many steps the simplex crossover should take to arrive to an extreme point: 0 - chosen,all ever used, all 1 - chosen, all 2 - all 3 - do not do anything - maybe basis + 16 do presolves */ void crossOver(int mode); //@} /**@name Gets and sets of most useful data */ //@{ /** Starting weight - small emphasizes feasibility, default 1.0e-4 */ inline double getStartingWeight() const { return mu_; } inline void setStartingWeight(double value) { mu_ = value; } /** Weight factor - weight multiplied by this when changes, default 0.333 */ inline double getWeightFactor() const { return muFactor_; } inline void setWeightFactor(double value) { muFactor_ = value; } /** Feasibility tolerance - problem essentially feasible if individual infeasibilities less than this. default 0.1 */ inline double getFeasibilityTolerance() const { return smallInfeas_; } inline void setFeasibilityTolerance(double value) { smallInfeas_ = value; } /** Reasonably feasible. Dubious method concentrates more on objective when sum of infeasibilities less than this. Very dubious default value of (Number of rows)/20 */ inline double getReasonablyFeasible() const { return reasonableInfeas_; } inline void setReasonablyFeasible(double value) { reasonableInfeas_ = value; } /** Exit infeasibility - exit if sum of infeasibilities less than this. Default -1.0 (i.e. switched off) */ inline double getExitInfeasibility() const { return exitFeasibility_; } inline void setExitInfeasibility(double value) { exitFeasibility_ = value; } /** Major iterations. stop after this number. Default 30. Use 2-5 for "crash" 50-100 for serious crunching */ inline int getMajorIterations() const { return majorIterations_; } inline void setMajorIterations(int value) { majorIterations_ = value; } /** Minor iterations. Do this number of tiny steps before deciding whether to change weights etc. Default - dubious sqrt(Number of Rows). Good numbers 105 to 405 say (5 is dubious method of making sure idiot is not trying to be clever which it may do every 10 minor iterations) */ inline int getMinorIterations() const { return maxIts2_; } inline void setMinorIterations(int value) { maxIts2_ = value; } // minor iterations for first time inline int getMinorIterations0() const { return maxIts_; } inline void setMinorIterations0(int value) { maxIts_ = value; } /** Reduce weight after this many major iterations. It may get reduced before this but this is a maximum. Default 3. 3-10 plausible. */ inline int getReduceIterations() const { return maxBigIts_; } inline void setReduceIterations(int value) { maxBigIts_ = value; } /// Amount of information - default of 1 should be okay inline int getLogLevel() const { return logLevel_; } inline void setLogLevel(int value) { logLevel_ = value; } /// How lightweight - 0 not, 1 yes, 2 very lightweight inline int getLightweight() const { return lightWeight_; } inline void setLightweight(int value) { lightWeight_ = value; } /// strategy inline int getStrategy() const { return strategy_; } inline void setStrategy(int value) { strategy_ = value; } /// Fine tuning - okay if feasibility drop this factor inline double getDropEnoughFeasibility() const { return dropEnoughFeasibility_; } inline void setDropEnoughFeasibility(double value) { dropEnoughFeasibility_ = value; } /// Fine tuning - okay if weighted obj drop this factor inline double getDropEnoughWeighted() const { return dropEnoughWeighted_; } inline void setDropEnoughWeighted(double value) { dropEnoughWeighted_ = value; } //@} /// Stuff for internal use private: /// Does actual work // allow public! public: void solve2(CoinMessageHandler * handler, const CoinMessages *messages); private: IdiotResult IdiSolve( int nrows, int ncols, double * rowsol , double * colsol, double * pi, double * djs, const double * origcost , double * rowlower, double * rowupper, const double * lower, const double * upper, const double * element, const int * row, const CoinBigIndex * colcc, const int * length, double * lambda, int maxIts, double mu, double drop, double maxmin, double offset, int strategy, double djTol, double djExit, double djFlag, CoinThreadRandom * randomNumberGenerator); int dropping(IdiotResult result, double tolerance, double small, int *nbad); IdiotResult objval(int nrows, int ncols, double * rowsol , double * colsol, double * pi, double * djs, const double * cost , const double * rowlower, const double * rowupper, const double * lower, const double * upper, const double * elemnt, const int * row, const CoinBigIndex * columnStart, const int * length, int extraBlock, int * rowExtra, double * solExtra, double * elemExtra, double * upperExtra, double * costExtra, double weight); // Deals with whenUsed and slacks int cleanIteration(int iteration, int ordinaryStart, int ordinaryEnd, double * colsol, const double * lower, const double * upper, const double * rowLower, const double * rowUpper, const double * cost, const double * element, double fixTolerance, double & objChange, double & infChange); private: /// Underlying model OsiSolverInterface * model_; double djTolerance_; double mu_; /* starting mu */ double drop_; /* exit if drop over 5 checks less than this */ double muFactor_; /* reduce mu by this */ double stopMu_; /* exit if mu gets smaller than this */ double smallInfeas_; /* feasibility tolerance */ double reasonableInfeas_; /* use lambdas if feasibility less than this */ double exitDrop_; /* candidate for stopping after a major iteration */ double muAtExit_; /* mu on exit */ double exitFeasibility_; /* exit if infeasibility less than this */ double dropEnoughFeasibility_; /* okay if feasibility drop this factor */ double dropEnoughWeighted_; /* okay if weighted obj drop this factor */ int * whenUsed_; /* array to say what was used */ int maxBigIts_; /* always reduce mu after this */ int maxIts_; /* do this many iterations on first go */ int majorIterations_; int logLevel_; int logFreq_; int checkFrequency_; /* can exit after 5 * this iterations (on drop) */ int lambdaIterations_; /* do at least this many lambda iterations */ int maxIts2_; /* do this many iterations on subsequent goes */ int strategy_; /* 0 - default strategy 1 - do accelerator step but be cautious 2 - do not do accelerator step 4 - drop, exitDrop and djTolerance all relative 8 - keep accelerator step to theta=10.0 32 - Scale 512 - crossover 2048 - keep lambda across mu change 4096 - return best solution (not last found) 8192 - always do a presolve in crossover 16384 - costed slacks found - so whenUsed_ longer */ int lightWeight_; // 0 - normal, 1 lightweight }; #endif Clp-1.15.10/src/ClpPdco.cpp0000644000076600007660000011600212131314313013662 0ustar coincoin/* $Id: ClpPdco.cpp 1941 2013-04-10 16:52:27Z 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). /* Pdco algorithm Method */ #include "CoinPragma.hpp" #include #include "CoinDenseVector.hpp" #include "ClpPdco.hpp" #include "ClpPdcoBase.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpLsqr.hpp" #include "CoinTime.hpp" #include "ClpMessage.hpp" #include #include #include #include #include int ClpPdco::pdco() { printf("Dummy pdco solve\n"); return 0; } // ** Temporary version int ClpPdco::pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo) { // D1, D2 are positive-definite diagonal matrices defined from d1, d2. // In particular, d2 indicates the accuracy required for // satisfying each row of Ax = b. // // D1 and D2 (via d1 and d2) provide primal and dual regularization // respectively. They ensure that the primal and dual solutions // (x,r) and (y,z) are unique and bounded. // // A scalar d1 is equivalent to d1 = ones(n,1), D1 = diag(d1). // A scalar d2 is equivalent to d2 = ones(m,1), D2 = diag(d2). // Typically, d1 = d2 = 1e-4. // These values perturb phi(x) only slightly (by about 1e-8) and request // that A*x = b be satisfied quite accurately (to about 1e-8). // Set d1 = 1e-4, d2 = 1 for least-squares problems with bound constraints. // The problem is then // // minimize phi(x) + 1/2 norm(d1*x)^2 + 1/2 norm(A*x - b)^2 // subject to bl <= x <= bu. // // More generally, d1 and d2 may be n and m vectors containing any positive // values (preferably not too small, and typically no larger than 1). // Bigger elements of d1 and d2 improve the stability of the solver. // // At an optimal solution, if x(j) is on its lower or upper bound, // the corresponding z(j) is positive or negative respectively. // If x(j) is between its bounds, z(j) = 0. // If bl(j) = bu(j), x(j) is fixed at that value and z(j) may have // either sign. // // Also, r and y satisfy r = D2 y, so that Ax + D2^2 y = b. // Thus if d2(i) = 1e-4, the i-th row of Ax = b will be satisfied to // approximately 1e-8. This determines how large d2(i) can safely be. // // // EXTERNAL FUNCTIONS: // options = pdcoSet; provided with pdco.m // [obj,grad,hess] = pdObj( x ); provided by user // y = pdMat( name,mode,m,n,x ); provided by user if pdMat // is a string, not a matrix // // INPUT ARGUMENTS: // pdObj is a string containing the name of a function pdObj.m // or a function_handle for such a function // such that [obj,grad,hess] = pdObj(x) defines // obj = phi(x) : a scalar, // grad = gradient of phi(x) : an n-vector, // hess = diag(Hessian of phi): an n-vector. // Examples: // If phi(x) is the linear function c"x, pdObj should return // [obj,grad,hess] = [c"*x, c, zeros(n,1)]. // If phi(x) is the entropy function E(x) = sum x(j) log x(j), // [obj,grad,hess] = [E(x), log(x)+1, 1./x]. // pdMat may be an ifexplicit m x n matrix A (preferably sparse!), // or a string containing the name of a function pdMat.m // or a function_handle for such a function // such that y = pdMat( name,mode,m,n,x ) // returns y = A*x (mode=1) or y = A"*x (mode=2). // The input parameter "name" will be the string pdMat. // b is an m-vector. // bl is an n-vector of lower bounds. Non-existent bounds // may be represented by bl(j) = -Inf or bl(j) <= -1e+20. // bu is an n-vector of upper bounds. Non-existent bounds // may be represented by bu(j) = Inf or bu(j) >= 1e+20. // d1, d2 may be positive scalars or positive vectors (see above). // options is a structure that may be set and altered by pdcoSet // (type help pdcoSet). // x0, y0, z0 provide an initial solution. // xsize, zsize are estimates of the biggest x and z at the solution. // They are used to scale (x,y,z). Good estimates // should improve the performance of the barrier method. // // // OUTPUT ARGUMENTS: // x is the primal solution. // y is the dual solution associated with Ax + D2 r = b. // z is the dual solution associated with bl <= x <= bu. // inform = 0 if a solution is found; // = 1 if too many iterations were required; // = 2 if the linesearch failed too often. // PDitns is the number of Primal-Dual Barrier iterations required. // CGitns is the number of Conjugate-Gradient iterations required // if an iterative solver is used (LSQR). // time is the cpu time used. //---------------------------------------------------------------------- // PRIVATE FUNCTIONS: // pdxxxbounds // pdxxxdistrib // pdxxxlsqr // pdxxxlsqrmat // pdxxxmat // pdxxxmerit // pdxxxresid1 // pdxxxresid2 // pdxxxstep // // GLOBAL VARIABLES: // global pdDDD1 pdDDD2 pdDDD3 // // // NOTES: // The matrix A should be reasonably well scaled: norm(A,inf) =~ 1. // The vector b and objective phi(x) may be of any size, but ensure that // xsize and zsize are reasonably close to norm(x,inf) and norm(z,inf) // at the solution. // // The files defining pdObj and pdMat // must not be called Fname.m or Aname.m!! // // // AUTHOR: // Michael Saunders, Systems Optimization Laboratory (SOL), // Stanford University, Stanford, California, USA. // saunders@stanford.edu // // CONTRIBUTORS: // Byunggyoo Kim, SOL, Stanford University. // bgkim@stanford.edu // // DEVELOPMENT: // 20 Jun 1997: Original version of pdsco.m derived from pdlp0.m. // 29 Sep 2002: Original version of pdco.m derived from pdsco.m. // Introduced D1, D2 in place of gamma*I, delta*I // and allowed for general bounds bl <= x <= bu. // 06 Oct 2002: Allowed for fixed variabes: bl(j) = bu(j) for any j. // 15 Oct 2002: Eliminated some work vectors (since m, n might be LARGE). // Modularized residuals, linesearch // 16 Oct 2002: pdxxx..., pdDDD... names rationalized. // pdAAA eliminated (global copy of A). // Aname is now used directly as an ifexplicit A or a function. // NOTE: If Aname is a function, it now has an extra parameter. // 23 Oct 2002: Fname and Aname can now be function handles. // 01 Nov 2002: Bug fixed in feval in pdxxxmat. //----------------------------------------------------------------------- // global pdDDD1 pdDDD2 pdDDD3 double inf = 1.0e30; double eps = 1.0e-15; double atolold = -1.0, r3ratio = -1.0, Pinf, Dinf, Cinf, Cinf0; printf("\n --------------------------------------------------------"); printf("\n pdco.m Version of 01 Nov 2002"); printf("\n Primal-dual barrier method to minimize a convex function"); printf("\n subject to linear constraints Ax + r = b, bl <= x <= bu"); printf("\n --------------------------------------------------------\n"); int m = numberRows_; int n = numberColumns_; bool ifexplicit = true; CoinDenseVector b(m, rhs_); CoinDenseVector x(n, x_); CoinDenseVector y(m, y_); CoinDenseVector z(n, dj_); //delete old arrays delete [] rhs_; delete [] x_; delete [] y_; delete [] dj_; rhs_ = NULL; x_ = NULL; y_ = NULL; dj_ = NULL; // Save stuff so available elsewhere pdcoStuff_ = stuff; double normb = b.infNorm(); double normx0 = x.infNorm(); double normy0 = y.infNorm(); double normz0 = z.infNorm(); printf("\nmax |b | = %8g max |x0| = %8g", normb , normx0); printf( " xsize = %8g", xsize_); printf("\nmax |y0| = %8g max |z0| = %8g", normy0, normz0); printf( " zsize = %8g", zsize_); //--------------------------------------------------------------------- // Initialize. //--------------------------------------------------------------------- //true = 1; //false = 0; //zn = zeros(n,1); //int nb = n + m; int CGitns = 0; int inform = 0; //--------------------------------------------------------------------- // Only allow scalar d1, d2 for now //--------------------------------------------------------------------- /* if (d1_->size()==1) d1_->resize(n, d1_->getElements()[0]); // Allow scalar d1, d2 if (d2_->size()==1) d2->resize(m, d2->getElements()[0]); // to mean dk * unit vector */ assert (stuff->sizeD1() == 1); double d1 = stuff->getD1(); double d2 = stuff->getD2(); //--------------------------------------------------------------------- // Grab input options. //--------------------------------------------------------------------- int maxitn = options.MaxIter; double featol = options.FeaTol; double opttol = options.OptTol; double steptol = options.StepTol; int stepSame = 1; /* options.StepSame; // 1 means stepx == stepz */ double x0min = options.x0min; double z0min = options.z0min; double mu0 = options.mu0; int LSproblem = options.LSproblem; // See below int LSmethod = options.LSmethod; // 1=Cholesky 2=QR 3=LSQR int itnlim = options.LSQRMaxIter * CoinMin(m, n); double atol1 = options.LSQRatol1; // Initial atol double atol2 = options.LSQRatol2; // Smallest atol,unless atol1 is smaller double conlim = options.LSQRconlim; //int wait = options.wait; // LSproblem: // 1 = dy 2 = dy shifted, DLS // 11 = s 12 = s shifted, DLS (dx = Ds) // 21 = dx // 31 = 3x3 system, symmetrized by Z^{1/2} // 32 = 2x2 system, symmetrized by X^{1/2} //--------------------------------------------------------------------- // Set other parameters. //--------------------------------------------------------------------- int kminor = 0; // 1 stops after each iteration double eta = 1e-4; // Linesearch tolerance for "sufficient descent" double maxf = 10; // Linesearch backtrack limit (function evaluations) double maxfail = 1; // Linesearch failure limit (consecutive iterations) double bigcenter = 1e+3; // mu is reduced if center < bigcenter. // Parameters for LSQR. double atolmin = eps; // Smallest atol if linesearch back-tracks double btol = 0; // Should be small (zero is ok) double show = false; // Controls lsqr iteration log /* double gamma = d1->infNorm(); double delta = d2->infNorm(); */ double gamma = d1; double delta = d2; printf("\n\nx0min = %8g featol = %8.1e", x0min, featol); printf( " d1max = %8.1e", gamma); printf( "\nz0min = %8g opttol = %8.1e", z0min, opttol); printf( " d2max = %8.1e", delta); printf( "\nmu0 = %8.1e steptol = %8g", mu0 , steptol); printf( " bigcenter= %8g" , bigcenter); printf("\n\nLSQR:"); printf("\natol1 = %8.1e atol2 = %8.1e", atol1 , atol2 ); printf( " btol = %8.1e", btol ); printf("\nconlim = %8.1e itnlim = %8d" , conlim, itnlim); printf( " show = %8g" , show ); // LSmethod = 3; ////// Hardwire LSQR // LSproblem = 1; ////// and LS problem defining "dy". /* if wait printf("\n\nReview parameters... then type "return"\n") keyboard end */ if (eta < 0) printf("\n\nLinesearch disabled by eta < 0"); //--------------------------------------------------------------------- // All parameters have now been set. //--------------------------------------------------------------------- double time = CoinCpuTime(); //bool useChol = (LSmethod == 1); //bool useQR = (LSmethod == 2); bool direct = (LSmethod <= 2 && ifexplicit); char solver[6]; strcpy(solver, " LSQR"); //--------------------------------------------------------------------- // Categorize bounds and allow for fixed variables by modifying b. //--------------------------------------------------------------------- int nlow, nupp, nfix; int *bptrs[3] = {0}; getBoundTypes(&nlow, &nupp, &nfix, bptrs ); int *low = bptrs[0]; int *upp = bptrs[1]; int *fix = bptrs[2]; int nU = n; if (nupp == 0) nU = 1; //Make dummy vectors if no Upper bounds //--------------------------------------------------------------------- // Get pointers to local copy of model bounds //--------------------------------------------------------------------- CoinDenseVector bl(n, columnLower_); double *bl_elts = bl.getElements(); CoinDenseVector bu(nU, columnUpper_); // this is dummy if no UB double *bu_elts = bu.getElements(); CoinDenseVector r1(m, 0.0); double *r1_elts = r1.getElements(); CoinDenseVector x1(n, 0.0); double *x1_elts = x1.getElements(); if (nfix > 0) { for (int k = 0; k < nfix; k++) x1_elts[fix[k]] = bl[fix[k]]; matVecMult(1, r1, x1); b = b - r1; // At some stage, might want to look at normfix = norm(r1,inf); } //--------------------------------------------------------------------- // Scale the input data. // The scaled variables are // xbar = x/beta, // ybar = y/zeta, // zbar = z/zeta. // Define // theta = beta*zeta; // The scaled function is // phibar = ( 1 /theta) fbar(beta*xbar), // gradient = (beta /theta) grad, // Hessian = (beta2/theta) hess. //--------------------------------------------------------------------- double beta = xsize_; if (beta == 0) beta = 1; // beta scales b, x. double zeta = zsize_; if (zeta == 0) zeta = 1; // zeta scales y, z. double theta = beta * zeta; // theta scales obj. // (theta could be anything, but theta = beta*zeta makes // scaled grad = grad/zeta = 1 approximately if zeta is chosen right.) for (int k = 0; k < nlow; k++) bl_elts[low[k]] = bl_elts[low[k]] / beta; for (int k = 0; k < nupp; k++) bu_elts[upp[k]] = bu_elts[upp[k]] / beta; d1 = d1 * ( beta / sqrt(theta) ); d2 = d2 * ( sqrt(theta) / beta ); double beta2 = beta * beta; b.scale( (1.0 / beta) ); y.scale( (1.0 / zeta) ); x.scale( (1.0 / beta) ); z.scale( (1.0 / zeta) ); //--------------------------------------------------------------------- // Initialize vectors that are not fully used if bounds are missing. //--------------------------------------------------------------------- CoinDenseVector rL(n, 0.0); CoinDenseVector cL(n, 0.0); CoinDenseVector z1(n, 0.0); CoinDenseVector dx1(n, 0.0); CoinDenseVector dz1(n, 0.0); CoinDenseVector r2(n, 0.0); // Assign upper bd regions (dummy if no UBs) CoinDenseVector rU(nU, 0.0); CoinDenseVector cU(nU, 0.0); CoinDenseVector x2(nU, 0.0); CoinDenseVector z2(nU, 0.0); CoinDenseVector dx2(nU, 0.0); CoinDenseVector dz2(nU, 0.0); //--------------------------------------------------------------------- // Initialize x, y, z, objective, etc. //--------------------------------------------------------------------- CoinDenseVector dx(n, 0.0); CoinDenseVector dy(m, 0.0); CoinDenseVector Pr(m); CoinDenseVector D(n); double *D_elts = D.getElements(); CoinDenseVector w(n); double *w_elts = w.getElements(); CoinDenseVector rhs(m + n); //--------------------------------------------------------------------- // Pull out the element array pointers for efficiency //--------------------------------------------------------------------- double *x_elts = x.getElements(); double *x2_elts = x2.getElements(); double *z_elts = z.getElements(); double *z1_elts = z1.getElements(); double *z2_elts = z2.getElements(); for (int k = 0; k < nlow; k++) { x_elts[low[k]] = CoinMax( x_elts[low[k]], bl[low[k]]); x1_elts[low[k]] = CoinMax( x_elts[low[k]] - bl[low[k]], x0min ); z1_elts[low[k]] = CoinMax( z_elts[low[k]], z0min ); } for (int k = 0; k < nupp; k++) { x_elts[upp[k]] = CoinMin( x_elts[upp[k]], bu[upp[k]]); x2_elts[upp[k]] = CoinMax(bu[upp[k]] - x_elts[upp[k]], x0min ); z2_elts[upp[k]] = CoinMax(-z_elts[upp[k]], z0min ); } //////////////////// Assume hessian is diagonal. ////////////////////// // [obj,grad,hess] = feval( Fname, (x*beta) ); x.scale(beta); double obj = getObj(x); CoinDenseVector grad(n); getGrad(x, grad); CoinDenseVector H(n); getHessian(x , H); x.scale((1.0 / beta)); //double * g_elts = grad.getElements(); double * H_elts = H.getElements(); obj /= theta; // Scaled obj. grad = grad * (beta / theta) + (d1 * d1) * x; // grad includes x regularization. H = H * (beta2 / theta) + (d1 * d1) ; // H includes x regularization. /*--------------------------------------------------------------------- // Compute primal and dual residuals: // r1 = b - Aprod(x) - d2*d2*y; // r2 = grad - Atprod(y) + z2 - z1; // rL = bl - x + x1; // rU = x + x2 - bu; */ //--------------------------------------------------------------------- // [r1,r2,rL,rU,Pinf,Dinf] = ... // pdxxxresid1( Aname,fix,low,upp, ... // b,bl,bu,d1,d2,grad,rL,rU,x,x1,x2,y,z1,z2 ); pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix, b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2, y, z1, z2, r1, r2, &Pinf, &Dinf); //--------------------------------------------------------------------- // Initialize mu and complementarity residuals: // cL = mu*e - X1*z1. // cU = mu*e - X2*z2. // // 25 Jan 2001: Now that b and obj are scaled (and hence x,y,z), // we should be able to use mufirst = mu0 (absolute value). // 0.1 worked poorly on StarTest1 with x0min = z0min = 0.1. // 29 Jan 2001: We might as well use mu0 = x0min * z0min; // so that most variables are centered after a warm start. // 29 Sep 2002: Use mufirst = mu0*(x0min * z0min), // regarding mu0 as a scaling of the initial center. //--------------------------------------------------------------------- // double mufirst = mu0*(x0min * z0min); double mufirst = mu0; // revert to absolute value double mulast = 0.1 * opttol; mulast = CoinMin( mulast, mufirst ); double mu = mufirst; double center, fmerit; pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2, ¢er, &Cinf, &Cinf0 ); fmerit = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU ); // Initialize other things. bool precon = true; double PDitns = 0; //bool converged = false; double atol = atol1; atol2 = CoinMax( atol2, atolmin ); atolmin = atol2; // pdDDD2 = d2; // Global vector for diagonal matrix D2 // Iteration log. int nf = 0; int itncg = 0; int nfail = 0; printf("\n\nItn mu stepx stepz Pinf Dinf"); printf(" Cinf Objective nf center"); if (direct) { printf("\n"); } else { printf(" atol solver Inexact\n"); } double regx = (d1 * x).twoNorm(); double regy = (d2 * y).twoNorm(); // regterm = twoNorm(d1.*x)^2 + norm(d2.*y)^2; double regterm = regx * regx + regy * regy; double objreg = obj + 0.5 * regterm; double objtrue = objreg * theta; printf("\n%3g ", PDitns ); printf("%6.1f%6.1f" , log10(Pinf ), log10(Dinf)); printf("%6.1f%15.7e", log10(Cinf0), objtrue ); printf(" %8.1f\n" , center ); /* if kminor printf("\n\nStart of first minor itn...\n"); keyboard end */ //--------------------------------------------------------------------- // Main loop. //--------------------------------------------------------------------- // Lsqr ClpLsqr thisLsqr(this); // while (converged) { while(PDitns < maxitn) { PDitns = PDitns + 1; // 31 Jan 2001: Set atol according to progress, a la Inexact Newton. // 07 Feb 2001: 0.1 not small enough for Satellite problem. Try 0.01. // 25 Apr 2001: 0.01 seems wasteful for Star problem. // Now that starting conditions are better, go back to 0.1. double r3norm = CoinMax(Pinf, CoinMax(Dinf, Cinf)); atol = CoinMin(atol, r3norm * 0.1); atol = CoinMax(atol, atolmin ); info.r3norm = r3norm; //------------------------------------------------------------------- // Define a damped Newton iteration for solving f = 0, // keeping x1, x2, z1, z2 > 0. We eliminate dx1, dx2, dz1, dz2 // to obtain the system // // [-H2 A" ] [ dx ] = [ w ], H2 = H + D1^2 + X1inv Z1 + X2inv Z2, // [ A D2^2] [ dy ] = [ r1] w = r2 - X1inv(cL + Z1 rL) // + X2inv(cU + Z2 rU), // // which is equivalent to the least-squares problem // // min || [ D A"]dy - [ D w ] ||, D = H2^{-1/2}. (*) // || [ D2 ] [D2inv r1] || //------------------------------------------------------------------- for (int k = 0; k < nlow; k++) H_elts[low[k]] = H_elts[low[k]] + z1[low[k]] / x1[low[k]]; for (int k = 0; k < nupp; k++) H[upp[k]] = H[upp[k]] + z2[upp[k]] / x2[upp[k]]; w = r2; for (int k = 0; k < nlow; k++) w[low[k]] = w[low[k]] - (cL[low[k]] + z1[low[k]] * rL[low[k]]) / x1[low[k]]; for (int k = 0; k < nupp; k++) w[upp[k]] = w[upp[k]] + (cU[upp[k]] + z2[upp[k]] * rU[upp[k]]) / x2[upp[k]]; if (LSproblem == 1) { //----------------------------------------------------------------- // Solve (*) for dy. //----------------------------------------------------------------- H = 1.0 / H; // H is now Hinv (NOTE!) for (int k = 0; k < nfix; k++) H[fix[k]] = 0; for (int k = 0; k < n; k++) D_elts[k] = sqrt(H_elts[k]); thisLsqr.borrowDiag1(D_elts); thisLsqr.diag2_ = d2; if (direct) { // Omit direct option for now } else {// Iterative solve using LSQR. //rhs = [ D.*w; r1./d2 ]; for (int k = 0; k < n; k++) rhs[k] = D_elts[k] * w_elts[k]; for (int k = 0; k < m; k++) rhs[n+k] = r1_elts[k] * (1.0 / d2); double damp = 0; if (precon) { // Construct diagonal preconditioner for LSQR matPrecon(d2, Pr, D); } /* rw(7) = precon; info.atolmin = atolmin; info.r3norm = fmerit; // Must be the 2-norm here. [ dy, istop, itncg, outfo ] = ... pdxxxlsqr( nb,m,"pdxxxlsqrmat",Aname,rw,rhs,damp, ... atol,btol,conlim,itnlim,show,info ); thisLsqr.input->rhs_vec = &rhs; thisLsqr.input->sol_vec = &dy; thisLsqr.input->rel_mat_err = atol; thisLsqr.do_lsqr(this); */ // New version of lsqr int istop; dy.clear(); show = false; info.atolmin = atolmin; info.r3norm = fmerit; // Must be the 2-norm here. thisLsqr.do_lsqr( rhs, damp, atol, btol, conlim, itnlim, show, info, dy , &istop, &itncg, &outfo, precon, Pr); if (precon) dy = dy * Pr; if (!precon && itncg > 999999) precon = true; if (istop == 3 || istop == 7 ) // conlim or itnlim printf("\n LSQR stopped early: istop = //%d", istop); atolold = outfo.atolold; atol = outfo.atolnew; r3ratio = outfo.r3ratio; }// LSproblem 1 // grad = pdxxxmat( Aname,2,m,n,dy ); // grad = A"dy grad.clear(); matVecMult(2, grad, dy); for (int k = 0; k < nfix; k++) grad[fix[k]] = 0; // grad is a work vector dx = H * (grad - w); } else { perror( "This LSproblem not yet implemented\n" ); } //------------------------------------------------------------------- CGitns += itncg; //------------------------------------------------------------------- // dx and dy are now known. Get dx1, dx2, dz1, dz2. //------------------------------------------------------------------- for (int k = 0; k < nlow; k++) { dx1[low[k]] = - rL[low[k]] + dx[low[k]]; dz1[low[k]] = (cL[low[k]] - z1[low[k]] * dx1[low[k]]) / x1[low[k]]; } for (int k = 0; k < nupp; k++) { dx2[upp[k]] = - rU[upp[k]] - dx[upp[k]]; dz2[upp[k]] = (cU[upp[k]] - z2[upp[k]] * dx2[upp[k]]) / x2[upp[k]]; } //------------------------------------------------------------------- // Find the maximum step. //-------------------------------------------------------------------- double stepx1 = pdxxxstep(nlow, low, x1, dx1 ); double stepx2 = inf; if (nupp > 0) stepx2 = pdxxxstep(nupp, upp, x2, dx2 ); double stepz1 = pdxxxstep( z1 , dz1 ); double stepz2 = inf; if (nupp > 0) stepz2 = pdxxxstep( z2 , dz2 ); double stepx = CoinMin( stepx1, stepx2 ); double stepz = CoinMin( stepz1, stepz2 ); stepx = CoinMin( steptol * stepx, 1.0 ); stepz = CoinMin( steptol * stepz, 1.0 ); if (stepSame) { // For NLPs, force same step stepx = CoinMin( stepx, stepz ); // (true Newton method) stepz = stepx; } //------------------------------------------------------------------- // Backtracking linesearch. //------------------------------------------------------------------- bool fail = true; nf = 0; while (nf < maxf) { nf = nf + 1; x = x + stepx * dx; y = y + stepz * dy; for (int k = 0; k < nlow; k++) { x1[low[k]] = x1[low[k]] + stepx * dx1[low[k]]; z1[low[k]] = z1[low[k]] + stepz * dz1[low[k]]; } for (int k = 0; k < nupp; k++) { x2[upp[k]] = x2[upp[k]] + stepx * dx2[upp[k]]; z2[upp[k]] = z2[upp[k]] + stepz * dz2[upp[k]]; } // [obj,grad,hess] = feval( Fname, (x*beta) ); x.scale(beta); obj = getObj(x); getGrad(x, grad); getHessian(x, H); x.scale((1.0 / beta)); obj /= theta; grad = grad * (beta / theta) + d1 * d1 * x; H = H * (beta2 / theta) + d1 * d1; // [r1,r2,rL,rU,Pinf,Dinf] = ... pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix, b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2, y, z1, z2, r1, r2, &Pinf, &Dinf ); //double center, Cinf, Cinf0; // [cL,cU,center,Cinf,Cinf0] = ... pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2, ¢er, &Cinf, &Cinf0); double fmeritnew = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU ); double step = CoinMin( stepx, stepz ); if (fmeritnew <= (1 - eta * step)*fmerit) { fail = false; break; } // Merit function didn"t decrease. // Restore variables to previous values. // (This introduces a little error, but save lots of space.) x = x - stepx * dx; y = y - stepz * dy; for (int k = 0; k < nlow; k++) { x1[low[k]] = x1[low[k]] - stepx * dx1[low[k]]; z1[low[k]] = z1[low[k]] - stepz * dz1[low[k]]; } for (int k = 0; k < nupp; k++) { x2[upp[k]] = x2[upp[k]] - stepx * dx2[upp[k]]; z2[upp[k]] = z2[upp[k]] - stepz * dz2[upp[k]]; } // Back-track. // If it"s the first time, // make stepx and stepz the same. if (nf == 1 && stepx != stepz) { stepx = step; } else if (nf < maxf) { stepx = stepx / 2; } stepz = stepx; } if (fail) { printf("\n Linesearch failed (nf too big)"); nfail += 1; } else { nfail = 0; } //------------------------------------------------------------------- // Set convergence measures. //-------------------------------------------------------------------- regx = (d1 * x).twoNorm(); regy = (d2 * y).twoNorm(); regterm = regx * regx + regy * regy; objreg = obj + 0.5 * regterm; objtrue = objreg * theta; bool primalfeas = Pinf <= featol; bool dualfeas = Dinf <= featol; bool complementary = Cinf0 <= opttol; bool enough = PDitns >= 4; // Prevent premature termination. bool converged = primalfeas & dualfeas & complementary & enough; //------------------------------------------------------------------- // Iteration log. //------------------------------------------------------------------- char str1[100], str2[100], str3[100], str4[100], str5[100]; sprintf(str1, "\n%3g%5.1f" , PDitns , log10(mu) ); sprintf(str2, "%8.5f%8.5f" , stepx , stepz ); if (stepx < 0.0001 || stepz < 0.0001) { sprintf(str2, " %6.1e %6.1e" , stepx , stepz ); } sprintf(str3, "%6.1f%6.1f" , log10(Pinf) , log10(Dinf)); sprintf(str4, "%6.1f%15.7e", log10(Cinf0), objtrue ); sprintf(str5, "%3d%8.1f" , nf , center ); if (center > 99999) { sprintf(str5, "%3d%8.1e" , nf , center ); } printf("%s%s%s%s%s", str1, str2, str3, str4, str5); if (direct) { // relax } else { printf(" %5.1f%7d%7.3f", log10(atolold), itncg, r3ratio); } //------------------------------------------------------------------- // Test for termination. //------------------------------------------------------------------- if (kminor) { printf( "\nStart of next minor itn...\n"); // keyboard; } if (converged) { printf("\n Converged"); break; } else if (PDitns >= maxitn) { printf("\n Too many iterations"); inform = 1; break; } else if (nfail >= maxfail) { printf("\n Too many linesearch failures"); inform = 2; break; } else { // Reduce mu, and reset certain residuals. double stepmu = CoinMin( stepx , stepz ); stepmu = CoinMin( stepmu, steptol ); double muold = mu; mu = mu - stepmu * mu; if (center >= bigcenter) mu = muold; // mutrad = mu0*(sum(Xz)/n); // 24 May 1998: Traditional value, but // mu = CoinMin(mu,mutrad ); // it seemed to decrease mu too much. mu = CoinMax(mu, mulast); // 13 Jun 1998: No need for smaller mu. // [cL,cU,center,Cinf,Cinf0] = ... pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2, ¢er, &Cinf, &Cinf0 ); fmerit = pdxxxmerit( nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU ); // Reduce atol for LSQR (and SYMMLQ). // NOW DONE AT TOP OF LOOP. atolold = atol; // if atol > atol2 // atolfac = (mu/mufirst)^0.25; // atol = CoinMax( atol*atolfac, atol2 ); // end // atol = CoinMin( atol, mu ); // 22 Jan 2001: a la Inexact Newton. // atol = CoinMin( atol, 0.5*mu ); // 30 Jan 2001: A bit tighter // If the linesearch took more than one function (nf > 1), // we assume the search direction needed more accuracy // (though this may be true only for LPs). // 12 Jun 1998: Ask for more accuracy if nf > 2. // 24 Nov 2000: Also if the steps are small. // 30 Jan 2001: Small steps might be ok with warm start. // 06 Feb 2001: Not necessarily. Reinstated tests in next line. if (nf > 2 || CoinMin( stepx, stepz ) <= 0.01) atol = atolold * 0.1; } //--------------------------------------------------------------------- // End of main loop. //--------------------------------------------------------------------- } for (int k = 0; k < nfix; k++) x[fix[k]] = bl[fix[k]]; z = z1; if (nupp > 0) z = z - z2; printf("\n\nmax |x| =%10.3f", x.infNorm() ); printf(" max |y| =%10.3f", y.infNorm() ); printf(" max |z| =%10.3f", z.infNorm() ); printf(" scaled"); x.scale(beta); y.scale(zeta); z.scale(zeta); // Unscale x, y, z. printf( "\nmax |x| =%10.3f", x.infNorm() ); printf(" max |y| =%10.3f", y.infNorm() ); printf(" max |z| =%10.3f", z.infNorm() ); printf(" unscaled\n"); time = CoinCpuTime() - time; char str1[100], str2[100]; sprintf(str1, "\nPDitns =%10g", PDitns ); sprintf(str2, "itns =%10d", CGitns ); // printf( [str1 " " solver str2] ); printf(" time =%10.1f\n", time); /* pdxxxdistrib( abs(x),abs(z) ); // Private function if (wait) keyboard; */ //----------------------------------------------------------------------- // End function pdco.m //----------------------------------------------------------------------- /* printf("Solution x values:\n\n"); for (int k=0; k 1; j--) printf(" %g to %g %d\n", thresh[j-1], thresh[j], counts[j]); printf(" Less than %g %d\n", thresh[2], counts[0]); return inform; } // LSQR void ClpPdco::lsqr() { } void ClpPdco::matVecMult( int mode, double* x_elts, double* y_elts) { pdcoStuff_->matVecMult(this, mode, x_elts, y_elts); } void ClpPdco::matVecMult( int mode, CoinDenseVector &x, double *y_elts) { double *x_elts = x.getElements(); matVecMult( mode, x_elts, y_elts); return; } void ClpPdco::matVecMult( int mode, CoinDenseVector &x, CoinDenseVector &y) { double *x_elts = x.getElements(); double *y_elts = y.getElements(); matVecMult( mode, x_elts, y_elts); return; } void ClpPdco::matVecMult( int mode, CoinDenseVector *x, CoinDenseVector *y) { double *x_elts = x->getElements(); double *y_elts = y->getElements(); matVecMult( mode, x_elts, y_elts); return; } void ClpPdco::matPrecon(double delta, double* x_elts, double* y_elts) { pdcoStuff_->matPrecon(this, delta, x_elts, y_elts); } void ClpPdco::matPrecon(double delta, CoinDenseVector &x, double *y_elts) { double *x_elts = x.getElements(); matPrecon(delta, x_elts, y_elts); return; } void ClpPdco::matPrecon(double delta, CoinDenseVector &x, CoinDenseVector &y) { double *x_elts = x.getElements(); double *y_elts = y.getElements(); matPrecon(delta, x_elts, y_elts); return; } void ClpPdco::matPrecon(double delta, CoinDenseVector *x, CoinDenseVector *y) { double *x_elts = x->getElements(); double *y_elts = y->getElements(); matPrecon(delta, x_elts, y_elts); return; } void ClpPdco::getBoundTypes(int *nlow, int *nupp, int *nfix, int **bptrs) { *nlow = numberColumns_; *nupp = *nfix = 0; int *low_ = (int *)malloc(numberColumns_ * sizeof(int)) ; for (int k = 0; k < numberColumns_; k++) low_[k] = k; bptrs[0] = low_; return; } double ClpPdco::getObj(CoinDenseVector &x) { return pdcoStuff_->getObj(this, x); } void ClpPdco::getGrad(CoinDenseVector &x, CoinDenseVector &g) { pdcoStuff_->getGrad(this, x, g); } void ClpPdco::getHessian(CoinDenseVector &x, CoinDenseVector &H) { pdcoStuff_->getHessian(this, x, H); } Clp-1.15.10/src/AbcWarmStart.cpp0000644000076600007660000001074712101105055014677 0ustar coincoin/* $Id: AbcWarmStart.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "CoinUtilsConfig.h" #include #include "AbcWarmStart.hpp" #include "CoinHelperFunctions.hpp" #include #include //############################################################################# void AbcWarmStart::setSize(int ns, int na) { CoinWarmStartBasis::setSize(ns,na); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } void AbcWarmStart::assignBasisStatus(int ns, int na, char*& sStat, char*& aStat) { CoinWarmStartBasis::assignBasisStatus(ns,na,sStat,aStat); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } AbcWarmStart::AbcWarmStart(AbcSimplex * model,int type) : CoinWarmStartBasis(model->numberColumns(),model->numberRows(), #ifdef CLP_WARMSTART reinterpret_cast(model->statusArray()), reinterpret_cast(model->statusArray()+model->numberColumns()) #else reinterpret_cast(model->statusArray()+model->maximumAbcNumberRows()), reinterpret_cast(model->statusArray()) #endif ), typeExtraInformation_(type), lengthExtraInformation_(0), extraInformation_(NULL), model_(model), organizer_(NULL), previousBasis_(NULL), nextBasis_(NULL), stamp_(-1), numberValidRows_(0) { assert (!typeExtraInformation_); } AbcWarmStart::AbcWarmStart(const AbcWarmStart& rhs) : CoinWarmStartBasis(rhs), typeExtraInformation_(rhs.typeExtraInformation_), lengthExtraInformation_(rhs.lengthExtraInformation_), extraInformation_(NULL), model_(rhs.model_), organizer_(rhs.organizer_), previousBasis_(NULL), nextBasis_(NULL), stamp_(-1), numberValidRows_(0) { if (typeExtraInformation_) extraInformation_=CoinCopyOfArray(rhs.extraInformation_,lengthExtraInformation_); } AbcWarmStart& AbcWarmStart::operator=(const AbcWarmStart& rhs) { if (this != &rhs) { CoinWarmStartBasis::operator=(rhs); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_ = rhs.typeExtraInformation_; lengthExtraInformation_ = rhs.lengthExtraInformation_; model_ = rhs.model_; organizer_ = rhs.organizer_; previousBasis_ = NULL; nextBasis_ = NULL; stamp_ = -1; numberValidRows_ = 0; if (typeExtraInformation_) extraInformation_=CoinCopyOfArray(rhs.extraInformation_,lengthExtraInformation_); } return *this; } // Resizes void AbcWarmStart::resize (int newNumberRows, int newNumberColumns) { if (newNumberRows==numArtificial_&&newNumberColumns==numStructural_) return; CoinWarmStartBasis::resize(newNumberRows,newNumberColumns); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } /* compressRows takes an ascending list of target indices without duplicates and removes them, compressing the artificialStatus_ array in place. It will fail spectacularly if the indices are not sorted. Use deleteRows if you need to preprocess the target indices to satisfy the conditions. */ void AbcWarmStart::compressRows (int tgtCnt, const int *tgts) { if (!tgtCnt) return; CoinWarmStartBasis::compressRows(tgtCnt,tgts); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } /* deleteRows takes an unordered list of target indices with duplicates and removes them from the basis. The strategy is to preprocesses the list into an ascending list without duplicates, suitable for compressRows. */ void AbcWarmStart::deleteRows (int rawTgtCnt, const int *rawTgts) { if (rawTgtCnt <= 0) return ; CoinWarmStartBasis::deleteRows(rawTgtCnt,rawTgts); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } // Deletes columns void AbcWarmStart::deleteColumns(int number, const int * which) { CoinWarmStartBasis::deleteColumns(number,which); delete [] extraInformation_; extraInformation_=NULL; typeExtraInformation_=0; } AbcWarmStart::AbcWarmStart() : CoinWarmStartBasis(), typeExtraInformation_(0), lengthExtraInformation_(0), extraInformation_(NULL), model_(NULL), organizer_(NULL), previousBasis_(NULL), nextBasis_(NULL), stamp_(-1), numberValidRows_(0) { } AbcWarmStart::~AbcWarmStart() { delete[] extraInformation_; } Clp-1.15.10/src/ClpNode.cpp0000644000076600007660000013551212101105055013667 0ustar coincoin/* $Id: ClpNode.cpp 1910 2013-01-27 02:00:13Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpNode.hpp" #include "ClpFactorization.hpp" #include "ClpDualRowSteepest.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNode::ClpNode () : branchingValue_(0.5), objectiveValue_(0.0), sumInfeasibilities_(0.0), estimatedSolution_(0.0), factorization_(NULL), weights_(NULL), status_(NULL), primalSolution_(NULL), dualSolution_(NULL), lower_(NULL), upper_(NULL), pivotVariables_(NULL), fixed_(NULL), sequence_(1), numberInfeasibilities_(0), depth_(0), numberFixed_(0), flags_(0), maximumFixed_(0), maximumRows_(0), maximumColumns_(0), maximumIntegers_(0) { branchState_.firstBranch = 0; branchState_.branch = 0; } //------------------------------------------------------------------- // Useful Constructor from model //------------------------------------------------------------------- ClpNode::ClpNode (ClpSimplex * model, const ClpNodeStuff * stuff, int depth) : branchingValue_(0.5), objectiveValue_(0.0), sumInfeasibilities_(0.0), estimatedSolution_(0.0), factorization_(NULL), weights_(NULL), status_(NULL), primalSolution_(NULL), dualSolution_(NULL), lower_(NULL), upper_(NULL), pivotVariables_(NULL), fixed_(NULL), sequence_(1), numberInfeasibilities_(0), depth_(0), numberFixed_(0), flags_(0), maximumFixed_(0), maximumRows_(0), maximumColumns_(0), maximumIntegers_(0) { branchState_.firstBranch = 0; branchState_.branch = 0; gutsOfConstructor(model, stuff, 0, depth); } //------------------------------------------------------------------- // Most of work of constructor from model //------------------------------------------------------------------- void ClpNode::gutsOfConstructor (ClpSimplex * model, const ClpNodeStuff * stuff, int arraysExist, int depth) { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int numberTotal = numberRows + numberColumns; int maximumTotal = maximumRows_ + maximumColumns_; depth_ = depth; // save stuff objectiveValue_ = model->objectiveValue() * model->optimizationDirection(); estimatedSolution_ = objectiveValue_; flags_ = 1; //say scaled if (!arraysExist) { maximumRows_ = CoinMax(maximumRows_, numberRows); maximumColumns_ = CoinMax(maximumColumns_, numberColumns); maximumTotal = maximumRows_ + maximumColumns_; assert (!factorization_); factorization_ = new ClpFactorization(*model->factorization(), numberRows); status_ = CoinCopyOfArrayPartial(model->statusArray(), maximumTotal, numberTotal); primalSolution_ = CoinCopyOfArrayPartial(model->solutionRegion(), maximumTotal, numberTotal); dualSolution_ = CoinCopyOfArrayPartial(model->djRegion(), maximumTotal, numberTotal); //? has duals as well? pivotVariables_ = CoinCopyOfArrayPartial(model->pivotVariable(), maximumRows_, numberRows); ClpDualRowSteepest* pivot = dynamic_cast< ClpDualRowSteepest*>(model->dualRowPivot()); if (pivot) { assert (!weights_); weights_ = new ClpDualRowSteepest(*pivot); } } else { if (arraysExist == 2) assert(lower_); if (numberRows <= maximumRows_ && numberColumns <= maximumColumns_) { CoinMemcpyN(model->statusArray(), numberTotal, status_); if (arraysExist == 1) { *factorization_ = *model->factorization(); CoinMemcpyN(model->solutionRegion(), numberTotal, primalSolution_); CoinMemcpyN(model->djRegion(), numberTotal, dualSolution_); //? has duals as well? ClpDualRowSteepest* pivot = dynamic_cast< ClpDualRowSteepest*>(model->dualRowPivot()); if (pivot) { if (weights_) { //if (weights_->numberRows()==pivot->numberRows()) { weights_->fill(*pivot); //} else { //delete weights_; //weights_ = new ClpDualRowSteepest(*pivot); //} } else { weights_ = new ClpDualRowSteepest(*pivot); } } CoinMemcpyN(model->pivotVariable(), numberRows, pivotVariables_); } else { CoinMemcpyN(model->primalColumnSolution(), numberColumns, primalSolution_); CoinMemcpyN(model->dualColumnSolution(), numberColumns, dualSolution_); flags_ = 0; CoinMemcpyN(model->dualRowSolution(), numberRows, dualSolution_ + numberColumns); } } else { // size has changed maximumRows_ = CoinMax(maximumRows_, numberRows); maximumColumns_ = CoinMax(maximumColumns_, numberColumns); maximumTotal = maximumRows_ + maximumColumns_; delete weights_; weights_ = NULL; delete [] status_; delete [] primalSolution_; delete [] dualSolution_; delete [] pivotVariables_; status_ = CoinCopyOfArrayPartial(model->statusArray(), maximumTotal, numberTotal); primalSolution_ = new double [maximumTotal*sizeof(double)]; dualSolution_ = new double [maximumTotal*sizeof(double)]; if (arraysExist == 1) { *factorization_ = *model->factorization(); // I think this is OK CoinMemcpyN(model->solutionRegion(), numberTotal, primalSolution_); CoinMemcpyN(model->djRegion(), numberTotal, dualSolution_); //? has duals as well? ClpDualRowSteepest* pivot = dynamic_cast< ClpDualRowSteepest*>(model->dualRowPivot()); if (pivot) { assert (!weights_); weights_ = new ClpDualRowSteepest(*pivot); } } else { CoinMemcpyN(model->primalColumnSolution(), numberColumns, primalSolution_); CoinMemcpyN(model->dualColumnSolution(), numberColumns, dualSolution_); flags_ = 0; CoinMemcpyN(model->dualRowSolution(), numberRows, dualSolution_ + numberColumns); } pivotVariables_ = new int [maximumRows_]; if (model->pivotVariable() && model->numberRows() == numberRows) CoinMemcpyN(model->pivotVariable(), numberRows, pivotVariables_); else CoinFillN(pivotVariables_, numberRows, -1); } } numberFixed_ = 0; const double * lower = model->columnLower(); const double * upper = model->columnUpper(); const double * solution = model->primalColumnSolution(); const char * integerType = model->integerInformation(); const double * columnScale = model->columnScale(); if (!flags_) columnScale = NULL; // as duals correct int iColumn; sequence_ = -1; double integerTolerance = stuff->integerTolerance_; double mostAway = 0.0; int bestPriority = COIN_INT_MAX; sumInfeasibilities_ = 0.0; numberInfeasibilities_ = 0; int nFix = 0; double gap = CoinMax(model->dualObjectiveLimit() - objectiveValue_, 1.0e-4); #define PSEUDO 3 #if PSEUDO==1||PSEUDO==2 // Column copy of matrix ClpPackedMatrix * matrix = model->clpScaledMatrix(); const double *objective = model->costRegion() ; if (!objective) { objective = model->objective(); //if (!matrix) matrix = dynamic_cast< ClpPackedMatrix*>(model->clpMatrix()); } else if (!matrix) { matrix = dynamic_cast< ClpPackedMatrix*>(model->clpMatrix()); } const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double direction = model->optimizationDirection(); const double * dual = dualSolution_ + numberColumns; #if PSEUDO==2 double * activeWeight = new double [numberRows]; const double * rowLower = model->rowLower(); const double * rowUpper = model->rowUpper(); const double * rowActivity = model->primalRowSolution(); double tolerance = 1.0e-6; for (int iRow = 0; iRow < numberRows; iRow++) { // could use pi to see if active or activity if (rowActivity[iRow] > rowUpper[iRow] - tolerance || rowActivity[iRow] < rowLower[iRow] + tolerance) { activeWeight[iRow] = 0.0; } else { activeWeight[iRow] = -1.0; } } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) { double value = solution[iColumn]; if (fabs(value - floor(value + 0.5)) > 1.0e-6) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = start + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; if (activeWeight[iRow] >= 0.0) activeWeight[iRow] += 1.0; } } } } for (int iRow = 0; iRow < numberRows; iRow++) { if (activeWeight[iRow] > 0.0) { // could use pi activeWeight[iRow] = 1.0 / activeWeight[iRow]; } else { activeWeight[iRow] = 0.0; } } #endif #endif const double * downPseudo = stuff->downPseudo_; const int * numberDown = stuff->numberDown_; const int * numberDownInfeasible = stuff->numberDownInfeasible_; const double * upPseudo = stuff->upPseudo_; const int * priority = stuff->priority_; const int * numberUp = stuff->numberUp_; const int * numberUpInfeasible = stuff->numberUpInfeasible_; int numberBeforeTrust = stuff->numberBeforeTrust_; int stateOfSearch = stuff->stateOfSearch_; int iInteger = 0; // weight at 1.0 is max min (CbcBranch was 0.8,0.1) (ClpNode was 0.9,0.9) #define WEIGHT_AFTER 0.9 #define WEIGHT_BEFORE 0.2 //Stolen from Constraint Integer Programming book (with epsilon change) #define WEIGHT_PRODUCT #ifdef WEIGHT_PRODUCT double smallChange = stuff->smallChange_; #endif #ifndef INFEAS_MULTIPLIER #define INFEAS_MULTIPLIER 1.0 #endif for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) { double value = solution[iColumn]; value = CoinMax(value, static_cast (lower[iColumn])); value = CoinMin(value, static_cast (upper[iColumn])); double nearest = floor(value + 0.5); if (fabs(value - nearest) > integerTolerance) { numberInfeasibilities_++; sumInfeasibilities_ += fabs(value - nearest); #if PSEUDO==1 || PSEUDO ==2 double upValue = 0.0; double downValue = 0.0; double value2 = direction * objective[iColumn]; //double dj2=value2; if (value2) { if (value2 > 0.0) upValue += 1.5 * value2; else downValue -= 1.5 * value2; } CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int iRow = row[j]; value2 = -dual[iRow]; if (value2) { value2 *= element[j]; //dj2 += value2; #if PSEUDO==2 assert (activeWeight[iRow] > 0.0 || fabs(dual[iRow]) < 1.0e-6); value2 *= activeWeight[iRow]; #endif if (value2 > 0.0) upValue += value2; else downValue -= value2; } } //assert (fabs(dj2)<1.0e-4); int nUp = numberUp[iInteger]; double upValue2 = (upPseudo[iInteger] / (1.0 + nUp)); // Extra for infeasible branches if (nUp) { double ratio = 1.0 + INFEAS_MULTIPLIER*static_cast(numberUpInfeasible[iInteger]) / static_cast(nUp); upValue2 *= ratio; } int nDown = numberDown[iInteger]; double downValue2 = (downPseudo[iInteger] / (1.0 + nDown)); if (nDown) { double ratio = 1.0 + INFEAS_MULTIPLIER*static_cast(numberDownInfeasible[iInteger]) / static_cast(nDown); downValue2 *= ratio; } //printf("col %d - downPi %g up %g, downPs %g up %g\n", // iColumn,upValue,downValue,upValue2,downValue2); upValue = CoinMax(0.1 * upValue, upValue2); downValue = CoinMax(0.1 * downValue, downValue2); //upValue = CoinMax(upValue,1.0e-8); //downValue = CoinMax(downValue,1.0e-8); upValue *= ceil(value) - value; downValue *= value - floor(value); double infeasibility; //if (depth>1000) //infeasibility = CoinMax(upValue,downValue)+integerTolerance; //else if (stateOfSearch <= 2) { // no solution infeasibility = (1.0 - WEIGHT_BEFORE) * CoinMax(upValue, downValue) + WEIGHT_BEFORE * CoinMin(upValue, downValue) + integerTolerance; } else { #ifndef WEIGHT_PRODUCT infeasibility = (1.0 - WEIGHT_AFTER) * CoinMax(upValue, downValue) + WEIGHT_AFTER * CoinMin(upValue, downValue) + integerTolerance; #else infeasibility = CoinMax(CoinMax(upValue, downValue), smallChange) * CoinMax(CoinMin(upValue, downValue), smallChange); #endif } estimatedSolution_ += CoinMin(upValue2, downValue2); #elif PSEUDO==3 int nUp = numberUp[iInteger]; int nDown = numberDown[iInteger]; // Extra 100% for infeasible branches double upValue = (ceil(value) - value) * (upPseudo[iInteger] / (1.0 + nUp)); if (nUp) { double ratio = 1.0 + INFEAS_MULTIPLIER*static_cast(numberUpInfeasible[iInteger]) / static_cast(nUp); upValue *= ratio; } double downValue = (value - floor(value)) * (downPseudo[iInteger] / (1.0 + nDown)); if (nDown) { double ratio = 1.0 + INFEAS_MULTIPLIER*static_cast(numberDownInfeasible[iInteger]) / static_cast(nDown); downValue *= ratio; } if (nUp < numberBeforeTrust || nDown < numberBeforeTrust) { upValue *= 10.0; downValue *= 10.0; } double infeasibility; //if (depth>1000) //infeasibility = CoinMax(upValue,downValue)+integerTolerance; //else if (stateOfSearch <= 2) { // no solution infeasibility = (1.0 - WEIGHT_BEFORE) * CoinMax(upValue, downValue) + WEIGHT_BEFORE * CoinMin(upValue, downValue) + integerTolerance; } else { #ifndef WEIGHT_PRODUCT infeasibility = (1.0 - WEIGHT_AFTER) * CoinMax(upValue, downValue) + WEIGHT_AFTER * CoinMin(upValue, downValue) + integerTolerance; #else infeasibility = CoinMax(CoinMax(upValue, downValue), smallChange) * CoinMax(CoinMin(upValue, downValue), smallChange); //infeasibility += CoinMin(upValue,downValue)*smallChange; #endif } //infeasibility = 0.1*CoinMax(upValue,downValue)+ //0.9*CoinMin(upValue,downValue) + integerTolerance; estimatedSolution_ += CoinMin(upValue, downValue); #else double infeasibility = fabs(value - nearest); #endif assert (infeasibility > 0.0); if (priority[iInteger] < bestPriority) { mostAway = 0.0; bestPriority = priority[iInteger]; } else if (priority[iInteger] > bestPriority) { infeasibility = 0.0; } if (infeasibility > mostAway) { mostAway = infeasibility; sequence_ = iColumn; branchingValue_ = value; branchState_.branch = 0; #if PSEUDO>0 if (upValue <= downValue) branchState_.firstBranch = 1; // up else branchState_.firstBranch = 0; // down #else if (value <= nearest) branchState_.firstBranch = 1; // up else branchState_.firstBranch = 0; // down #endif } } else if (model->getColumnStatus(iColumn) == ClpSimplex::atLowerBound) { bool fix = false; if (columnScale) { if (dualSolution_[iColumn] > gap * columnScale[iColumn]) fix = true; } else { if (dualSolution_[iColumn] > gap) fix = true; } if (fix) { nFix++; //printf("fixed %d to zero gap %g dj %g %g\n",iColumn, // gap,dualSolution_[iColumn], columnScale ? columnScale[iColumn]:1.0); model->setColumnStatus(iColumn, ClpSimplex::isFixed); } } else if (model->getColumnStatus(iColumn) == ClpSimplex::atUpperBound) { bool fix = false; if (columnScale) { if (-dualSolution_[iColumn] > gap * columnScale[iColumn]) fix = true; } else { if (-dualSolution_[iColumn] > gap) fix = true; } if (fix) { nFix++; //printf("fixed %d to one gap %g dj %g %g\n",iColumn, // gap,dualSolution_[iColumn], columnScale ? columnScale[iColumn]:1.0); model->setColumnStatus(iColumn, ClpSimplex::isFixed); } } iInteger++; } } //printf("Choosing %d inf %g pri %d\n", // sequence_,mostAway,bestPriority); #if PSEUDO == 2 delete [] activeWeight; #endif if (lower_) { // save bounds if (iInteger > maximumIntegers_) { delete [] lower_; delete [] upper_; maximumIntegers_ = iInteger; lower_ = new int [maximumIntegers_]; upper_ = new int [maximumIntegers_]; } iInteger = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) { lower_[iInteger] = static_cast (lower[iColumn]); upper_[iInteger] = static_cast (upper[iColumn]); iInteger++; } } } // Could omit save of fixed if doing full save of bounds if (sequence_ >= 0 && nFix) { if (nFix > maximumFixed_) { delete [] fixed_; fixed_ = new int [nFix]; maximumFixed_ = nFix; } numberFixed_ = 0; unsigned char * status = model->statusArray(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (status[iColumn] != status_[iColumn]) { if (solution[iColumn] <= lower[iColumn] + 2.0 * integerTolerance) { model->setColumnUpper(iColumn, lower[iColumn]); fixed_[numberFixed_++] = iColumn; } else { assert (solution[iColumn] >= upper[iColumn] - 2.0 * integerTolerance); model->setColumnLower(iColumn, upper[iColumn]); fixed_[numberFixed_++] = iColumn | 0x10000000; } } } //printf("%d fixed\n",numberFixed_); } } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNode::ClpNode (const ClpNode & ) { printf("ClpNode copy not implemented\n"); abort(); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNode::~ClpNode () { delete factorization_; delete weights_; delete [] status_; delete [] primalSolution_; delete [] dualSolution_; delete [] lower_; delete [] upper_; delete [] pivotVariables_; delete [] fixed_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNode & ClpNode::operator=(const ClpNode& rhs) { if (this != &rhs) { printf("ClpNode = not implemented\n"); abort(); } return *this; } // Create odd arrays void ClpNode::createArrays(ClpSimplex * model) { int numberColumns = model->numberColumns(); const char * integerType = model->integerInformation(); int iColumn; int numberIntegers = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) numberIntegers++; } if (numberIntegers > maximumIntegers_ || !lower_) { delete [] lower_; delete [] upper_; maximumIntegers_ = numberIntegers; lower_ = new int [numberIntegers]; upper_ = new int [numberIntegers]; } } // Clean up as crunch is different model void ClpNode::cleanUpForCrunch() { delete weights_; weights_ = NULL; } /* Applies node to model 0 - just tree bounds 1 - tree bounds and basis etc 2 - saved bounds and basis etc */ void ClpNode::applyNode(ClpSimplex * model, int doBoundsEtc ) { int numberColumns = model->numberColumns(); const double * lower = model->columnLower(); const double * upper = model->columnUpper(); if (doBoundsEtc < 2) { // current bound int way = branchState_.firstBranch; if (branchState_.branch > 0) way = 1 - way; if (!way) { // This should also do underlying internal bound model->setColumnUpper(sequence_, floor(branchingValue_)); } else { // This should also do underlying internal bound model->setColumnLower(sequence_, ceil(branchingValue_)); } // apply dj fixings for (int i = 0; i < numberFixed_; i++) { int iColumn = fixed_[i]; if ((iColumn & 0x10000000) != 0) { iColumn &= 0xfffffff; model->setColumnLower(iColumn, upper[iColumn]); } else { model->setColumnUpper(iColumn, lower[iColumn]); } } } else { // restore bounds assert (lower_); int iInteger = -1; const char * integerType = model->integerInformation(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (integerType[iColumn]) { iInteger++; if (lower_[iInteger] != static_cast (lower[iColumn])) model->setColumnLower(iColumn, lower_[iInteger]); if (upper_[iInteger] != static_cast (upper[iColumn])) model->setColumnUpper(iColumn, upper_[iInteger]); } } } if (doBoundsEtc && doBoundsEtc < 3) { //model->copyFactorization(*factorization_); model->copyFactorization(*factorization_); ClpDualRowSteepest* pivot = dynamic_cast< ClpDualRowSteepest*>(model->dualRowPivot()); if (pivot && weights_) { pivot->fill(*weights_); } int numberRows = model->numberRows(); int numberTotal = numberRows + numberColumns; CoinMemcpyN(status_, numberTotal, model->statusArray()); if (doBoundsEtc < 2) { CoinMemcpyN(primalSolution_, numberTotal, model->solutionRegion()); CoinMemcpyN(dualSolution_, numberTotal, model->djRegion()); CoinMemcpyN(pivotVariables_, numberRows, model->pivotVariable()); CoinMemcpyN(dualSolution_ + numberColumns, numberRows, model->dualRowSolution()); } else { CoinMemcpyN(primalSolution_, numberColumns, model->primalColumnSolution()); CoinMemcpyN(dualSolution_, numberColumns, model->dualColumnSolution()); CoinMemcpyN(dualSolution_ + numberColumns, numberRows, model->dualRowSolution()); if (model->columnScale()) { // See if just primal will work double * solution = model->primalColumnSolution(); const double * columnScale = model->columnScale(); int i; for (i = 0; i < numberColumns; i++) { solution[i] *= columnScale[i]; } } } model->setObjectiveValue(objectiveValue_); } } // Choose a new variable void ClpNode::chooseVariable(ClpSimplex * , ClpNodeStuff * /*info*/) { #if 0 int way = branchState_.firstBranch; if (branchState_.branch > 0) way = 1 - way; assert (!branchState_.branch); // We need to use pseudo costs to choose a variable int numberColumns = model->numberColumns(); #endif } // Fix on reduced costs int ClpNode::fixOnReducedCosts(ClpSimplex * ) { return 0; } /* Way for integer variable -1 down , +1 up */ int ClpNode::way() const { int way = branchState_.firstBranch; if (branchState_.branch > 0) way = 1 - way; return way == 0 ? -1 : +1; } // Return true if branch exhausted bool ClpNode::fathomed() const { return branchState_.branch >= 1 ; } // Change state of variable i.e. go other way void ClpNode::changeState() { branchState_.branch++; assert (branchState_.branch <= 2); } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNodeStuff::ClpNodeStuff () : integerTolerance_(1.0e-7), integerIncrement_(1.0e-8), smallChange_(1.0e-8), downPseudo_(NULL), upPseudo_(NULL), priority_(NULL), numberDown_(NULL), numberUp_(NULL), numberDownInfeasible_(NULL), numberUpInfeasible_(NULL), saveCosts_(NULL), nodeInfo_(NULL), large_(NULL), whichRow_(NULL), whichColumn_(NULL), #ifndef NO_FATHOM_PRINT handler_(NULL), #endif nBound_(0), saveOptions_(0), solverOptions_(0), maximumNodes_(0), numberBeforeTrust_(0), stateOfSearch_(0), nDepth_(-1), nNodes_(0), numberNodesExplored_(0), numberIterations_(0), presolveType_(0) #ifndef NO_FATHOM_PRINT ,startingDepth_(-1), nodeCalled_(-1) #endif { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNodeStuff::ClpNodeStuff (const ClpNodeStuff & rhs) : integerTolerance_(rhs.integerTolerance_), integerIncrement_(rhs.integerIncrement_), smallChange_(rhs.smallChange_), downPseudo_(NULL), upPseudo_(NULL), priority_(NULL), numberDown_(NULL), numberUp_(NULL), numberDownInfeasible_(NULL), numberUpInfeasible_(NULL), saveCosts_(NULL), nodeInfo_(NULL), large_(NULL), whichRow_(NULL), whichColumn_(NULL), #ifndef NO_FATHOM_PRINT handler_(rhs.handler_), #endif nBound_(0), saveOptions_(rhs.saveOptions_), solverOptions_(rhs.solverOptions_), maximumNodes_(rhs.maximumNodes_), numberBeforeTrust_(rhs.numberBeforeTrust_), stateOfSearch_(rhs.stateOfSearch_), nDepth_(rhs.nDepth_), nNodes_(rhs.nNodes_), numberNodesExplored_(rhs.numberNodesExplored_), numberIterations_(rhs.numberIterations_), presolveType_(rhs.presolveType_) #ifndef NO_FATHOM_PRINT ,startingDepth_(rhs.startingDepth_), nodeCalled_(rhs.nodeCalled_) #endif { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNodeStuff & ClpNodeStuff::operator=(const ClpNodeStuff& rhs) { if (this != &rhs) { integerTolerance_ = rhs.integerTolerance_; integerIncrement_ = rhs.integerIncrement_; smallChange_ = rhs.smallChange_; downPseudo_ = NULL; upPseudo_ = NULL; priority_ = NULL; numberDown_ = NULL; numberUp_ = NULL; numberDownInfeasible_ = NULL; numberUpInfeasible_ = NULL; saveCosts_ = NULL; nodeInfo_ = NULL; large_ = NULL; whichRow_ = NULL; whichColumn_ = NULL; nBound_ = 0; saveOptions_ = rhs.saveOptions_; solverOptions_ = rhs.solverOptions_; maximumNodes_ = rhs.maximumNodes_; numberBeforeTrust_ = rhs.numberBeforeTrust_; stateOfSearch_ = rhs.stateOfSearch_; int n = maximumNodes(); if (n) { for (int i = 0; i < n; i++) delete nodeInfo_[i]; } delete [] nodeInfo_; nodeInfo_ = NULL; nDepth_ = rhs.nDepth_; nNodes_ = rhs.nNodes_; numberNodesExplored_ = rhs.numberNodesExplored_; numberIterations_ = rhs.numberIterations_; presolveType_ = rhs.presolveType_; #ifndef NO_FATHOM_PRINT handler_ = rhs.handler_; startingDepth_ = rhs.startingDepth_; nodeCalled_ = rhs.nodeCalled_; #endif } return *this; } // Zaps stuff 1 - arrays, 2 ints, 3 both void ClpNodeStuff::zap(int type) { if ((type & 1) != 0) { downPseudo_ = NULL; upPseudo_ = NULL; priority_ = NULL; numberDown_ = NULL; numberUp_ = NULL; numberDownInfeasible_ = NULL; numberUpInfeasible_ = NULL; saveCosts_ = NULL; nodeInfo_ = NULL; large_ = NULL; whichRow_ = NULL; whichColumn_ = NULL; } if ((type & 2) != 0) { nBound_ = 0; saveOptions_ = 0; solverOptions_ = 0; maximumNodes_ = 0; numberBeforeTrust_ = 0; stateOfSearch_ = 0; nDepth_ = -1; nNodes_ = 0; presolveType_ = 0; numberNodesExplored_ = 0; numberIterations_ = 0; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNodeStuff::~ClpNodeStuff () { delete [] downPseudo_; delete [] upPseudo_; delete [] priority_; delete [] numberDown_; delete [] numberUp_; delete [] numberDownInfeasible_; delete [] numberUpInfeasible_; int n = maximumNodes(); if (n) { for (int i = 0; i < n; i++) delete nodeInfo_[i]; } delete [] nodeInfo_; #ifdef CLP_INVESTIGATE // Should be NULL - find out why not? assert (!saveCosts_); #endif delete [] saveCosts_; } // Return maximum number of nodes int ClpNodeStuff::maximumNodes() const { int n = 0; #if 0 if (nDepth_ != -1) { if ((solverOptions_ & 32) == 0) n = (1 << nDepth_); else if (nDepth_) n = 1; } assert (n == maximumNodes_ - (1 + nDepth_) || n == 0); #else if (nDepth_ != -1) { n = maximumNodes_ - (1 + nDepth_); assert (n > 0); } #endif return n; } // Return maximum space for nodes int ClpNodeStuff::maximumSpace() const { return maximumNodes_; } /* Fill with pseudocosts */ void ClpNodeStuff::fillPseudoCosts(const double * down, const double * up, const int * priority, const int * numberDown, const int * numberUp, const int * numberDownInfeasible, const int * numberUpInfeasible, int number) { delete [] downPseudo_; delete [] upPseudo_; delete [] priority_; delete [] numberDown_; delete [] numberUp_; delete [] numberDownInfeasible_; delete [] numberUpInfeasible_; downPseudo_ = CoinCopyOfArray(down, number); upPseudo_ = CoinCopyOfArray(up, number); priority_ = CoinCopyOfArray(priority, number); numberDown_ = CoinCopyOfArray(numberDown, number); numberUp_ = CoinCopyOfArray(numberUp, number); numberDownInfeasible_ = CoinCopyOfArray(numberDownInfeasible, number); numberUpInfeasible_ = CoinCopyOfArray(numberUpInfeasible, number); // scale for (int i = 0; i < number; i++) { int n; n = numberDown_[i]; if (n) downPseudo_[i] *= n; n = numberUp_[i]; if (n) upPseudo_[i] *= n; } } // Update pseudo costs void ClpNodeStuff::update(int way, int sequence, double change, bool feasible) { assert (numberDown_[sequence] >= numberDownInfeasible_[sequence]); assert (numberUp_[sequence] >= numberUpInfeasible_[sequence]); if (way < 0) { numberDown_[sequence]++; if (!feasible) numberDownInfeasible_[sequence]++; downPseudo_[sequence] += CoinMax(change, 1.0e-12); } else { numberUp_[sequence]++; if (!feasible) numberUpInfeasible_[sequence]++; upPseudo_[sequence] += CoinMax(change, 1.0e-12); } } //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpHashValue::ClpHashValue () : hash_(NULL), numberHash_(0), maxHash_(0), lastUsed_(-1) { } //------------------------------------------------------------------- // Useful Constructor from model //------------------------------------------------------------------- ClpHashValue::ClpHashValue (ClpSimplex * model) : hash_(NULL), numberHash_(0), maxHash_(0), lastUsed_(-1) { maxHash_ = 1000; int numberColumns = model->numberColumns(); const double * columnLower = model->columnLower(); const double * columnUpper = model->columnUpper(); int numberRows = model->numberRows(); const double * rowLower = model->rowLower(); const double * rowUpper = model->rowUpper(); const double * objective = model->objective(); CoinPackedMatrix * matrix = model->matrix(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); int i; int ipos; hash_ = new CoinHashLink[maxHash_]; for ( i = 0; i < maxHash_; i++ ) { hash_[i].value = -1.0e-100; hash_[i].index = -1; hash_[i].next = -1; } // Put in +0 hash_[0].value = 0.0; hash_[0].index = 0; numberHash_ = 1; /* * Initialize the hash table. Only the index of the first value that * hashes to a value is entered in the table; subsequent values that * collide with it are not entered. */ for ( i = 0; i < numberColumns; i++ ) { int length = columnLength[i]; CoinBigIndex start = columnStart[i]; for (CoinBigIndex i = start; i < start + length; i++) { double value = elementByColumn[i]; ipos = hash ( value); if ( hash_[ipos].index == -1 ) { hash_[ipos].index = numberHash_; numberHash_++; hash_[ipos].value = elementByColumn[i]; } } } /* * Now take care of the values that collided in the preceding loop, * Also do other stuff */ for ( i = 0; i < numberRows; i++ ) { if (numberHash_ * 2 > maxHash_) resize(true); double value; value = rowLower[i]; ipos = index(value); if (ipos < 0) addValue(value); value = rowUpper[i]; ipos = index(value); if (ipos < 0) addValue(value); } for ( i = 0; i < numberColumns; i++ ) { int length = columnLength[i]; CoinBigIndex start = columnStart[i]; if (numberHash_ * 2 > maxHash_) resize(true); double value; value = objective[i]; ipos = index(value); if (ipos < 0) addValue(value); value = columnLower[i]; ipos = index(value); if (ipos < 0) addValue(value); value = columnUpper[i]; ipos = index(value); if (ipos < 0) addValue(value); for (CoinBigIndex j = start; j < start + length; j++) { if (numberHash_ * 2 > maxHash_) resize(true); value = elementByColumn[j]; ipos = index(value); if (ipos < 0) addValue(value); } } resize(false); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpHashValue::ClpHashValue (const ClpHashValue & rhs) : hash_(NULL), numberHash_(rhs.numberHash_), maxHash_(rhs.maxHash_), lastUsed_(rhs.lastUsed_) { if (maxHash_) { CoinHashLink * newHash = new CoinHashLink[maxHash_]; int i; for ( i = 0; i < maxHash_; i++ ) { newHash[i].value = rhs.hash_[i].value; newHash[i].index = rhs.hash_[i].index; newHash[i].next = rhs.hash_[i].next; } } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpHashValue::~ClpHashValue () { delete [] hash_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpHashValue & ClpHashValue::operator=(const ClpHashValue& rhs) { if (this != &rhs) { numberHash_ = rhs.numberHash_; maxHash_ = rhs.maxHash_; lastUsed_ = rhs.lastUsed_; delete [] hash_; if (maxHash_) { CoinHashLink * newHash = new CoinHashLink[maxHash_]; int i; for ( i = 0; i < maxHash_; i++ ) { newHash[i].value = rhs.hash_[i].value; newHash[i].index = rhs.hash_[i].index; newHash[i].next = rhs.hash_[i].next; } } else { hash_ = NULL; } } return *this; } // Return index or -1 if not found int ClpHashValue::index(double value) const { if (!value) return 0; int ipos = hash ( value); int returnCode = -1; while ( hash_[ipos].index >= 0 ) { if (value == hash_[ipos].value) { returnCode = hash_[ipos].index; break; } else { int k = hash_[ipos].next; if ( k == -1 ) { break; } else { ipos = k; } } } return returnCode; } // Add value to list and return index int ClpHashValue::addValue(double value) { int ipos = hash ( value); assert (value != hash_[ipos].value); if (hash_[ipos].index == -1) { // can put in here hash_[ipos].index = numberHash_; numberHash_++; hash_[ipos].value = value; return numberHash_ - 1; } int k = hash_[ipos].next; while (k != -1) { ipos = k; k = hash_[ipos].next; } while ( true ) { ++lastUsed_; assert (lastUsed_ <= maxHash_); if ( hash_[lastUsed_].index == -1 ) { break; } } hash_[ipos].next = lastUsed_; hash_[lastUsed_].index = numberHash_; numberHash_++; hash_[lastUsed_].value = value; return numberHash_ - 1; } namespace { /* Originally a local static variable in ClpHashValue::hash. Local static variables are a problem when building DLLs on Windows, but file-local constants seem to be ok. -- lh, 101016 -- */ const int mmult_for_hash[] = { 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247, 241667, 239179, 236609, 233983, 231289, 228859, 226357, 223829, 221281, 218849, 216319, 213721, 211093, 208673, 206263, 203773, 201233, 198637, 196159, 193603, 191161, 188701, 186149, 183761, 181303, 178873, 176389, 173897, 171469, 169049, 166471, 163871, 161387, 158941, 156437, 153949, 151531, 149159, 146749, 144299, 141709, 139369, 136889, 134591, 132169, 129641, 127343, 124853, 122477, 120163, 117757, 115361, 112979, 110567, 108179, 105727, 103387, 101021, 98639, 96179, 93911, 91583, 89317, 86939, 84521, 82183, 79939, 77587, 75307, 72959, 70793, 68447, 66103 }; } int ClpHashValue::hash ( double value) const { union { double d; char c[8]; } v1; assert (sizeof(double) == 8); v1.d = value; int n = 0; int j; for ( j = 0; j < 8; ++j ) { int ichar = v1.c[j]; n += mmult_for_hash[j] * ichar; } return ( abs ( n ) % maxHash_ ); /* integer abs */ } void ClpHashValue::resize(bool increaseMax) { int newSize = increaseMax ? ((3 * maxHash_) >> 1) + 1000 : maxHash_; CoinHashLink * newHash = new CoinHashLink[newSize]; int i; for ( i = 0; i < newSize; i++ ) { newHash[i].value = -1.0e-100; newHash[i].index = -1; newHash[i].next = -1; } // swap CoinHashLink * oldHash = hash_; hash_ = newHash; int oldSize = maxHash_; maxHash_ = newSize; /* * Initialize the hash table. Only the index of the first value that * hashes to a value is entered in the table; subsequent values that * collide with it are not entered. */ int ipos; int n = 0; for ( i = 0; i < oldSize; i++ ) { if (oldHash[i].index >= 0) { ipos = hash ( oldHash[i].value); if ( hash_[ipos].index == -1 ) { hash_[ipos].index = n; n++; hash_[ipos].value = oldHash[i].value; // unmark oldHash[i].index = -1; } } } /* * Now take care of the values that collided in the preceding loop, * by finding some other entry in the table for them. * Since there are as many entries in the table as there are values, * there must be room for them. */ lastUsed_ = -1; for ( i = 0; i < oldSize; ++i ) { if (oldHash[i].index >= 0) { double value = oldHash[i].value; ipos = hash ( value); int k; while ( true ) { assert (value != hash_[ipos].value); k = hash_[ipos].next; if ( k == -1 ) { while ( true ) { ++lastUsed_; assert (lastUsed_ <= maxHash_); if ( hash_[lastUsed_].index == -1 ) { break; } } hash_[ipos].next = lastUsed_; hash_[lastUsed_].index = n; n++; hash_[lastUsed_].value = value; break; } else { ipos = k; } } } } assert (n == numberHash_); delete [] oldHash; } Clp-1.15.10/src/CoinAbcCommonFactorization.hpp0000644000076600007660000000561612101105055017555 0ustar coincoin/* $Id: CoinAbcCommonFactorization.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2000, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CoinAbcCommonFactorization_H #define CoinAbcCommonFactorization_H /* meaning of ABC_SMALL -1 force copies (and no tests) 0 force copy of U 2 force no copies (and no tests) */ #include "CoinAbcCommon.hpp" //#define DONT_USE_SLACKS //#define COIN_ONE_ETA_COPY 100 //#define COIN_FAC_NEW 1 #define INITIAL_AVERAGE 1.0 #define INITIAL_AVERAGE2 1.0 #define AVERAGE_SCALE_BACK 0.8 //#define SWITCHABLE_STATISTICS #ifndef SWITCHABLE_STATISTICS #define setStatistics(x) #define factorizationStatistics() (true) #else #define setStatistics(x) collectStatistics_=x #define factorizationStatistics() (collectStatistics_) #endif #include "CoinAbcDenseFactorization.hpp" class CoinPackedMatrix; class CoinFactorization; #define FACTORIZATION_STATISTICS 0 //1 typedef struct { double countInput_; double countAfterL_; double countAfterR_; double countAfterU_; double averageAfterL_; double averageAfterR_; double averageAfterU_; #if FACTORIZATION_STATISTICS double twiddleFactor1_; double twiddleFactor2_; #endif CoinSimplexInt numberCounts_; } CoinAbcStatistics; #if FACTORIZATION_STATISTICS #define twiddleFactor1S() (statistics.twiddleFactor1_) #define twiddleFactor2S() (statistics.twiddleFactor2_) #define twiddleFtranFactor1() (ftranTwiddleFactor1_) #define twiddleFtranFTFactor1() (ftranFTTwiddleFactor1_) #define twiddleBtranFactor1() (btranTwiddleFactor1_) #define twiddleFtranFactor2() (ftranTwiddleFactor2_) #define twiddleFtranFTFactor2() (ftranFTTwiddleFactor2_) #define twiddleBtranFactor2() (btranTwiddleFactor2_) #define twiddleBtranFullFactor1() (btranFullTwiddleFactor1_) #else #define twiddleFactor1S() (1.0) #define twiddleFactor2S() (1.0) #define twiddleFtranFactor1() (1.0) #define twiddleFtranFTFactor1() (1.0) #define twiddleBtranFactor1() (1.0) #define twiddleFtranFactor2() (1.0) #define twiddleFtranFTFactor2() (1.0) #define twiddleBtranFactor2() (1.0) #define twiddleBtranFullFactor1() (1.0) #endif #define ABC_FAC_GOT_LCOPY 4 #define ABC_FAC_GOT_RCOPY 8 #define ABC_FAC_GOT_UCOPY 16 #define ABC_FAC_GOT_SPARSE 32 typedef struct { CoinBigIndex next; CoinBigIndex start; CoinSimplexUnsignedInt stack; } CoinAbcStack; void CoinAbcDgetrs(char trans,int m, double * a, double * work); int CoinAbcDgetrf(int m, int n, double * a, int lda, int * ipiv #if ABC_PARALLEL==2 ,int parallelMode #endif ); void CoinAbcDgetrs(char trans,int m, long double * a, long double * work); int CoinAbcDgetrf(int m, int n, long double * a, int lda, int * ipiv #if ABC_PARALLEL==2 ,int parallelMode #endif ); #define SWAP_FACTOR 2 #define BLOCKING8 8 #define BLOCKING8X8 BLOCKING8*BLOCKING8 #endif Clp-1.15.10/src/ClpFactorization.hpp0000644000076600007660000003750511510657452015646 0ustar coincoin/* $Id: ClpFactorization.hpp 1665 2011-01-04 17:55:54Z 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 ClpFactorization_H #define ClpFactorization_H #include "CoinPragma.hpp" #include "CoinFactorization.hpp" class ClpMatrixBase; class ClpSimplex; class ClpNetworkBasis; class CoinOtherFactorization; #ifndef CLP_MULTIPLE_FACTORIZATIONS #define CLP_MULTIPLE_FACTORIZATIONS 4 #endif #ifdef CLP_MULTIPLE_FACTORIZATIONS #include "CoinDenseFactorization.hpp" #include "ClpSimplex.hpp" #endif #ifndef COIN_FAST_CODE #define COIN_FAST_CODE #endif /** This just implements CoinFactorization when an ClpMatrixBase object is passed. If a network then has a dummy CoinFactorization and a genuine ClpNetworkBasis object */ class ClpFactorization #ifndef CLP_MULTIPLE_FACTORIZATIONS : public CoinFactorization #endif { //friend class CoinFactorization; public: /**@name factorization */ //@{ /** When part of LP - given by basic variables. Actually does factorization. Arrays passed in have non negative value to say basic. If status is okay, basic variables have pivot row - this is only needed if increasingRows_ >1. Allows scaling If status is singular, then basic variables have pivot row and ones thrown out have -1 returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ int factorize (ClpSimplex * model, int solveType, bool valuesPass); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpFactorization(); /** Destructor */ ~ClpFactorization(); //@} /**@name Copy method */ //@{ /** The copy constructor from an CoinFactorization. */ ClpFactorization(const CoinFactorization&); /** The copy constructor. */ ClpFactorization(const ClpFactorization&, int denseIfSmaller = 0); #ifdef CLP_MULTIPLE_FACTORIZATIONS /** The copy constructor from an CoinOtherFactorization. */ ClpFactorization(const CoinOtherFactorization&); #endif ClpFactorization& operator=(const ClpFactorization&); //@} /* **** below here is so can use networkish basis */ /**@name rank one updates which do exist */ //@{ /** Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If checkBeforeModifying is true will do all accuracy checks before modifying factorization. Whether to set this depends on speed considerations. You could just do this on first iteration after factorization and thereafter re-factorize partial update already in U */ int replaceColumn ( const ClpSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, double pivotCheck , bool checkBeforeModifying = false, double acceptablePivot = 1.0e-8); //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ //@{ /** Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room region1 starts as zero and is zero at end */ int updateColumnFT ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2); /** Updates one column (FTRAN) from region2 region1 starts as zero and is zero at end */ int updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute = false) const; /** Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ int updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, CoinIndexedVector * regionSparse2, CoinIndexedVector * regionSparse3, bool noPermuteRegion3 = false) ; /// For debug (no statistics update) int updateColumnForDebug ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2, bool noPermute = false) const; /** Updates one column (BTRAN) from region2 region1 starts as zero and is zero at end */ int updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const; //@} #ifdef CLP_MULTIPLE_FACTORIZATIONS /**@name Lifted from CoinFactorization */ //@{ /// Total number of elements in factorization inline int numberElements ( ) const { if (coinFactorizationA_) return coinFactorizationA_->numberElements(); else return coinFactorizationB_->numberElements() ; } /// Returns address of permute region inline int *permute ( ) const { if (coinFactorizationA_) return coinFactorizationA_->permute(); else return coinFactorizationB_->permute() ; } /// Returns address of pivotColumn region (also used for permuting) inline int *pivotColumn ( ) const { if (coinFactorizationA_) return coinFactorizationA_->pivotColumn(); else return coinFactorizationB_->permute() ; } /// Maximum number of pivots between factorizations inline int maximumPivots ( ) const { if (coinFactorizationA_) return coinFactorizationA_->maximumPivots(); else return coinFactorizationB_->maximumPivots() ; } /// Set maximum number of pivots between factorizations inline void maximumPivots ( int value) { if (coinFactorizationA_) coinFactorizationA_->maximumPivots(value); else coinFactorizationB_->maximumPivots(value); } /// Returns number of pivots since factorization inline int pivots ( ) const { if (coinFactorizationA_) return coinFactorizationA_->pivots(); else return coinFactorizationB_->pivots() ; } /// Whether larger areas needed inline double areaFactor ( ) const { if (coinFactorizationA_) return coinFactorizationA_->areaFactor(); else return 0.0 ; } /// Set whether larger areas needed inline void areaFactor ( double value) { if (coinFactorizationA_) coinFactorizationA_->areaFactor(value); } /// Zero tolerance inline double zeroTolerance ( ) const { if (coinFactorizationA_) return coinFactorizationA_->zeroTolerance(); else return coinFactorizationB_->zeroTolerance() ; } /// Set zero tolerance inline void zeroTolerance ( double value) { if (coinFactorizationA_) coinFactorizationA_->zeroTolerance(value); else coinFactorizationB_->zeroTolerance(value); } /// Set tolerances to safer of existing and given void saferTolerances ( double zeroTolerance, double pivotTolerance); /** get sparse threshold */ inline int sparseThreshold ( ) const { if (coinFactorizationA_) return coinFactorizationA_->sparseThreshold(); else return 0 ; } /** Set sparse threshold */ inline void sparseThreshold ( int value) { if (coinFactorizationA_) coinFactorizationA_->sparseThreshold(value); } /// Returns status inline int status ( ) const { if (coinFactorizationA_) return coinFactorizationA_->status(); else return coinFactorizationB_->status() ; } /// Sets status inline void setStatus ( int value) { if (coinFactorizationA_) coinFactorizationA_->setStatus(value); else coinFactorizationB_->setStatus(value) ; } /// Returns number of dense rows inline int numberDense() const { if (coinFactorizationA_) return coinFactorizationA_->numberDense(); else return 0 ; } #if 1 /// Returns number in U area inline CoinBigIndex numberElementsU ( ) const { if (coinFactorizationA_) return coinFactorizationA_->numberElementsU(); else return -1 ; } /// Returns number in L area inline CoinBigIndex numberElementsL ( ) const { if (coinFactorizationA_) return coinFactorizationA_->numberElementsL(); else return -1 ; } /// Returns number in R area inline CoinBigIndex numberElementsR ( ) const { if (coinFactorizationA_) return coinFactorizationA_->numberElementsR(); else return 0 ; } #endif inline bool timeToRefactorize() const { if (coinFactorizationA_) { return (coinFactorizationA_->pivots() * 3 > coinFactorizationA_->maximumPivots() * 2 && coinFactorizationA_->numberElementsR() * 3 > (coinFactorizationA_->numberElementsL() + coinFactorizationA_->numberElementsU()) * 2 + 1000 && !coinFactorizationA_->numberDense()); } else { return coinFactorizationB_->pivots() > coinFactorizationB_->numberRows() / 2.45 + 20; } } /// Level of detail of messages inline int messageLevel ( ) const { if (coinFactorizationA_) return coinFactorizationA_->messageLevel(); else return 1 ; } /// Set level of detail of messages inline void messageLevel ( int value) { if (coinFactorizationA_) coinFactorizationA_->messageLevel(value); } /// Get rid of all memory inline void clearArrays() { if (coinFactorizationA_) coinFactorizationA_->clearArrays(); else if (coinFactorizationB_) coinFactorizationB_->clearArrays(); } /// Number of Rows after factorization inline int numberRows ( ) const { if (coinFactorizationA_) return coinFactorizationA_->numberRows(); else return coinFactorizationB_->numberRows() ; } /// Gets dense threshold inline int denseThreshold() const { if (coinFactorizationA_) return coinFactorizationA_->denseThreshold(); else return 0 ; } /// Sets dense threshold inline void setDenseThreshold(int value) { if (coinFactorizationA_) coinFactorizationA_->setDenseThreshold(value); } /// Pivot tolerance inline double pivotTolerance ( ) const { if (coinFactorizationA_) return coinFactorizationA_->pivotTolerance(); else if (coinFactorizationB_) return coinFactorizationB_->pivotTolerance(); return 1.0e-8 ; } /// Set pivot tolerance inline void pivotTolerance ( double value) { if (coinFactorizationA_) coinFactorizationA_->pivotTolerance(value); else if (coinFactorizationB_) coinFactorizationB_->pivotTolerance(value); } /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed inline void relaxAccuracyCheck(double value) { if (coinFactorizationA_) coinFactorizationA_->relaxAccuracyCheck(value); } /** Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ inline int persistenceFlag() const { if (coinFactorizationA_) return coinFactorizationA_->persistenceFlag(); else return 0 ; } inline void setPersistenceFlag(int value) { if (coinFactorizationA_) coinFactorizationA_->setPersistenceFlag(value); } /// Delete all stuff (leaves as after CoinFactorization()) inline void almostDestructor() { if (coinFactorizationA_) coinFactorizationA_->almostDestructor(); else if (coinFactorizationB_) coinFactorizationB_->clearArrays(); } /// Returns areaFactor but adjusted for dense inline double adjustedAreaFactor() const { if (coinFactorizationA_) return coinFactorizationA_->adjustedAreaFactor(); else return 0.0 ; } inline void setBiasLU(int value) { if (coinFactorizationA_) coinFactorizationA_->setBiasLU(value); } /// true if Forrest Tomlin update, false if PFI inline void setForrestTomlin(bool value) { if (coinFactorizationA_) coinFactorizationA_->setForrestTomlin(value); } /// Sets default values inline void setDefaultValues() { if (coinFactorizationA_) { // row activities have negative sign #ifndef COIN_FAST_CODE coinFactorizationA_->slackValue(-1.0); #endif coinFactorizationA_->zeroTolerance(1.0e-13); } } /// If nonzero force use of 1,dense 2,small 3,osl void forceOtherFactorization(int which); /// Get switch to osl if number rows <= this inline int goOslThreshold() const { return goOslThreshold_; } /// Set switch to osl if number rows <= this inline void setGoOslThreshold(int value) { goOslThreshold_ = value; } /// Get switch to dense if number rows <= this inline int goDenseThreshold() const { return goDenseThreshold_; } /// Set switch to dense if number rows <= this inline void setGoDenseThreshold(int value) { goDenseThreshold_ = value; } /// Get switch to small if number rows <= this inline int goSmallThreshold() const { return goSmallThreshold_; } /// Set switch to small if number rows <= this inline void setGoSmallThreshold(int value) { goSmallThreshold_ = value; } /// Go over to dense or small code if small enough void goDenseOrSmall(int numberRows) ; /// Sets factorization void setFactorization(ClpFactorization & factorization); /// Return 1 if dense code inline int isDenseOrSmall() const { return coinFactorizationB_ ? 1 : 0; } #else inline bool timeToRefactorize() const { return (pivots() * 3 > maximumPivots() * 2 && numberElementsR() * 3 > (numberElementsL() + numberElementsU()) * 2 + 1000 && !numberDense()); } /// Sets default values inline void setDefaultValues() { // row activities have negative sign #ifndef COIN_FAST_CODE slackValue(-1.0); #endif zeroTolerance(1.0e-13); } /// Go over to dense code inline void goDense() {} #endif //@} /**@name other stuff */ //@{ /** makes a row copy of L for speed and to allow very sparse problems */ void goSparse(); /// Cleans up i.e. gets rid of network basis void cleanUp(); /// Says whether to redo pivot order bool needToReorder() const; #ifndef SLIM_CLP /// Says if a network basis inline bool networkBasis() const { return (networkBasis_ != NULL); } #else /// Says if a network basis inline bool networkBasis() const { return false; } #endif /// Fills weighted row list void getWeights(int * weights) const; //@} ////////////////// data ////////////////// private: /**@name data */ //@{ /// Pointer to network basis #ifndef SLIM_CLP ClpNetworkBasis * networkBasis_; #endif #ifdef CLP_MULTIPLE_FACTORIZATIONS /// Pointer to CoinFactorization CoinFactorization * coinFactorizationA_; /// Pointer to CoinOtherFactorization CoinOtherFactorization * coinFactorizationB_; #ifdef CLP_REUSE_ETAS /// Pointer to model ClpSimplex * model_; #endif /// If nonzero force use of 1,dense 2,small 3,osl int forceB_; /// Switch to osl if number rows <= this int goOslThreshold_; /// Switch to small if number rows <= this int goSmallThreshold_; /// Switch to dense if number rows <= this int goDenseThreshold_; #endif //@} }; #endif Clp-1.15.10/src/ClpConstraintLinear.hpp0000644000076600007660000000631211510657452016301 0ustar coincoin/* $Id: ClpConstraintLinear.hpp 1665 2011-01-04 17:55:54Z 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). #ifndef ClpConstraintLinear_H #define ClpConstraintLinear_H #include "ClpConstraint.hpp" //############################################################################# /** Linear Constraint Class */ class ClpConstraintLinear : public ClpConstraint { public: ///@name Stuff //@{ /** Fills gradient. If Linear 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 nonlinear columns to 1. Returns number of nonlinear 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; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpConstraintLinear(); /// Constructor from constraint ClpConstraintLinear(int row, int numberCoefficients, int numberColumns, const int * column, const double * element); /** Copy constructor . */ ClpConstraintLinear(const ClpConstraintLinear & rhs); /// Assignment operator ClpConstraintLinear & operator=(const ClpConstraintLinear& rhs); /// Destructor virtual ~ClpConstraintLinear (); /// Clone virtual ClpConstraint * clone() const; //@} ///@name Gets and sets //@{ /// Number of coefficients virtual int numberCoefficients() const; /// Number of columns in linear constraint inline int numberColumns() const { return numberColumns_; } /// Columns inline const int * column() const { return column_; } /// Coefficients inline const double * coefficient() const { return coefficient_; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Column int * column_; /// Coefficients double * coefficient_; /// Useful to have number of columns about int numberColumns_; /// Number of coefficients int numberCoefficients_; //@} }; #endif Clp-1.15.10/src/AbcPrimalColumnPivot.hpp0000644000076600007660000001137412101105055016401 0ustar coincoin/* $Id: AbcPrimalColumnPivot.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcPrimalColumnPivot_H #define AbcPrimalColumnPivot_H #include "AbcCommon.hpp" class AbcSimplex; class CoinIndexedVector; //############################################################################# /** Primal Column Pivot Abstract Base Class Abstract Base Class for describing an interface to an algorithm to choose column pivot in primal simplex algorithm. For some algorithms e.g. Dantzig choice then some functions may be null. For Dantzig the only one of any importance is pivotColumn. If you wish to inherit from this look at AbcPrimalColumnDantzig.cpp as that is simplest version. */ class AbcPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none Normally updates reduced costs using result of last iteration before selecting incoming column. The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row Inside pivotColumn the pivotRow_ and reduced cost from last iteration are also used. So in the simplest case i.e. feasible we compute the row of the tableau corresponding to last pivot and add a multiple of this to current reduced costs. We can use other arrays to help updates */ virtual int pivotColumn(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1) = 0; /// Updates weights - part 1 (may be empty) virtual void updateWeights(CoinIndexedVector * input); /** Saves any weights round factorization as pivot rows may change Will be empty unless steepest edge (will save model) May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) forces some initialization e.g. weights Also sets model */ virtual void saveWeights(AbcSimplex * model, int mode) = 0; /** Signals pivot row choice: -2 (default) - use normal pivot row choice -1 to numberRows-1 - use this (will be checked) way should be -1 to go to lower bound, +1 to upper bound */ virtual int pivotRow(double & way) { way = 0; return -2; } /// Gets rid of all arrays (may be empty) virtual void clearArrays(); /// Returns true if would not find any column virtual bool looksOptimal() const { return looksOptimal_; } /// Sets optimality flag (for advanced use) virtual void setLooksOptimal(bool flag) { looksOptimal_ = flag; } //@} ///@name Constructors and destructors //@{ /// Default Constructor AbcPrimalColumnPivot(); /// Copy constructor AbcPrimalColumnPivot(const AbcPrimalColumnPivot &); /// Assignment operator AbcPrimalColumnPivot & operator=(const AbcPrimalColumnPivot& rhs); /// Destructor virtual ~AbcPrimalColumnPivot (); /// Clone virtual AbcPrimalColumnPivot * clone(bool copyData = true) const = 0; //@} ///@name Other //@{ /// Returns model inline AbcSimplex * model() { return model_; } /// Sets model inline void setModel(AbcSimplex * newmodel) { model_ = newmodel; } /// Returns type (above 63 is extra information) inline int type() { return type_; } /** Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ virtual int numberSprintColumns(int & numberIterations) const; /// Switch off sprint idea virtual void switchOffSprint(); /// Called when maximum pivots changes virtual void maximumPivotsChanged() {} //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Pointer to model AbcSimplex * model_; /// Type of column pivot algorithm int type_; /// Says if looks optimal (normally computed) bool looksOptimal_; //@} }; #ifndef CLP_PRIMAL_SLACK_MULTIPLIER #define CLP_PRIMAL_SLACK_MULTIPLIER 1.01 #endif #endif Clp-1.15.10/src/ClpDualRowDantzig.hpp0000644000076600007660000000367011510657452015724 0ustar coincoin/* $Id: ClpDualRowDantzig.hpp 1665 2011-01-04 17:55:54Z 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 ClpDualRowDantzig_H #define ClpDualRowDantzig_H #include "ClpDualRowPivot.hpp" //############################################################################# /** Dual Row Pivot Dantzig Algorithm Class This is simplest choice - choose largest infeasibility */ class ClpDualRowDantzig : public ClpDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow(); /** Updates weights and returns pivot alpha. Also does FT update */ virtual double updateWeights(CoinIndexedVector * input, CoinIndexedVector * spare, CoinIndexedVector * spare2, CoinIndexedVector * updatedColumn); /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ virtual void updatePrimalSolution(CoinIndexedVector * input, double theta, double & changeInObjective); //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpDualRowDantzig(); /// Copy constructor ClpDualRowDantzig(const ClpDualRowDantzig &); /// Assignment operator ClpDualRowDantzig & operator=(const ClpDualRowDantzig& rhs); /// Destructor virtual ~ClpDualRowDantzig (); /// Clone virtual ClpDualRowPivot * clone(bool copyData = true) const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data //@} }; #endif Clp-1.15.10/src/ClpDummyMatrix.cpp0000644000076600007660000002007011510657452015272 0ustar coincoin/* $Id: ClpDummyMatrix.cpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). #include #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpDummyMatrix.hpp" #include "ClpFactorization.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDummyMatrix::ClpDummyMatrix () : ClpMatrixBase() { setType(14); numberRows_ = 0; numberColumns_ = 0; numberElements_ = 0; } /* Constructor from data */ ClpDummyMatrix::ClpDummyMatrix(int numberColumns, int numberRows, int numberElements) : ClpMatrixBase() { setType(14); numberRows_ = numberRows; numberColumns_ = numberColumns; numberElements_ = numberElements; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDummyMatrix::ClpDummyMatrix (const ClpDummyMatrix & rhs) : ClpMatrixBase(rhs) { numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; numberElements_ = rhs.numberElements_; } ClpDummyMatrix::ClpDummyMatrix (const CoinPackedMatrix & ) : ClpMatrixBase() { std::cerr << "Constructor from CoinPackedMatrix nnot supported - ClpDummyMatrix" << std::endl; abort(); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDummyMatrix::~ClpDummyMatrix () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDummyMatrix & ClpDummyMatrix::operator=(const ClpDummyMatrix& rhs) { if (this != &rhs) { ClpMatrixBase::operator=(rhs); numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; numberElements_ = rhs.numberElements_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpDummyMatrix::clone() const { return new ClpDummyMatrix(*this); } /* Returns a new matrix in reverse order without gaps */ ClpMatrixBase * ClpDummyMatrix::reverseOrderedCopy() const { std::cerr << "reverseOrderedCopy not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } //unscaled versions void ClpDummyMatrix::times(double , const double * , double * ) const { std::cerr << "times not supported - ClpDummyMatrix" << std::endl; abort(); } void ClpDummyMatrix::transposeTimes(double , const double * , double * ) const { std::cerr << "transposeTimes not supported - ClpDummyMatrix" << std::endl; abort(); } void ClpDummyMatrix::times(double , const double * , double * , const double * , const double * ) const { std::cerr << "timesnot supported - ClpDummyMatrix" << std::endl; abort(); } void ClpDummyMatrix::transposeTimes( double, const double * , double * , const double * , const double * ) const { std::cerr << "transposeTimesnot supported - ClpDummyMatrix" << std::endl; abort(); } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpDummyMatrix::transposeTimes(const ClpSimplex * , double , const CoinIndexedVector * , CoinIndexedVector * , CoinIndexedVector * ) const { std::cerr << "transposeTimes not supported - ClpDummyMatrix" << std::endl; abort(); } /* Return x *A in z but just for indices in y */ void ClpDummyMatrix::subsetTransposeTimes(const ClpSimplex * , const CoinIndexedVector * , const CoinIndexedVector * , CoinIndexedVector * ) const { std::cerr << "subsetTransposeTimes not supported - ClpDummyMatrix" << std::endl; abort(); } /// returns number of elements in column part of basis, CoinBigIndex ClpDummyMatrix::countBasis(const int * , int & ) { std::cerr << "countBasis not supported - ClpDummyMatrix" << std::endl; abort(); return 0; } void ClpDummyMatrix::fillBasis(ClpSimplex * , const int * , int & , int * , int * , int * , int * , CoinFactorizationDouble * ) { std::cerr << "fillBasis not supported - ClpDummyMatrix" << std::endl; abort(); } /* Unpacks a column into an CoinIndexedvector */ void ClpDummyMatrix::unpack(const ClpSimplex * , CoinIndexedVector * , int ) const { std::cerr << "unpack not supported - ClpDummyMatrix" << std::endl; abort(); } /* Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ void ClpDummyMatrix::unpackPacked(ClpSimplex * , CoinIndexedVector * , int ) const { std::cerr << "unpackPacked not supported - ClpDummyMatrix" << std::endl; abort(); } /* Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ void ClpDummyMatrix::add(const ClpSimplex * , CoinIndexedVector * , int , double ) const { std::cerr << "add not supported - ClpDummyMatrix" << std::endl; abort(); } /* Adds multiple of a column into an array */ void ClpDummyMatrix::add(const ClpSimplex * , double * , int , double ) const { std::cerr << "add not supported - ClpDummyMatrix" << std::endl; abort(); } // Return a complete CoinPackedMatrix CoinPackedMatrix * ClpDummyMatrix::getPackedMatrix() const { std::cerr << "getPackedMatrix not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } /* A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ const double * ClpDummyMatrix::getElements() const { std::cerr << "getElements not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } const CoinBigIndex * ClpDummyMatrix::getVectorStarts() const { std::cerr << "getVectorStarts not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } /* The lengths of the major-dimension vectors. */ const int * ClpDummyMatrix::getVectorLengths() const { std::cerr << "get VectorLengths not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } /* Delete the columns whose indices are listed in indDel. */ void ClpDummyMatrix::deleteCols(const int , const int * ) { std::cerr << "deleteCols not supported - ClpDummyMatrix" << std::endl; abort(); } /* Delete the rows whose indices are listed in indDel. */ void ClpDummyMatrix::deleteRows(const int , const int * ) { std::cerr << "deleteRows not supported - ClpDummyMatrix" << std::endl; abort(); } const int * ClpDummyMatrix::getIndices() const { std::cerr << "getIndices not supported - ClpDummyMatrix" << std::endl; abort(); return NULL; } Clp-1.15.10/src/AbcDualRowDantzig.hpp0000644000076600007660000000523312101105055015650 0ustar coincoin/* $Id: AbcDualRowDantzig.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcDualRowDantzig_H #define AbcDualRowDantzig_H #include "AbcDualRowPivot.hpp" //############################################################################# /** Dual Row Pivot Dantzig Algorithm Class This is simplest choice - choose largest infeasibility */ class AbcDualRowDantzig : public AbcDualRowPivot { public: ///@name Algorithmic methods //@{ /// Returns pivot row, -1 if none virtual int pivotRow(); /** Updates weights and returns pivot alpha. Also does FT update */ virtual double updateWeights(CoinIndexedVector & input,CoinIndexedVector & updatedColumn); virtual double updateWeights1(CoinIndexedVector & input,CoinIndexedVector & updateColumn); virtual void updateWeightsOnly(CoinIndexedVector & /*input*/) {}; /// Actually updates weights virtual void updateWeights2(CoinIndexedVector & input,CoinIndexedVector & /*updateColumn*/) {input.clear();}; /** Updates primal solution (and maybe list of candidates) Uses input vector which it deletes Computes change in objective function */ virtual void updatePrimalSolution(CoinIndexedVector & input, double theta); /** Saves any weights round factorization as pivot rows may change Will be empty unless steepest edge (will save model) May also recompute infeasibility stuff 1) before factorization 2) after good factorization (if weights empty may initialize) 3) after something happened but no factorization (e.g. check for infeasible) 4) as 2 but restore weights from previous snapshot 5) for strong branching - initialize , infeasibilities */ virtual void saveWeights(AbcSimplex * model, int mode); /// Recompute infeasibilities virtual void recomputeInfeasibilities(); //@} ///@name Constructors and destructors //@{ /// Default Constructor AbcDualRowDantzig(); /// Copy constructor AbcDualRowDantzig(const AbcDualRowDantzig &); /// Assignment operator AbcDualRowDantzig & operator=(const AbcDualRowDantzig& rhs); /// Destructor virtual ~AbcDualRowDantzig (); /// Clone virtual AbcDualRowPivot * clone(bool copyData = true) const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// infeasibility array (just for infeasible rows) CoinIndexedVector * infeasible_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyWssmpKKT.hpp0000644000076600007660000000413011510657452016203 0ustar coincoin/* $Id: ClpCholeskyWssmpKKT.hpp 1665 2011-01-04 17:55:54Z 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 ClpCholeskyWssmpKKT_H #define ClpCholeskyWssmpKKT_H #include "ClpCholeskyBase.hpp" class ClpMatrixBase; class ClpCholeskyDense; /** WssmpKKT class for Clp Cholesky factorization */ class ClpCholeskyWssmpKKT : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ //@{ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /** Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const double * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (double * region) ; /** Uses factorization to solve. - given as if KKT. region1 is rows+columns, region2 is rows */ virtual void solveKKT (double * region1, double * region2, const double * diagonal, double diagonalScaleFactor); //@} /**@name Constructors, destructor */ //@{ /** Constructor which has dense columns activated. Default is off. */ ClpCholeskyWssmpKKT(int denseThreshold = -1); /** Destructor */ virtual ~ClpCholeskyWssmpKKT(); // Copy ClpCholeskyWssmpKKT(const ClpCholeskyWssmpKKT&); // Assignment ClpCholeskyWssmpKKT& operator=(const ClpCholeskyWssmpKKT&); /// Clone virtual ClpCholeskyBase * clone() const ; //@} private: /**@name Data members */ //@{ //@} }; #endif Clp-1.15.10/src/config_clp.h.in0000644000076600007660000000054012101105055014510 0ustar coincoin/* src/config_clp.h.in. */ /* Define to 1, 2, 3, or 4 if Aboca should be build. */ #undef CLP_HAS_ABC /* Version number of project */ #undef CLP_VERSION /* Major Version number of project */ #undef CLP_VERSION_MAJOR /* Minor Version number of project */ #undef CLP_VERSION_MINOR /* Release Version number of project */ #undef CLP_VERSION_RELEASE Clp-1.15.10/src/CoinAbcOrderedFactorization5.cpp0000644000076600007660000000107712101105055017766 0ustar coincoin/* $Id: CoinAbcOrderedFactorization5.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -1 #define ABC_ORDERED_FACTORIZATION #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization5.cpp" #endif Clp-1.15.10/src/IdiSolve.cpp0000644000076600007660000016131112017705027014070 0ustar coincoin/* $Id: IdiSolve.cpp 1878 2012-08-30 15:43:19Z 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). #include "CoinPragma.hpp" #include #include #include #include #include "CoinHelperFunctions.hpp" #include "Idiot.hpp" #define FIT #ifdef FIT #define HISTORY 8 #else #define HISTORY 7 #endif #define NSOLVE HISTORY-1 static void solveSmall(int nsolve, double **aIn, double **a, double * b) { int i, j; /* copy */ for (i = 0; i < nsolve; i++) { for (j = 0; j < nsolve; j++) { a[i][j] = aIn[i][j]; } } for (i = 0; i < nsolve; i++) { /* update using all previous */ double diagonal; int j; for (j = i; j < nsolve; j++) { int k; double value = a[i][j]; for (k = 0; k < i; k++) { value -= a[k][i] * a[k][j]; } a[i][j] = value; } diagonal = a[i][i]; if (diagonal < 1.0e-20) { diagonal = 0.0; } else { diagonal = 1.0 / sqrt(diagonal); } a[i][i] = diagonal; for (j = i + 1; j < nsolve; j++) { a[i][j] *= diagonal; } } /* update */ for (i = 0; i < nsolve; i++) { int j; double value = b[i]; for (j = 0; j < i; j++) { value -= b[j] * a[j][i]; } value *= a[i][i]; b[i] = value; } for (i = nsolve - 1; i >= 0; i--) { int j; double value = b[i]; for (j = i + 1; j < nsolve; j++) { value -= b[j] * a[i][j]; } value *= a[i][i]; b[i] = value; } } IdiotResult Idiot::objval(int nrows, int ncols, double * rowsol , double * colsol, double * pi, double * /*djs*/, const double * cost , const double * /*rowlower*/, const double * rowupper, const double * /*lower*/, const double * /*upper*/, const double * elemnt, const int * row, const CoinBigIndex * columnStart, const int * length, int extraBlock, int * rowExtra, double * solExtra, double * elemExtra, double * /*upperExtra*/, double * costExtra, double weight) { IdiotResult result; double objvalue = 0.0; double sum1 = 0.0, sum2 = 0.0; int i; for (i = 0; i < nrows; i++) { rowsol[i] = -rowupper[i]; } for (i = 0; i < ncols; i++) { CoinBigIndex j; double value = colsol[i]; if (value) { objvalue += value * cost[i]; if (elemnt) { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += elemnt[j] * value; } } else { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += value; } } } } /* adjust to make as feasible as possible */ /* no */ if (extraBlock) { for (i = 0; i < extraBlock; i++) { double element = elemExtra[i]; int irow = rowExtra[i]; objvalue += solExtra[i] * costExtra[i]; rowsol[irow] += solExtra[i] * element; } } for (i = 0; i < nrows; i++) { double value = rowsol[i]; sum1 += fabs(value); sum2 += value * value; pi[i] = -2.0 * weight * value; } result.infeas = sum1; result.objval = objvalue; result.weighted = objvalue + weight * sum2; result.sumSquared = sum2; return result; } IdiotResult Idiot::IdiSolve( int nrows, int ncols, double * COIN_RESTRICT rowsol , double * COIN_RESTRICT colsol, double * COIN_RESTRICT pi, double * COIN_RESTRICT djs, const double * COIN_RESTRICT origcost , double * COIN_RESTRICT rowlower, double * COIN_RESTRICT rowupper, const double * COIN_RESTRICT lower, const double * COIN_RESTRICT upper, const double * COIN_RESTRICT elemnt, const int * row, const CoinBigIndex * columnStart, const int * length, double * COIN_RESTRICT lambda, int maxIts, double mu, double drop, double maxmin, double offset, int strategy, double djTol, double djExit, double djFlag, CoinThreadRandom * randomNumberGenerator) { IdiotResult result; int i, j, k, iter; double value = 0.0, objvalue = 0.0, weightedObj = 0.0; double tolerance = 1.0e-8; double * history[HISTORY+1]; int ncolx; int nChange; int extraBlock = 0; int * rowExtra = NULL; double * COIN_RESTRICT solExtra = NULL; double * COIN_RESTRICT elemExtra = NULL; double * COIN_RESTRICT upperExtra = NULL; double * COIN_RESTRICT costExtra = NULL; double * COIN_RESTRICT useCostExtra = NULL; double * COIN_RESTRICT saveExtra = NULL; double * COIN_RESTRICT cost = NULL; double saveValue = 1.0e30; double saveOffset = offset; double useOffset = offset; /*#define NULLVECTOR*/ #ifndef NULLVECTOR int nsolve = NSOLVE; #else int nsolve = NSOLVE + 1; /* allow for null vector */ #endif int nflagged; double * COIN_RESTRICT thetaX; double * COIN_RESTRICT djX; double * COIN_RESTRICT bX; double * COIN_RESTRICT vX; double ** aX; double **aworkX; double ** allsum; double * COIN_RESTRICT saveSol = 0; const double * COIN_RESTRICT useCost = cost; double bestSol = 1.0e60; double weight = 0.5 / mu; char * statusSave = new char[2*ncols]; char * statusWork = statusSave + ncols; #define DJTEST 5 double djSave[DJTEST]; double largestDj = 0.0; double smallestDj = 1.0e60; double maxDj = 0.0; int doFull = 0; #define SAVEHISTORY 10 #define EVERY (2*SAVEHISTORY) #define AFTER SAVEHISTORY*(HISTORY+1) #define DROP 5 double after = AFTER; double obj[DROP]; double kbad = 0, kgood = 0; if (strategy & 128) after = 999999; /* no acceleration at all */ for (i = 0; i < DROP; i++) { obj[i] = 1.0e70; } //#define FOUR_GOES 2 #ifdef FOUR_GOES double * COIN_RESTRICT pi2 = new double [3*nrows]; double * COIN_RESTRICT rowsol2 = new double [3*nrows]; double * COIN_RESTRICT piX[4]; double * COIN_RESTRICT rowsolX[4]; int startsX[2][5]; int nChangeX[4]; double maxDjX[4]; double objvalueX[4]; int nflaggedX[4]; piX[0]=pi; piX[1]=pi2; piX[2]=pi2+nrows; piX[3]=piX[2]+nrows; rowsolX[0]=rowsol; rowsolX[1]=rowsol2; rowsolX[2]=rowsol2+nrows; rowsolX[3]=rowsolX[2]+nrows; #endif allsum = new double * [nsolve]; aX = new double * [nsolve]; aworkX = new double * [nsolve]; thetaX = new double[nsolve]; vX = new double[nsolve]; bX = new double[nsolve]; djX = new double[nsolve]; allsum[0] = pi; for (i = 0; i < nsolve; i++) { if (i) allsum[i] = new double[nrows]; aX[i] = new double[nsolve]; aworkX[i] = new double[nsolve]; } /* check = rows */ for (i = 0; i < nrows; i++) { if (rowupper[i] - rowlower[i] > tolerance) { extraBlock++; } } cost = new double[ncols]; memset(rowsol, 0, nrows * sizeof(double)); for (i = 0; i < ncols; i++) { CoinBigIndex j; double value = origcost[i] * maxmin; double value2 = colsol[i]; if (elemnt) { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; value += elemnt[j] * lambda[irow]; rowsol[irow] += elemnt[j] * value2; } } else { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; value += lambda[irow]; rowsol[irow] += value2; } } cost[i] = value; } if (extraBlock) { rowExtra = new int[extraBlock]; solExtra = new double[extraBlock]; elemExtra = new double[extraBlock]; upperExtra = new double[extraBlock]; costExtra = new double[extraBlock]; saveExtra = new double[extraBlock]; extraBlock = 0; int nbad = 0; for (i = 0; i < nrows; i++) { if (rowupper[i] - rowlower[i] > tolerance) { double smaller, difference; double value; saveExtra[extraBlock] = rowupper[i]; if (fabs(rowupper[i]) > fabs(rowlower[i])) { smaller = rowlower[i]; value = -1.0; } else { smaller = rowupper[i]; value = 1.0; } if (fabs(smaller) > 1.0e10) { if (!nbad) COIN_DETAIL_PRINT(printf("Can't handle rows where both bounds >1.0e10 %d %g\n", i, smaller)); nbad++; if (rowupper[i] < 0.0 || rowlower[i] > 0.0) abort(); if (fabs(rowupper[i]) > fabs(rowlower[i])) { rowlower[i] = -0.9e10; smaller = rowlower[i]; value = -1.0; } else { rowupper[i] = 0.9e10; saveExtra[extraBlock] = rowupper[i]; smaller = rowupper[i]; value = 1.0; } } difference = rowupper[i] - rowlower[i]; difference = CoinMin(difference, 1.0e31); rowupper[i] = smaller; elemExtra[extraBlock] = value; solExtra[extraBlock] = (rowupper[i] - rowsol[i]) / value; if (solExtra[extraBlock] < 0.0) solExtra[extraBlock] = 0.0; if (solExtra[extraBlock] > difference) solExtra[extraBlock] = difference; costExtra[extraBlock] = lambda[i] * value; upperExtra[extraBlock] = difference; rowsol[i] += value * solExtra[extraBlock]; rowExtra[extraBlock++] = i; } } if (nbad) COIN_DETAIL_PRINT(printf("%d bad values - results may be wrong\n", nbad)); } for (i = 0; i < nrows; i++) { offset += lambda[i] * rowsol[i]; } if ((strategy & 256) != 0) { /* save best solution */ saveSol = new double[ncols]; CoinMemcpyN(colsol, ncols, saveSol); if (extraBlock) { useCostExtra = new double[extraBlock]; memset(useCostExtra, 0, extraBlock * sizeof(double)); } useCost = origcost; useOffset = saveOffset; } else { useCostExtra = costExtra; useCost = cost; useOffset = offset; } ncolx = ncols + extraBlock; for (i = 0; i < HISTORY + 1; i++) { history[i] = new double[ncolx]; } for (i = 0; i < DJTEST; i++) { djSave[i] = 1.0e30; } for (i = 0; i < ncols; i++) { if (upper[i] - lower[i]) { statusSave[i] = 0; } else { statusSave[i] = 1; } } // for two pass method int start[2]; int stop[2]; int direction = -1; start[0] = 0; stop[0] = ncols; start[1] = 0; stop[1] = 0; iter = 0; for (; iter < maxIts; iter++) { double sum1 = 0.0, sum2 = 0.0; double lastObj = 1.0e70; int good = 0, doScale = 0; if (strategy & 16) { int ii = iter / EVERY + 1; ii = ii * EVERY; if (iter > ii - HISTORY * 2 && (iter & 1) == 0) { double * COIN_RESTRICT x = history[HISTORY-1]; for (i = HISTORY - 1; i > 0; i--) { history[i] = history[i-1]; } history[0] = x; CoinMemcpyN(colsol, ncols, history[0]); CoinMemcpyN(solExtra, extraBlock, history[0] + ncols); } } if ((iter % SAVEHISTORY) == 0 || doFull) { if ((strategy & 16) == 0) { double * COIN_RESTRICT x = history[HISTORY-1]; for (i = HISTORY - 1; i > 0; i--) { history[i] = history[i-1]; } history[0] = x; CoinMemcpyN(colsol, ncols, history[0]); CoinMemcpyN(solExtra, extraBlock, history[0] + ncols); } } /* start full try */ if ((iter % EVERY) == 0 || doFull) { // for next pass direction = - direction; // randomize. // The cast is to avoid gcc compiler warning int kcol = static_cast(ncols * randomNumberGenerator->randomDouble()); if (kcol == ncols) kcol = ncols - 1; if (direction > 0) { start[0] = kcol; stop[0] = ncols; start[1] = 0; stop[1] = kcol; #ifdef FOUR_GOES for (int itry=0;itry<2;itry++) { int chunk=(stop[itry]-start[itry]+FOUR_GOES-1)/FOUR_GOES; startsX[itry][0]=start[itry]; for (int i=1;i<5;i++) startsX[itry][i]=CoinMin(stop[itry],startsX[itry][i-1]+chunk); } #endif } else { start[0] = kcol; stop[0] = -1; start[1] = ncols - 1; stop[1] = kcol; #ifdef FOUR_GOES for (int itry=0;itry<2;itry++) { int chunk=(start[itry]-stop[itry]+FOUR_GOES-1)/FOUR_GOES; startsX[itry][0]=start[itry]; for (int i=1;i<5;i++) startsX[itry][i]=CoinMax(stop[itry],startsX[itry][i-1]-chunk); } #endif } int itry = 0; /*if ((strategy&16)==0) { double * COIN_RESTRICT x=history[HISTORY-1]; for (i=HISTORY-1;i>0;i--) { history[i]=history[i-1]; } history[0]=x; CoinMemcpyN(colsol,ncols,history[0]); CoinMemcpyN(solExtra,extraBlock,history[0]+ncols); }*/ while (!good) { itry++; #define MAXTRY 5 if (iter > after && doScale < 2 && itry < MAXTRY) { /* now full one */ for (i = 0; i < nrows; i++) { rowsol[i] = -rowupper[i]; } sum2 = 0.0; objvalue = 0.0; memset(pi, 0, nrows * sizeof(double)); { double * COIN_RESTRICT theta = thetaX; double * COIN_RESTRICT dj = djX; double * COIN_RESTRICT b = bX; double ** a = aX; double ** awork = aworkX; double * COIN_RESTRICT v = vX; double c; #ifdef FIT int ntot = 0, nsign = 0, ngood = 0, mgood[4] = {0, 0, 0, 0}; double diff1, diff2, val0, val1, val2, newValue; CoinMemcpyN(colsol, ncols, history[HISTORY-1]); CoinMemcpyN(solExtra, extraBlock, history[HISTORY-1] + ncols); #endif dj[0] = 0.0; for (i = 1; i < nsolve; i++) { dj[i] = 0.0; memset(allsum[i], 0, nrows * sizeof(double)); } for (i = 0; i < ncols; i++) { double value2 = colsol[i]; if (value2 > lower[i] + tolerance) { if(value2 < (upper[i] - tolerance)) { int k; objvalue += value2 * cost[i]; #ifdef FIT ntot++; val0 = history[0][i]; val1 = history[1][i]; val2 = history[2][i]; diff1 = val0 - val1; diff2 = val1 - val2; if (diff1*diff2 >= 0.0) { nsign++; if (fabs(diff1) < fabs(diff2)) { int ii = static_cast(fabs(4.0 * diff1 / diff2)); if (ii == 4) ii = 3; mgood[ii]++; ngood++; } if (fabs(diff1) < 0.75 * fabs(diff2)) { newValue = val1 + (diff1 * diff2) / (diff2 - diff1); } else { newValue = val1 + 4.0 * diff1; } } else { newValue = 0.333333333 * (val0 + val1 + val2); } if (newValue > upper[i] - tolerance) { newValue = upper[i]; } else if (newValue < lower[i] + tolerance) { newValue = lower[i]; } history[HISTORY-1][i] = newValue; #endif for (k = 0; k < HISTORY - 1; k++) { value = history[k][i] - history[k+1][i]; dj[k] += value * cost[i]; v[k] = value; } if (elemnt) { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; for (k = 0; k < HISTORY - 1; k++) { allsum[k][irow] += elemnt[j] * v[k]; } rowsol[irow] += elemnt[j] * value2; } } else { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; for (k = 0; k < HISTORY - 1; k++) { allsum[k][irow] += v[k]; } rowsol[irow] += value2; } } } else { /* at ub */ colsol[i] = upper[i]; value2 = colsol[i]; objvalue += value2 * cost[i]; if (elemnt) { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += elemnt[j] * value2; } } else { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += value2; } } } } else { /* at lb */ if (value2) { objvalue += value2 * cost[i]; if (elemnt) { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += elemnt[j] * value2; } } else { for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; rowsol[irow] += value2; } } } } } #ifdef FIT /*printf("total %d, same sign %d, good %d %d %d %d %d\n", ntot,nsign,ngood,mgood[0],mgood[1],mgood[2],mgood[3]);*/ #endif if (extraBlock) { for (i = 0; i < extraBlock; i++) { double element = elemExtra[i]; int irow = rowExtra[i]; objvalue += solExtra[i] * costExtra[i]; if (solExtra[i] > tolerance && solExtra[i] < (upperExtra[i] - tolerance)) { double value2 = solExtra[i]; int k; for (k = 0; k < HISTORY - 1; k++) { value = history[k][i+ncols] - history[k+1][i+ncols]; dj[k] += value * costExtra[i]; allsum[k][irow] += element * value; } rowsol[irow] += element * value2; } else { double value2 = solExtra[i]; double element = elemExtra[i]; int irow = rowExtra[i]; rowsol[irow] += element * value2; } } } #ifdef NULLVECTOR if ((strategy & 64)) { double djVal = dj[0]; for (i = 0; i < ncols - nrows; i++) { double value2 = colsol[i]; if (value2 > lower[i] + tolerance && value2 < upper[i] - tolerance) { value = history[0][i] - history[1][i]; } else { value = 0.0; } history[HISTORY][i] = value; } for (; i < ncols; i++) { double value2 = colsol[i]; double delta; int irow = i - (ncols - nrows); double oldSum = allsum[0][irow];; if (value2 > lower[i] + tolerance && value2 < upper[i] - tolerance) { delta = history[0][i] - history[1][i]; } else { delta = 0.0; } djVal -= delta * cost[i]; oldSum -= delta; delta = - oldSum; djVal += delta * cost[i]; history[HISTORY][i] = delta; } dj[HISTORY-1] = djVal; djVal = 0.0; for (i = 0; i < ncols; i++) { double value2 = colsol[i]; if (value2 > lower[i] + tolerance && value2 < upper[i] - tolerance || i >= ncols - nrows) { int k; value = history[HISTORY][i]; djVal += value * cost[i]; for (j = columnStart[i]; j < columnStart[i] + length[i]; j++) { int irow = row[j]; allsum[nsolve-1][irow] += value; } } } printf("djs %g %g\n", dj[HISTORY-1], djVal); } #endif for (i = 0; i < nsolve; i++) { int j; b[i] = 0.0; for (j = 0; j < nsolve; j++) { a[i][j] = 0.0; } } c = 0.0; for (i = 0; i < nrows; i++) { double value = rowsol[i]; for (k = 0; k < nsolve; k++) { v[k] = allsum[k][i]; b[k] += v[k] * value; } c += value * value; for (k = 0; k < nsolve; k++) { for (j = k; j < nsolve; j++) { a[k][j] += v[k] * v[j]; } } } sum2 = c; if (itry == 1) { lastObj = objvalue + weight * sum2; } for (k = 0; k < nsolve; k++) { b[k] = - (weight * b[k] + 0.5 * dj[k]); for (j = k; j < nsolve; j++) { a[k][j] *= weight; a[j][k] = a[k][j]; } } c *= weight; for (k = 0; k < nsolve; k++) { theta[k] = b[k]; } solveSmall(nsolve, a, awork, theta); if ((strategy & 64) != 0) { value = 10.0; for (k = 0; k < nsolve; k++) { value = CoinMax(value, fabs(theta[k])); } if (value > 10.0 && ((logLevel_ & 4) != 0)) { printf("theta %g %g %g\n", theta[0], theta[1], theta[2]); } value = 10.0 / value; for (k = 0; k < nsolve; k++) { theta[k] *= value; } } for (i = 0; i < ncolx; i++) { double valueh = 0.0; for (k = 0; k < HISTORY - 1; k++) { value = history[k][i] - history[k+1][i]; valueh += value * theta[k]; } #ifdef NULLVECTOR value = history[HISTORY][i]; valueh += value * theta[HISTORY-1]; #endif history[HISTORY][i] = valueh; } } #ifdef NULLVECTOR if ((strategy & 64)) { for (i = 0; i < ncols - nrows; i++) { if (colsol[i] <= lower[i] + tolerance || colsol[i] >= (upper[i] - tolerance)) { history[HISTORY][i] = 0.0;; } } tolerance = -tolerance; /* switch off test */ } #endif if (!doScale) { for (i = 0; i < ncols; i++) { if (colsol[i] > lower[i] + tolerance && colsol[i] < (upper[i] - tolerance)) { value = history[HISTORY][i]; colsol[i] += value; if (colsol[i] < lower[i] + tolerance) { colsol[i] = lower[i]; } else if (colsol[i] > upper[i] - tolerance) { colsol[i] = upper[i]; } } } if (extraBlock) { for (i = 0; i < extraBlock; i++) { if (solExtra[i] > tolerance && solExtra[i] < (upperExtra[i] - tolerance)) { value = history[HISTORY][i+ncols]; solExtra[i] += value; if (solExtra[i] < 0.0) { solExtra[i] = 0.0; } else if (solExtra[i] > upperExtra[i]) { solExtra[i] = upperExtra[i]; } } } } } else { double theta = 1.0; double saveTheta = theta; for (i = 0; i < ncols; i++) { if (colsol[i] > lower[i] + tolerance && colsol[i] < (upper[i] - tolerance)) { value = history[HISTORY][i]; if (value > 0) { if (theta * value + colsol[i] > upper[i]) { theta = (upper[i] - colsol[i]) / value; } } else if (value < 0) { if (colsol[i] + theta * value < lower[i]) { theta = (lower[i] - colsol[i]) / value; } } } } if (extraBlock) { for (i = 0; i < extraBlock; i++) { if (solExtra[i] > tolerance && solExtra[i] < (upperExtra[i] - tolerance)) { value = history[HISTORY][i+ncols]; if (value > 0) { if (theta * value + solExtra[i] > upperExtra[i]) { theta = (upperExtra[i] - solExtra[i]) / value; } } else if (value < 0) { if (solExtra[i] + theta * value < 0.0) { theta = -solExtra[i] / value; } } } } } if ((iter % 100 == 0) && (logLevel_ & 8) != 0) { if (theta < saveTheta) { printf(" - modified theta %g\n", theta); } } for (i = 0; i < ncols; i++) { if (colsol[i] > lower[i] + tolerance && colsol[i] < (upper[i] - tolerance)) { value = history[HISTORY][i]; colsol[i] += value * theta; } } if (extraBlock) { for (i = 0; i < extraBlock; i++) { if (solExtra[i] > tolerance && solExtra[i] < (upperExtra[i] - tolerance)) { value = history[HISTORY][i+ncols]; solExtra[i] += value * theta; } } } } #ifdef NULLVECTOR tolerance = fabs(tolerance); /* switch back on */ #endif if ((iter % 100) == 0 && (logLevel_ & 8) != 0) { printf("\n"); } } good = 1; result = objval(nrows, ncols, rowsol, colsol, pi, djs, useCost, rowlower, rowupper, lower, upper, elemnt, row, columnStart, length, extraBlock, rowExtra, solExtra, elemExtra, upperExtra, useCostExtra, weight); weightedObj = result.weighted; if (!iter) saveValue = weightedObj; objvalue = result.objval; sum1 = result.infeas; if (saveSol) { if (result.weighted < bestSol) { COIN_DETAIL_PRINT(printf("%d %g better than %g\n", iter, result.weighted * maxmin - useOffset, bestSol * maxmin - useOffset)); bestSol = result.weighted; CoinMemcpyN(colsol, ncols, saveSol); } } #ifdef FITz if (iter > after) { IdiotResult result2; double ww, oo, ss; if (extraBlock) abort(); result2 = objval(nrows, ncols, row2, sol2, pi2, djs, cost, rowlower, rowupper, lower, upper, elemnt, row, columnStart, extraBlock, rowExtra, solExtra, elemExtra, upperExtra, costExtra, weight); ww = result2.weighted; oo = result2.objval; ss = result2.infeas; printf("wobj %g obj %g inf %g last %g\n", ww, oo, ss, lastObj); if (ww < weightedObj && ww < lastObj) { printf(" taken"); ntaken++; saving += weightedObj - ww; weightedObj = ww; objvalue = oo; sum1 = ss; CoinMemcpyN(row2, nrows, rowsol); CoinMemcpyN(pi2, nrows, pi); CoinMemcpyN(sol2, ncols, colsol); result = objval(nrows, ncols, rowsol, colsol, pi, djs, cost, rowlower, rowupper, lower, upper, elemnt, row, columnStart, extraBlock, rowExtra, solExtra, elemExtra, upperExtra, costExtra, weight); weightedObj = result.weighted; objvalue = result.objval; sum1 = result.infeas; if (ww < weightedObj) abort(); } else { printf(" not taken"); nottaken++; } } #endif /*printf("%d %g %g %g %g\n",itry,lastObj,weightedObj,objvalue,sum1);*/ if (weightedObj > lastObj + 1.0e-4 && itry < MAXTRY) { if((logLevel_ & 16) != 0 && doScale) { printf("Weighted objective from %g to %g **** bad move\n", lastObj, weightedObj); } if (doScale) { good = 1; } if ((strategy & 3) == 1) { good = 0; if (weightedObj > lastObj + djExit) { if ((logLevel_ & 16) != 0) { printf("Weighted objective from %g to %g ?\n", lastObj, weightedObj); } CoinMemcpyN(history[0], ncols, colsol); CoinMemcpyN(history[0] + ncols, extraBlock, solExtra); good = 1; } } else if ((strategy & 3) == 2) { if (weightedObj > lastObj + 0.1 * maxDj) { CoinMemcpyN(history[0], ncols, colsol); CoinMemcpyN(history[0] + ncols, extraBlock, solExtra); doScale++; good = 0; } } else if ((strategy & 3) == 3) { if (weightedObj > lastObj + 0.001 * maxDj) { /*doScale++;*/ good = 0; } } } } if ((iter % checkFrequency_) == 0) { double best = weightedObj; double test = obj[0]; for (i = 1; i < DROP; i++) { obj[i-1] = obj[i]; if (best > obj[i]) best = obj[i]; } obj[DROP-1] = best; if (test - best < drop && (strategy & 8) == 0) { if ((logLevel_ & 8) != 0) { printf("Exiting as drop in %d its is %g after %d iterations\n", DROP * checkFrequency_, test - best, iter); } goto RETURN; } } if ((iter % logFreq_) == 0) { double piSum = 0.0; for (i = 0; i < nrows; i++) { piSum += (rowsol[i] + rowupper[i]) * pi[i]; } if ((logLevel_ & 2) != 0) { printf("%d Infeas %g, obj %g - wtObj %g dual %g maxDj %g\n", iter, sum1, objvalue * maxmin - useOffset, weightedObj - useOffset, piSum * maxmin - useOffset, maxDj); } } CoinMemcpyN(statusSave, ncols, statusWork); nflagged = 0; } nChange = 0; doFull = 0; maxDj = 0.0; // go through forwards or backwards and starting at odd places #ifdef FOUR_GOES for (int i=1;i>1; } else { istart=(start[itry]+stop[itry])>>1; istop = stop[itry]; } #endif #if 0 printf("istart %d istop %d direction %d array %d %d new %d %d\n", istart,istop,direction,start[itry],stop[itry], startsX[itry][iPar],startsX[itry][iPar+1]); #endif istart=startsX[itry][iPar]; istop=startsX[itry][iPar+1]; #else for (int itry = 0; itry < 2; itry++) { int istart = start[itry]; int istop = stop[itry]; #endif for (int icol=istart; icol != istop; icol += direction) { if (!statusWork[icol]) { CoinBigIndex j; double value = colsol[icol]; double djval = cost[icol]; double djval2, value2; double theta, a, b, c; if (elemnt) { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; djval -= elemnt[j] * pi[irow]; } } else { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; djval -= pi[irow]; } } /*printf("xx iter %d seq %d djval %g value %g\n", iter,i,djval,value);*/ if (djval > 1.0e-5) { value2 = (lower[icol] - value); } else { value2 = (upper[icol] - value); } djval2 = djval * value2; djval = fabs(djval); if (djval > djTol) { if (djval2 < -1.0e-4) { #ifndef FOUR_GOES nChange++; if (djval > maxDj) maxDj = djval; #else nChangeX[iPar]++; if (djval > maxDjX[iPar]) maxDjX[iPar] = djval; #endif /*if (djval>3.55e6) { printf("big\n"); }*/ a = 0.0; b = 0.0; c = 0.0; djval2 = cost[icol]; if (elemnt) { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; double value = rowsol[irow]; c += value * value; a += elemnt[j] * elemnt[j]; b += value * elemnt[j]; } } else { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; double value = rowsol[irow]; c += value * value; a += 1.0; b += value; } } a *= weight; b = b * weight + 0.5 * djval2; c *= weight; /* solve */ theta = -b / a; #ifndef FOUR_GOES if ((strategy & 4) != 0) { double valuep, thetap; value2 = a * theta * theta + 2.0 * b * theta; thetap = 2.0 * theta; valuep = a * thetap * thetap + 2.0 * b * thetap; if (valuep < value2 + djTol) { theta = thetap; kgood++; } else { kbad++; } } #endif if (theta > 0.0) { if (theta < upper[icol] - colsol[icol]) { value2 = theta; } else { value2 = upper[icol] - colsol[icol]; } } else { if (theta > lower[icol] - colsol[icol]) { value2 = theta; } else { value2 = lower[icol] - colsol[icol]; } } colsol[icol] += value2; #ifndef FOUR_GOES objvalue += cost[icol] * value2; #else objvalueX[iPar] += cost[icol] * value2; #endif if (elemnt) { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; double value; rowsol[irow] += elemnt[j] * value2; value = rowsol[irow]; pi[irow] = -2.0 * weight * value; } } else { for (j = columnStart[icol]; j < columnStart[icol] + length[icol]; j++) { int irow = row[j]; double value; rowsol[irow] += value2; value = rowsol[irow]; pi[irow] = -2.0 * weight * value; } } } else { /* dj but at bound */ if (djval > djFlag) { statusWork[icol] = 1; #ifndef FOUR_GOES nflagged++; #else nflaggedX[iPar]++; #endif } } } } } #ifdef FOUR_GOES } #endif } #ifdef FOUR_GOES for (int i=0;i 1.0e-5) { value2 = -value; } else { value2 = (upperExtra[i] - value); } djval2 = djval * value2; if (djval2 < -1.0e-4 && fabs(djval) > djTol) { nChange++; a = 0.0; b = 0.0; c = 0.0; djval2 = costExtra[i]; value = rowsol[irow]; c += value * value; a += element * element; b += element * value; a *= weight; b = b * weight + 0.5 * djval2; c *= weight; /* solve */ theta = -b / a; if (theta > 0.0) { value2 = CoinMin(theta, upperExtra[i] - solExtra[i]); } else { value2 = CoinMax(theta, -solExtra[i]); } solExtra[i] += value2; rowsol[irow] += element * value2; value = rowsol[irow]; pi[irow] = -2.0 * weight * value; } } } if ((iter % 10) == 2) { for (int i = DJTEST - 1; i > 0; i--) { djSave[i] = djSave[i-1]; } djSave[0] = maxDj; largestDj = CoinMax(largestDj, maxDj); smallestDj = CoinMin(smallestDj, maxDj); for (int i = DJTEST - 1; i > 0; i--) { maxDj += djSave[i]; } maxDj = maxDj / static_cast (DJTEST); if (maxDj < djExit && iter > 50) { //printf("Exiting on low dj %g after %d iterations\n",maxDj,iter); break; } if (nChange < 100) { djTol *= 0.5; } } } RETURN: if (kgood || kbad) { COIN_DETAIL_PRINT(printf("%g good %g bad\n", kgood, kbad)); } result = objval(nrows, ncols, rowsol, colsol, pi, djs, useCost, rowlower, rowupper, lower, upper, elemnt, row, columnStart, length, extraBlock, rowExtra, solExtra, elemExtra, upperExtra, useCostExtra, weight); result.djAtBeginning = largestDj; result.djAtEnd = smallestDj; result.dropThis = saveValue - result.weighted; if (saveSol) { if (result.weighted < bestSol) { bestSol = result.weighted; CoinMemcpyN(colsol, ncols, saveSol); } else { COIN_DETAIL_PRINT(printf("restoring previous - now %g best %g\n", result.weighted * maxmin - useOffset, bestSol * maxmin - useOffset)); } } if (saveSol) { if (extraBlock) { delete [] useCostExtra; } CoinMemcpyN(saveSol, ncols, colsol); delete [] saveSol; } for (i = 0; i < nsolve; i++) { if (i) delete [] allsum[i]; delete [] aX[i]; delete [] aworkX[i]; } delete [] thetaX; delete [] djX; delete [] bX; delete [] vX; delete [] aX; delete [] aworkX; delete [] allsum; delete [] cost; #ifdef FOUR_GOES delete [] pi2 ; delete [] rowsol2 ; #endif for (i = 0; i < HISTORY + 1; i++) { delete [] history[i]; } delete [] statusSave; /* do original costs objvalue*/ result.objval = 0.0; for (i = 0; i < ncols; i++) { result.objval += colsol[i] * origcost[i]; } if (extraBlock) { for (i = 0; i < extraBlock; i++) { int irow = rowExtra[i]; rowupper[irow] = saveExtra[i]; } delete [] rowExtra; delete [] solExtra; delete [] elemExtra; delete [] upperExtra; delete [] costExtra; delete [] saveExtra; } result.iteration = iter; result.objval -= saveOffset; result.weighted = result.objval + weight * result.sumSquared; return result; } Clp-1.15.10/src/CoinAbcFactorization3.cpp0000644000076600007660000000101712101105055016451 0ustar coincoin/* $Id: CoinAbcFactorization3.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization3.cpp" #endif Clp-1.15.10/src/ClpGubMatrix.cpp0000644000076600007660000056457412130104455014727 0ustar coincoin/* $Id: ClpGubMatrix.cpp 1931 2013-04-06 20:44:29Z 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 "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpNonLinearCost.hpp" // at end to get min/max! #include "ClpGubMatrix.hpp" //#include "ClpGubDynamicMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpGubMatrix::ClpGubMatrix () : ClpPackedMatrix(), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), infeasibilityWeight_(0.0), start_(NULL), end_(NULL), lower_(NULL), upper_(NULL), status_(NULL), saveStatus_(NULL), savedKeyVariable_(NULL), backward_(NULL), backToPivotRow_(NULL), changeCost_(NULL), keyVariable_(NULL), next_(NULL), toIndex_(NULL), fromIndex_(NULL), model_(NULL), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), noCheck_(-1), numberSets_(0), saveNumber_(0), possiblePivotKey_(0), gubSlackIn_(-1), firstGub_(0), lastGub_(0), gubType_(0) { setType(16); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpGubMatrix::ClpGubMatrix (const ClpGubMatrix & rhs) : ClpPackedMatrix(rhs) { numberSets_ = rhs.numberSets_; saveNumber_ = rhs.saveNumber_; possiblePivotKey_ = rhs.possiblePivotKey_; gubSlackIn_ = rhs.gubSlackIn_; start_ = ClpCopyOfArray(rhs.start_, numberSets_); end_ = ClpCopyOfArray(rhs.end_, numberSets_); lower_ = ClpCopyOfArray(rhs.lower_, numberSets_); upper_ = ClpCopyOfArray(rhs.upper_, numberSets_); status_ = ClpCopyOfArray(rhs.status_, numberSets_); saveStatus_ = ClpCopyOfArray(rhs.saveStatus_, numberSets_); savedKeyVariable_ = ClpCopyOfArray(rhs.savedKeyVariable_, numberSets_); int numberColumns = getNumCols(); backward_ = ClpCopyOfArray(rhs.backward_, numberColumns); backToPivotRow_ = ClpCopyOfArray(rhs.backToPivotRow_, numberColumns); changeCost_ = ClpCopyOfArray(rhs.changeCost_, getNumRows() + numberSets_); fromIndex_ = ClpCopyOfArray(rhs.fromIndex_, getNumRows() + numberSets_ + 1); keyVariable_ = ClpCopyOfArray(rhs.keyVariable_, numberSets_); // find longest set int * longest = new int[numberSets_]; CoinZeroN(longest, numberSets_); int j; for (j = 0; j < numberColumns; j++) { int iSet = backward_[j]; if (iSet >= 0) longest[iSet]++; } int length = 0; for (j = 0; j < numberSets_; j++) length = CoinMax(length, longest[j]); next_ = ClpCopyOfArray(rhs.next_, numberColumns + numberSets_ + 2 * length); toIndex_ = ClpCopyOfArray(rhs.toIndex_, numberSets_); sumDualInfeasibilities_ = rhs. sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; infeasibilityWeight_ = rhs.infeasibilityWeight_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; noCheck_ = rhs.noCheck_; firstGub_ = rhs.firstGub_; lastGub_ = rhs.lastGub_; gubType_ = rhs.gubType_; model_ = rhs.model_; } //------------------------------------------------------------------- // assign matrix (for space reasons) //------------------------------------------------------------------- ClpGubMatrix::ClpGubMatrix (CoinPackedMatrix * rhs) : ClpPackedMatrix(rhs), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), infeasibilityWeight_(0.0), start_(NULL), end_(NULL), lower_(NULL), upper_(NULL), status_(NULL), saveStatus_(NULL), savedKeyVariable_(NULL), backward_(NULL), backToPivotRow_(NULL), changeCost_(NULL), keyVariable_(NULL), next_(NULL), toIndex_(NULL), fromIndex_(NULL), model_(NULL), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), noCheck_(-1), numberSets_(0), saveNumber_(0), possiblePivotKey_(0), gubSlackIn_(-1), firstGub_(0), lastGub_(0), gubType_(0) { setType(16); } /* This takes over ownership (for space reasons) and is the real constructor*/ ClpGubMatrix::ClpGubMatrix(ClpPackedMatrix * matrix, int numberSets, const int * start, const int * end, const double * lower, const double * upper, const unsigned char * status) : ClpPackedMatrix(matrix->matrix()), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), saveNumber_(0), possiblePivotKey_(0), gubSlackIn_(-1) { model_ = NULL; numberSets_ = numberSets; start_ = ClpCopyOfArray(start, numberSets_); end_ = ClpCopyOfArray(end, numberSets_); lower_ = ClpCopyOfArray(lower, numberSets_); upper_ = ClpCopyOfArray(upper, numberSets_); // Check valid and ordered int last = -1; int numberColumns = matrix_->getNumCols(); int numberRows = matrix_->getNumRows(); backward_ = new int[numberColumns]; backToPivotRow_ = new int[numberColumns]; changeCost_ = new double [numberRows+numberSets_]; keyVariable_ = new int[numberSets_]; // signal to need new ordering next_ = NULL; for (int iColumn = 0; iColumn < numberColumns; iColumn++) backward_[iColumn] = -1; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) { // set key variable as slack keyVariable_[iSet] = iSet + numberColumns; if (start_[iSet] < 0 || start_[iSet] >= numberColumns) throw CoinError("Index out of range", "constructor", "ClpGubMatrix"); if (end_[iSet] < 0 || end_[iSet] > numberColumns) throw CoinError("Index out of range", "constructor", "ClpGubMatrix"); if (end_[iSet] <= start_[iSet]) throw CoinError("Empty or negative set", "constructor", "ClpGubMatrix"); if (start_[iSet] < last) throw CoinError("overlapping or non-monotonic sets", "constructor", "ClpGubMatrix"); last = end_[iSet]; int j; for (j = start_[iSet]; j < end_[iSet]; j++) backward_[j] = iSet; } // Find type of gub firstGub_ = numberColumns + 1; lastGub_ = -1; int i; for (i = 0; i < numberColumns; i++) { if (backward_[i] >= 0) { firstGub_ = CoinMin(firstGub_, i); lastGub_ = CoinMax(lastGub_, i); } } gubType_ = 0; // adjust lastGub_ if (lastGub_ > 0) lastGub_++; for (i = firstGub_; i < lastGub_; i++) { if (backward_[i] < 0) { gubType_ = 1; printf("interior non gub %d\n", i); break; } } if (status) { status_ = ClpCopyOfArray(status, numberSets_); } else { status_ = new unsigned char [numberSets_]; memset(status_, 0, numberSets_); int i; for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } } saveStatus_ = new unsigned char [numberSets_]; memset(saveStatus_, 0, numberSets_); savedKeyVariable_ = new int [numberSets_]; memset(savedKeyVariable_, 0, numberSets_ * sizeof(int)); noCheck_ = -1; infeasibilityWeight_ = 0.0; } ClpGubMatrix::ClpGubMatrix (const CoinPackedMatrix & rhs) : ClpPackedMatrix(rhs), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), infeasibilityWeight_(0.0), start_(NULL), end_(NULL), lower_(NULL), upper_(NULL), status_(NULL), saveStatus_(NULL), savedKeyVariable_(NULL), backward_(NULL), backToPivotRow_(NULL), changeCost_(NULL), keyVariable_(NULL), next_(NULL), toIndex_(NULL), fromIndex_(NULL), model_(NULL), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), noCheck_(-1), numberSets_(0), saveNumber_(0), possiblePivotKey_(0), gubSlackIn_(-1), firstGub_(0), lastGub_(0), gubType_(0) { setType(16); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpGubMatrix::~ClpGubMatrix () { delete [] start_; delete [] end_; delete [] lower_; delete [] upper_; delete [] status_; delete [] saveStatus_; delete [] savedKeyVariable_; delete [] backward_; delete [] backToPivotRow_; delete [] changeCost_; delete [] keyVariable_; delete [] next_; delete [] toIndex_; delete [] fromIndex_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpGubMatrix & ClpGubMatrix::operator=(const ClpGubMatrix& rhs) { if (this != &rhs) { ClpPackedMatrix::operator=(rhs); delete [] start_; delete [] end_; delete [] lower_; delete [] upper_; delete [] status_; delete [] saveStatus_; delete [] savedKeyVariable_; delete [] backward_; delete [] backToPivotRow_; delete [] changeCost_; delete [] keyVariable_; delete [] next_; delete [] toIndex_; delete [] fromIndex_; numberSets_ = rhs.numberSets_; saveNumber_ = rhs.saveNumber_; possiblePivotKey_ = rhs.possiblePivotKey_; gubSlackIn_ = rhs.gubSlackIn_; start_ = ClpCopyOfArray(rhs.start_, numberSets_); end_ = ClpCopyOfArray(rhs.end_, numberSets_); lower_ = ClpCopyOfArray(rhs.lower_, numberSets_); upper_ = ClpCopyOfArray(rhs.upper_, numberSets_); status_ = ClpCopyOfArray(rhs.status_, numberSets_); saveStatus_ = ClpCopyOfArray(rhs.saveStatus_, numberSets_); savedKeyVariable_ = ClpCopyOfArray(rhs.savedKeyVariable_, numberSets_); int numberColumns = getNumCols(); backward_ = ClpCopyOfArray(rhs.backward_, numberColumns); backToPivotRow_ = ClpCopyOfArray(rhs.backToPivotRow_, numberColumns); changeCost_ = ClpCopyOfArray(rhs.changeCost_, getNumRows() + numberSets_); fromIndex_ = ClpCopyOfArray(rhs.fromIndex_, getNumRows() + numberSets_ + 1); keyVariable_ = ClpCopyOfArray(rhs.keyVariable_, numberSets_); // find longest set int * longest = new int[numberSets_]; CoinZeroN(longest, numberSets_); int j; for (j = 0; j < numberColumns; j++) { int iSet = backward_[j]; if (iSet >= 0) longest[iSet]++; } int length = 0; for (j = 0; j < numberSets_; j++) length = CoinMax(length, longest[j]); next_ = ClpCopyOfArray(rhs.next_, numberColumns + numberSets_ + 2 * length); toIndex_ = ClpCopyOfArray(rhs.toIndex_, numberSets_); sumDualInfeasibilities_ = rhs. sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; infeasibilityWeight_ = rhs.infeasibilityWeight_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; noCheck_ = rhs.noCheck_; firstGub_ = rhs.firstGub_; lastGub_ = rhs.lastGub_; gubType_ = rhs.gubType_; model_ = rhs.model_; } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpGubMatrix::clone() const { return new ClpGubMatrix(*this); } /* Subset clone (without gaps). Duplicates are allowed and order is as given */ ClpMatrixBase * ClpGubMatrix::subsetClone (int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const { return new ClpGubMatrix(*this, numberRows, whichRows, numberColumns, whichColumns); } /* Returns a new matrix in reverse order without gaps Is allowed to return NULL if doesn't want to have row copy */ ClpMatrixBase * ClpGubMatrix::reverseOrderedCopy() const { return NULL; } int ClpGubMatrix::hiddenRows() const { return numberSets_; } /* Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpGubMatrix::ClpGubMatrix ( const ClpGubMatrix & rhs, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) : ClpPackedMatrix(rhs, numberRows, whichRows, numberColumns, whichColumns) { // Assuming no gub rows deleted // We also assume all sets in same order // Get array with backward pointers int numberColumnsOld = rhs.matrix_->getNumCols(); int * array = new int [ numberColumnsOld]; int i; for (i = 0; i < numberColumnsOld; i++) array[i] = -1; for (int iSet = 0; iSet < numberSets_; iSet++) { for (int j = start_[iSet]; j < end_[iSet]; j++) array[j] = iSet; } numberSets_ = -1; int lastSet = -1; bool inSet = false; for (i = 0; i < numberColumns; i++) { int iColumn = whichColumns[i]; int iSet = array[iColumn]; if (iSet < 0) { inSet = false; } else { if (!inSet) { // start of new set but check okay if (iSet <= lastSet) throw CoinError("overlapping or non-monotonic sets", "subset constructor", "ClpGubMatrix"); lastSet = iSet; numberSets_++; start_[numberSets_] = i; end_[numberSets_] = i + 1; lower_[numberSets_] = lower_[iSet]; upper_[numberSets_] = upper_[iSet]; inSet = true; } else { if (iSet < lastSet) { throw CoinError("overlapping or non-monotonic sets", "subset constructor", "ClpGubMatrix"); } else if (iSet == lastSet) { end_[numberSets_] = i + 1; } else { // new set lastSet = iSet; numberSets_++; start_[numberSets_] = i; end_[numberSets_] = i + 1; lower_[numberSets_] = lower_[iSet]; upper_[numberSets_] = upper_[iSet]; } } } } delete [] array; numberSets_++; // adjust // Find type of gub firstGub_ = numberColumns + 1; lastGub_ = -1; for (i = 0; i < numberColumns; i++) { if (backward_[i] >= 0) { firstGub_ = CoinMin(firstGub_, i); lastGub_ = CoinMax(lastGub_, i); } } if (lastGub_ > 0) lastGub_++; gubType_ = 0; for (i = firstGub_; i < lastGub_; i++) { if (backward_[i] < 0) { gubType_ = 1; break; } } // Make sure key is feasible if only key in set } ClpGubMatrix::ClpGubMatrix ( const CoinPackedMatrix & rhs, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) : ClpPackedMatrix(rhs, numberRows, whichRows, numberColumns, whichColumns), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), start_(NULL), end_(NULL), lower_(NULL), upper_(NULL), backward_(NULL), backToPivotRow_(NULL), changeCost_(NULL), keyVariable_(NULL), next_(NULL), toIndex_(NULL), fromIndex_(NULL), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), numberSets_(0), saveNumber_(0), possiblePivotKey_(0), gubSlackIn_(-1), firstGub_(0), lastGub_(0), gubType_(0) { setType(16); } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpGubMatrix::transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); int numberNonZero = 0; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int numberInRowArray = rowArray->getNumElements(); // maybe I need one in OsiSimplex double zeroTolerance = model->zeroTolerance(); int numberRows = model->numberRows(); ClpPackedMatrix* rowCopy = dynamic_cast< ClpPackedMatrix*>(model->rowCopy()); bool packed = rowArray->packedMode(); double factor = 0.3; // We may not want to do by row if there may be cache problems int numberColumns = model->numberColumns(); // It would be nice to find L2 cache size - for moment 512K // Be slightly optimistic if (numberColumns * sizeof(double) > 1000000) { if (numberRows * 10 < numberColumns) factor = 0.1; else if (numberRows * 4 < numberColumns) factor = 0.15; else if (numberRows * 2 < numberColumns) factor = 0.2; //if (model->numberIterations()%50==0) //printf("%d nonzero\n",numberInRowArray); } // reduce for gub factor *= 0.5; assert (!y->getNumElements()); if (numberInRowArray > factor * numberRows || !rowCopy) { // do by column int iColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); int numberColumns = model->numberColumns(); int iSet = -1; double djMod = 0.0; if (packed) { // need to expand pi into y assert(y->capacity() >= numberRows); double * piOld = pi; pi = y->denseVector(); const int * whichRow = rowArray->getIndices(); int i; if (!rowScale) { // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i]; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (backward_[iColumn] != iSet) { // get pi on gub row iSet = backward_[iColumn]; if (iSet >= 0) { int iBasic = keyVariable_[iSet]; if (iBasic < numberColumns) { // get dj without assert (model->getStatus(iBasic) == ClpSimplex::basic); djMod = 0.0; for (CoinBigIndex j = columnStart[iBasic]; j < columnStart[iBasic] + columnLength[iBasic]; j++) { int jRow = row[j]; djMod -= pi[jRow] * elementByColumn[j]; } } else { djMod = 0.0; } } else { djMod = 0.0; } } double value = -djMod; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } else { // scaled // modify pi so can collapse to one loop for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = scalar * piOld[i] * rowScale[iRow]; } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (backward_[iColumn] != iSet) { // get pi on gub row iSet = backward_[iColumn]; if (iSet >= 0) { int iBasic = keyVariable_[iSet]; if (iBasic < numberColumns) { // get dj without assert (model->getStatus(iBasic) == ClpSimplex::basic); djMod = 0.0; // scaled for (CoinBigIndex j = columnStart[iBasic]; j < columnStart[iBasic] + columnLength[iBasic]; j++) { int jRow = row[j]; djMod -= pi[jRow] * elementByColumn[j] * rowScale[jRow]; } } else { djMod = 0.0; } } else { djMod = 0.0; } } double value = -djMod; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } value *= columnScale[iColumn]; if (fabs(value) > zeroTolerance) { array[numberNonZero] = value; index[numberNonZero++] = iColumn; } } } // zero out for (i = 0; i < numberInRowArray; i++) { int iRow = whichRow[i]; pi[iRow] = 0.0; } } else { // code later assert (packed); if (!rowScale) { if (scalar == -1.0) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = -value; } } } else if (scalar == 1.0) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } value *= scalar; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } } else { // scaled if (scalar == -1.0) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= columnScale[iColumn]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = -value; } } } else if (scalar == 1.0) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= columnScale[iColumn]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= scalar * columnScale[iColumn]; if (fabs(value) > zeroTolerance) { index[numberNonZero++] = iColumn; array[iColumn] = value; } } } } } columnArray->setNumElements(numberNonZero); y->setNumElements(0); } else { // do by row transposeTimesByRow(model, scalar, rowArray, y, columnArray); } if (packed) columnArray->setPackedMode(true); if (0) { columnArray->checkClean(); int numberNonZero = columnArray->getNumElements();; int * index = columnArray->getIndices(); double * array = columnArray->denseVector(); int i; for (i = 0; i < numberNonZero; i++) { int j = index[i]; double value; if (packed) value = array[i]; else value = array[j]; printf("Ti %d %d %g\n", i, j, value); } } } /* Return x * A + y in z. Squashes small elements and knows about ClpSimplex */ void ClpGubMatrix::transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * rowArray, CoinIndexedVector * y, CoinIndexedVector * columnArray) const { // Do packed part ClpPackedMatrix::transposeTimesByRow(model, scalar, rowArray, y, columnArray); if (numberSets_) { /* what we need to do is do by row as normal but get list of sets touched and then update those ones */ abort(); } } /* Return x *A in z but just for indices in y. */ void ClpGubMatrix::subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * rowArray, const CoinIndexedVector * y, CoinIndexedVector * columnArray) const { columnArray->clear(); double * pi = rowArray->denseVector(); double * array = columnArray->denseVector(); int jColumn; // get matrix data pointers const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); int numberToDo = y->getNumElements(); const int * which = y->getIndices(); assert (!rowArray->packedMode()); columnArray->setPacked(); int numberTouched = 0; if (!rowScale) { for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j]; } array[jColumn] = value; if (value) { int iSet = backward_[iColumn]; if (iSet >= 0) { int iBasic = keyVariable_[iSet]; if (iBasic == iColumn) { toIndex_[iSet] = jColumn; fromIndex_[numberTouched++] = iSet; } } } } } else { // scaled for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; double value = 0.0; CoinBigIndex j; const double * columnScale = model->columnScale(); for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; value += pi[iRow] * elementByColumn[j] * rowScale[iRow]; } value *= columnScale[iColumn]; array[jColumn] = value; if (value) { int iSet = backward_[iColumn]; if (iSet >= 0) { int iBasic = keyVariable_[iSet]; if (iBasic == iColumn) { toIndex_[iSet] = jColumn; fromIndex_[numberTouched++] = iSet; } } } } } // adjust djs for (jColumn = 0; jColumn < numberToDo; jColumn++) { int iColumn = which[jColumn]; int iSet = backward_[iColumn]; if (iSet >= 0) { int kColumn = toIndex_[iSet]; if (kColumn >= 0) array[jColumn] -= array[kColumn]; } } // and clear basic for (int j = 0; j < numberTouched; j++) { int iSet = fromIndex_[j]; int kColumn = toIndex_[iSet]; toIndex_[iSet] = -1; array[kColumn] = 0.0; } } /// returns number of elements in column part of basis, CoinBigIndex ClpGubMatrix::countBasis(const int * whichColumn, int & numberColumnBasic) { int i; int numberColumns = getNumCols(); const int * columnLength = matrix_->getVectorLengths(); int numberRows = getNumRows(); int numberBasic = 0; CoinBigIndex numberElements = 0; int lastSet = -1; int key = -1; int keyLength = -1; double * work = new double[numberRows]; CoinZeroN(work, numberRows); char * mark = new char[numberRows]; CoinZeroN(mark, numberRows); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * row = matrix_->getIndices(); const double * elementByColumn = matrix_->getElements(); //ClpGubDynamicMatrix* gubx = //dynamic_cast< ClpGubDynamicMatrix*>(this); //int * id = gubx->id(); // just count for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; int iSet = backward_[iColumn]; int length = columnLength[iColumn]; if (iSet < 0 || keyVariable_[iSet] >= numberColumns) { numberElements += length; numberBasic++; //printf("non gub - set %d id %d (column %d) nel %d\n",iSet,id[iColumn-20],iColumn,length); } else { // in gub set if (iColumn != keyVariable_[iSet]) { numberBasic++; CoinBigIndex j; // not key if (lastSet < iSet) { // erase work if (key >= 0) { for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) work[row[j]] = 0.0; } key = keyVariable_[iSet]; lastSet = iSet; keyLength = columnLength[key]; for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) work[row[j]] = elementByColumn[j]; } int extra = keyLength; for (j = columnStart[iColumn]; j < columnStart[iColumn] + length; j++) { int iRow = row[j]; double keyValue = work[iRow]; double value = elementByColumn[j]; if (!keyValue) { if (fabs(value) > 1.0e-20) extra++; } else { value -= keyValue; if (fabs(value) <= 1.0e-20) extra--; } } numberElements += extra; //printf("gub - set %d id %d (column %d) nel %d\n",iSet,id[iColumn-20],iColumn,extra); } } } delete [] work; delete [] mark; // update number of column basic numberColumnBasic = numberBasic; return numberElements; } void ClpGubMatrix::fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * indexRowU, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * elementU) { int i; int numberColumns = getNumCols(); const int * columnLength = matrix_->getVectorLengths(); int numberRows = getNumRows(); assert (next_ || !elementU) ; CoinBigIndex numberElements = start[0]; int lastSet = -1; int key = -1; int keyLength = -1; double * work = new double[numberRows]; CoinZeroN(work, numberRows); char * mark = new char[numberRows]; CoinZeroN(mark, numberRows); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * row = matrix_->getIndices(); const double * elementByColumn = matrix_->getElements(); const double * rowScale = model->rowScale(); int numberBasic = 0; if (0) { printf("%d basiccolumns\n", numberColumnBasic); int i; for (i = 0; i < numberSets_; i++) { int k = keyVariable_[i]; if (k < numberColumns) { printf("key %d on set %d, %d elements\n", k, i, columnStart[k+1] - columnStart[k]); for (int j = columnStart[k]; j < columnStart[k+1]; j++) printf("row %d el %g\n", row[j], elementByColumn[j]); } else { printf("slack key on set %d\n", i); } } } // fill if (!rowScale) { // no scaling for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; int iSet = backward_[iColumn]; int length = columnLength[iColumn]; if (0) { int k = iColumn; printf("column %d in set %d, %d elements\n", k, iSet, columnStart[k+1] - columnStart[k]); for (int j = columnStart[k]; j < columnStart[k+1]; j++) printf("row %d el %g\n", row[j], elementByColumn[j]); } CoinBigIndex j; if (iSet < 0 || keyVariable_[iSet] >= numberColumns) { for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { double value = elementByColumn[j]; if (fabs(value) > 1.0e-20) { int iRow = row[j]; indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } // end of column columnCount[numberBasic] = numberElements - start[numberBasic]; numberBasic++; start[numberBasic] = numberElements; } else { // in gub set if (iColumn != keyVariable_[iSet]) { // not key if (lastSet != iSet) { // erase work if (key >= 0) { for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; work[iRow] = 0.0; mark[iRow] = 0; } } key = keyVariable_[iSet]; lastSet = iSet; keyLength = columnLength[key]; for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; work[iRow] = elementByColumn[j]; mark[iRow] = 1; } } for (j = columnStart[iColumn]; j < columnStart[iColumn] + length; j++) { int iRow = row[j]; double value = elementByColumn[j]; if (mark[iRow]) { mark[iRow] = 0; double keyValue = work[iRow]; value -= keyValue; } if (fabs(value) > 1.0e-20) { indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; if (mark[iRow]) { double value = -work[iRow]; if (fabs(value) > 1.0e-20) { indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } else { // just put back mark mark[iRow] = 1; } } // end of column columnCount[numberBasic] = numberElements - start[numberBasic]; numberBasic++; start[numberBasic] = numberElements; } } } } else { // scaling const double * columnScale = model->columnScale(); for (i = 0; i < numberColumnBasic; i++) { int iColumn = whichColumn[i]; int iSet = backward_[iColumn]; int length = columnLength[iColumn]; CoinBigIndex j; if (iSet < 0 || keyVariable_[iSet] >= numberColumns) { double scale = columnScale[iColumn]; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = elementByColumn[j] * scale * rowScale[iRow]; if (fabs(value) > 1.0e-20) { indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } // end of column columnCount[numberBasic] = numberElements - start[numberBasic]; numberBasic++; start[numberBasic] = numberElements; } else { // in gub set if (iColumn != keyVariable_[iSet]) { double scale = columnScale[iColumn]; // not key if (lastSet < iSet) { // erase work if (key >= 0) { for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; work[iRow] = 0.0; mark[iRow] = 0; } } key = keyVariable_[iSet]; lastSet = iSet; keyLength = columnLength[key]; double scale = columnScale[key]; for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; work[iRow] = elementByColumn[j] * scale * rowScale[iRow]; mark[iRow] = 1; } } for (j = columnStart[iColumn]; j < columnStart[iColumn] + length; j++) { int iRow = row[j]; double value = elementByColumn[j] * scale * rowScale[iRow]; if (mark[iRow]) { mark[iRow] = 0; double keyValue = work[iRow]; value -= keyValue; } if (fabs(value) > 1.0e-20) { indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } for (j = columnStart[key]; j < columnStart[key] + keyLength; j++) { int iRow = row[j]; if (mark[iRow]) { double value = -work[iRow]; if (fabs(value) > 1.0e-20) { indexRowU[numberElements] = iRow; rowCount[iRow]++; elementU[numberElements++] = value; } } else { // just put back mark mark[iRow] = 1; } } // end of column columnCount[numberBasic] = numberElements - start[numberBasic]; numberBasic++; start[numberBasic] = numberElements; } } } } delete [] work; delete [] mark; // update number of column basic numberColumnBasic = numberBasic; } /* Unpacks a column into an CoinIndexedvector */ void ClpGubMatrix::unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn) const { assert (iColumn < model->numberColumns()); // Do packed part ClpPackedMatrix::unpack(model, rowArray, iColumn); int iSet = backward_[iColumn]; if (iSet >= 0) { int iBasic = keyVariable_[iSet]; if (iBasic < model->numberColumns()) { add(model, rowArray, iBasic, -1.0); } } } /* Unpacks a column into a CoinIndexedVector ** in packed format Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ void ClpGubMatrix::unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn) const { int numberColumns = model->numberColumns(); if (iColumn < numberColumns) { // Do packed part ClpPackedMatrix::unpackPacked(model, rowArray, iColumn); int iSet = backward_[iColumn]; if (iSet >= 0) { // columns are in order int iBasic = keyVariable_[iSet]; if (iBasic < numberColumns) { int number = rowArray->getNumElements(); const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); double * array = rowArray->denseVector(); int * index = rowArray->getIndices(); CoinBigIndex i; int numberOld = number; int lastIndex = 0; int next = index[lastIndex]; if (!rowScale) { for (i = columnStart[iBasic]; i < columnStart[iBasic] + columnLength[iBasic]; i++) { int iRow = row[i]; while (iRow > next) { lastIndex++; if (lastIndex == numberOld) next = matrix_->getNumRows(); else next = index[lastIndex]; } if (iRow < next) { array[number] = -elementByColumn[i]; index[number++] = iRow; } else { assert (iRow == next); array[lastIndex] -= elementByColumn[i]; if (!array[lastIndex]) array[lastIndex] = 1.0e-100; } } } else { // apply scaling double scale = model->columnScale()[iBasic]; for (i = columnStart[iBasic]; i < columnStart[iBasic] + columnLength[iBasic]; i++) { int iRow = row[i]; while (iRow > next) { lastIndex++; if (lastIndex == numberOld) next = matrix_->getNumRows(); else next = index[lastIndex]; } if (iRow < next) { array[number] = -elementByColumn[i] * scale * rowScale[iRow]; index[number++] = iRow; } else { assert (iRow == next); array[lastIndex] -= elementByColumn[i] * scale * rowScale[iRow]; if (!array[lastIndex]) array[lastIndex] = 1.0e-100; } } } rowArray->setNumElements(number); } } } else { // key slack entering int iBasic = keyVariable_[gubSlackIn_]; assert (iBasic < numberColumns); int number = 0; const double * rowScale = model->rowScale(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * elementByColumn = matrix_->getElements(); double * array = rowArray->denseVector(); int * index = rowArray->getIndices(); CoinBigIndex i; if (!rowScale) { for (i = columnStart[iBasic]; i < columnStart[iBasic] + columnLength[iBasic]; i++) { int iRow = row[i]; array[number] = elementByColumn[i]; index[number++] = iRow; } } else { // apply scaling double scale = model->columnScale()[iBasic]; for (i = columnStart[iBasic]; i < columnStart[iBasic] + columnLength[iBasic]; i++) { int iRow = row[i]; array[number] = elementByColumn[i] * scale * rowScale[iRow]; index[number++] = iRow; } } rowArray->setNumElements(number); rowArray->setPacked(); } } /* Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ void ClpGubMatrix::add(const ClpSimplex * model, CoinIndexedVector * rowArray, int iColumn, double multiplier) const { assert (iColumn < model->numberColumns()); // Do packed part ClpPackedMatrix::add(model, rowArray, iColumn, multiplier); int iSet = backward_[iColumn]; if (iSet >= 0 && iColumn != keyVariable_[iSet]) { ClpPackedMatrix::add(model, rowArray, keyVariable_[iSet], -multiplier); } } /* Adds multiple of a column into an array */ void ClpGubMatrix::add(const ClpSimplex * model, double * array, int iColumn, double multiplier) const { assert (iColumn < model->numberColumns()); // Do packed part ClpPackedMatrix::add(model, array, iColumn, multiplier); if (iColumn < model->numberColumns()) { int iSet = backward_[iColumn]; if (iSet >= 0 && iColumn != keyVariable_[iSet] && keyVariable_[iSet] < model->numberColumns()) { ClpPackedMatrix::add(model, array, keyVariable_[iSet], -multiplier); } } } // Partial pricing void ClpGubMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; if (numberSets_) { // Do packed part before gub int numberColumns = matrix_->getNumCols(); double ratio = static_cast (firstGub_) / static_cast (numberColumns); ClpPackedMatrix::partialPricing(model, startFraction * ratio, endFraction * ratio, bestSequence, numberWanted); if (numberWanted || minimumGoodReducedCosts_ < -1) { // do gub const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); const double * rowScale = model->rowScale(); const double * columnScale = model->columnScale(); int iSequence; CoinBigIndex j; double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); const double * cost = model->costRegion(); double bestDj; int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); if (bestSequence >= 0) bestDj = fabs(this->reducedCost(model, bestSequence)); else bestDj = tolerance; int sequenceOut = model->sequenceOut(); int saveSequence = bestSequence; int startG = firstGub_ + static_cast (startFraction * (lastGub_ - firstGub_)); int endG = firstGub_ + static_cast (endFraction * (lastGub_ - firstGub_)); endG = CoinMin(lastGub_, endG + 1); // If nothing found yet can go all the way to end int endAll = endG; if (bestSequence < 0 && !startG) endAll = lastGub_; int minSet = minimumObjectsScan_ < 0 ? 5 : minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ == -1 ? 5 : minimumGoodReducedCosts_; int nSets = 0; int iSet = -1; double djMod = 0.0; double infeasibilityCost = model->infeasibilityCost(); if (rowScale) { double bestDjMod = 0.0; // scaled for (iSequence = startG; iSequence < endAll; iSequence++) { if (numberWanted + minNeg < originalWanted_ && nSets > minSet) { // give up numberWanted = 0; break; } else if (iSequence == endG && bestSequence >= 0) { break; } if (backward_[iSequence] != iSet) { // get pi on gub row iSet = backward_[iSequence]; if (iSet >= 0) { nSets++; int iBasic = keyVariable_[iSet]; if (iBasic >= numberColumns) { djMod = - weight(iSet) * infeasibilityCost; } else { // get dj without assert (model->getStatus(iBasic) == ClpSimplex::basic); djMod = 0.0; // scaled for (j = startColumn[iBasic]; j < startColumn[iBasic] + length[iBasic]; j++) { int jRow = row[j]; djMod -= duals[jRow] * element[j] * rowScale[jRow]; } // allow for scaling djMod += cost[iBasic] / columnScale[iBasic]; // See if gub slack possible - dj is djMod if (getStatus(iSet) == ClpSimplex::atLowerBound) { double value = -djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet) == ClpSimplex::atUpperBound) { double value = djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } } else { // not in set djMod = 0.0; } } if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = -djMod; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = fabs(cost[iSequence] + value * columnScale[iSequence]); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = -djMod; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = cost[iSequence] + value * columnScale[iSequence]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = -djMod; // scaled for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } value = -(cost[iSequence] + value * columnScale[iSequence]); if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } if (bestSequence != saveSequence) { if (bestSequence < numberRows + numberColumns) { // recompute dj double value = bestDjMod; // scaled for (j = startColumn[bestSequence]; j < startColumn[bestSequence] + length[bestSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j] * rowScale[jRow]; } reducedCost[bestSequence] = cost[bestSequence] + value * columnScale[bestSequence]; gubSlackIn_ = -1; } else { // slack - make last column gubSlackIn_ = bestSequence - numberRows - numberColumns; bestSequence = numberColumns + 2 * numberRows; reducedCost[bestSequence] = bestDjMod; model->setStatus(bestSequence, getStatus(gubSlackIn_)); if (getStatus(gubSlackIn_) == ClpSimplex::atUpperBound) model->solutionRegion()[bestSequence] = upper_[gubSlackIn_]; else model->solutionRegion()[bestSequence] = lower_[gubSlackIn_]; model->lowerRegion()[bestSequence] = lower_[gubSlackIn_]; model->upperRegion()[bestSequence] = upper_[gubSlackIn_]; model->costRegion()[bestSequence] = 0.0; } savedBestSequence_ = bestSequence; savedBestDj_ = reducedCost[savedBestSequence_]; } } else { double bestDjMod = 0.0; //printf("iteration %d start %d end %d - wanted %d\n",model->numberIterations(), // startG,endG,numberWanted); for (iSequence = startG; iSequence < endG; iSequence++) { if (numberWanted + minNeg < originalWanted_ && nSets > minSet) { // give up numberWanted = 0; break; } else if (iSequence == endG && bestSequence >= 0) { break; } if (backward_[iSequence] != iSet) { // get pi on gub row iSet = backward_[iSequence]; if (iSet >= 0) { nSets++; int iBasic = keyVariable_[iSet]; if (iBasic >= numberColumns) { djMod = - weight(iSet) * infeasibilityCost; } else { // get dj without assert (model->getStatus(iBasic) == ClpSimplex::basic); djMod = 0.0; for (j = startColumn[iBasic]; j < startColumn[iBasic] + length[iBasic]; j++) { int jRow = row[j]; djMod -= duals[jRow] * element[j]; } djMod += cost[iBasic]; // See if gub slack possible - dj is djMod if (getStatus(iSet) == ClpSimplex::atLowerBound) { double value = -djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet) == ClpSimplex::atUpperBound) { double value = djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = numberRows + numberColumns + iSet; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } } else { // not in set djMod = 0.0; } } if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = cost[iSequence] - djMod; for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } value = fabs(value); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence] - djMod; for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = cost[iSequence] - djMod; for (j = startColumn[iSequence]; j < startColumn[iSequence] + length[iSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; bestDjMod = djMod; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } if (bestSequence != saveSequence) { if (bestSequence < numberRows + numberColumns) { // recompute dj double value = cost[bestSequence] - bestDjMod; for (j = startColumn[bestSequence]; j < startColumn[bestSequence] + length[bestSequence]; j++) { int jRow = row[j]; value -= duals[jRow] * element[j]; } //printf("price struct %d - dj %g gubpi %g\n",bestSequence,value,bestDjMod); reducedCost[bestSequence] = value; gubSlackIn_ = -1; } else { // slack - make last column gubSlackIn_ = bestSequence - numberRows - numberColumns; bestSequence = numberColumns + 2 * numberRows; reducedCost[bestSequence] = bestDjMod; //printf("price slack %d - gubpi %g\n",gubSlackIn_,bestDjMod); model->setStatus(bestSequence, getStatus(gubSlackIn_)); if (getStatus(gubSlackIn_) == ClpSimplex::atUpperBound) model->solutionRegion()[bestSequence] = upper_[gubSlackIn_]; else model->solutionRegion()[bestSequence] = lower_[gubSlackIn_]; model->lowerRegion()[bestSequence] = lower_[gubSlackIn_]; model->upperRegion()[bestSequence] = upper_[gubSlackIn_]; model->costRegion()[bestSequence] = 0.0; } } } // See if may be finished if (startG == firstGub_ && bestSequence < 0) infeasibilityWeight_ = model_->infeasibilityCost(); else if (bestSequence >= 0) infeasibilityWeight_ = -1.0; } if (numberWanted) { // Do packed part after gub double offset = static_cast (lastGub_) / static_cast (numberColumns); double ratio = static_cast (numberColumns) / static_cast (numberColumns) - offset; double start2 = offset + ratio * startFraction; double end2 = CoinMin(1.0, offset + ratio * endFraction + 1.0e-6); ClpPackedMatrix::partialPricing(model, start2, end2, bestSequence, numberWanted); } } else { // no gub ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); } if (bestSequence >= 0) infeasibilityWeight_ = -1.0; // not optimal currentWanted_ = numberWanted; } /* expands an updated column to allow for extra rows which the main solver does not know about and returns number added. */ int ClpGubMatrix::extendUpdated(ClpSimplex * model, CoinIndexedVector * update, int mode) { // I think we only need to bother about sets with two in basis or incoming set int number = update->getNumElements(); double * array = update->denseVector(); int * index = update->getIndices(); int i; assert (!number || update->packedMode()); int * pivotVariable = model->pivotVariable(); int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); int numberTotal = numberRows + numberColumns; int sequenceIn = model->sequenceIn(); int returnCode = 0; int iSetIn; if (sequenceIn < numberColumns) { iSetIn = backward_[sequenceIn]; gubSlackIn_ = -1; // in case set } else if (sequenceIn < numberRows + numberColumns) { iSetIn = -1; gubSlackIn_ = -1; // in case set } else { iSetIn = gubSlackIn_; } double * lower = model->lowerRegion(); double * upper = model->upperRegion(); double * cost = model->costRegion(); double * solution = model->solutionRegion(); int number2 = number; if (!mode) { double primalTolerance = model->primalTolerance(); double infeasibilityCost = model->infeasibilityCost(); // extend saveNumber_ = number; for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable[iRow]; if (iPivot < numberColumns) { int iSet = backward_[iPivot]; if (iSet >= 0) { // two (or more) in set int iIndex = toIndex_[iSet]; double otherValue = array[i]; double value; if (iIndex < 0) { toIndex_[iSet] = number2; int iNew = number2 - number; fromIndex_[number2-number] = iSet; iIndex = number2; index[number2] = numberRows + iNew; // do key stuff int iKey = keyVariable_[iSet]; if (iKey < numberColumns) { // Save current cost of key changeCost_[number2-number] = cost[iKey]; if (iSet != iSetIn) value = 0.0; else if (iSetIn != gubSlackIn_) value = 1.0; else value = -1.0; pivotVariable[numberRows+iNew] = iKey; // Do I need to recompute? double sol; assert (getStatus(iSet) != ClpSimplex::basic); if (getStatus(iSet) == ClpSimplex::atLowerBound) sol = lower_[iSet]; else sol = upper_[iSet]; if ((gubType_ & 8) != 0) { int iColumn = next_[iKey]; // sum all non-key variables while(iColumn >= 0) { sol -= solution[iColumn]; iColumn = next_[iColumn]; } } else { int stop = -(iKey + 1); int iColumn = next_[iKey]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; sol -= solution[iColumn]; iColumn = next_[iColumn]; } } solution[iKey] = sol; if (model->algorithm() > 0) model->nonLinearCost()->setOne(iKey, sol); //assert (fabs(sol-solution[iKey])<1.0e-3); } else { // gub slack is basic // Save current cost of key changeCost_[number2-number] = -weight(iSet) * infeasibilityCost; otherValue = - otherValue; //allow for - sign on slack if (iSet != iSetIn) value = 0.0; else value = -1.0; pivotVariable[numberRows+iNew] = iNew + numberTotal; model->djRegion()[iNew+numberTotal] = 0.0; double sol = 0.0; if ((gubType_ & 8) != 0) { int iColumn = next_[iKey]; // sum all non-key variables while(iColumn >= 0) { sol += solution[iColumn]; iColumn = next_[iColumn]; } } else { int stop = -(iKey + 1); int iColumn = next_[iKey]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; sol += solution[iColumn]; iColumn = next_[iColumn]; } } solution[iNew+numberTotal] = sol; // and do cost in nonLinearCost if (model->algorithm() > 0) model->nonLinearCost()->setOne(iNew + numberTotal, sol, lower_[iSet], upper_[iSet]); if (sol > upper_[iSet] + primalTolerance) { setAbove(iSet); lower[iNew+numberTotal] = upper_[iSet]; upper[iNew+numberTotal] = COIN_DBL_MAX; } else if (sol < lower_[iSet] - primalTolerance) { setBelow(iSet); lower[iNew+numberTotal] = -COIN_DBL_MAX; upper[iNew+numberTotal] = lower_[iSet]; } else { setFeasible(iSet); lower[iNew+numberTotal] = lower_[iSet]; upper[iNew+numberTotal] = upper_[iSet]; } cost[iNew+numberTotal] = weight(iSet) * infeasibilityCost; } number2++; } else { value = array[iIndex]; int iKey = keyVariable_[iSet]; if (iKey >= numberColumns) otherValue = - otherValue; //allow for - sign on slack } value -= otherValue; array[iIndex] = value; } } } if (iSetIn >= 0 && toIndex_[iSetIn] < 0) { // Do incoming update->setPacked(); // just in case no elements toIndex_[iSetIn] = number2; int iNew = number2 - number; fromIndex_[number2-number] = iSetIn; // Save current cost of key double currentCost; int key = keyVariable_[iSetIn]; if (key < numberColumns) currentCost = cost[key]; else currentCost = -weight(iSetIn) * infeasibilityCost; changeCost_[number2-number] = currentCost; index[number2] = numberRows + iNew; // do key stuff int iKey = keyVariable_[iSetIn]; if (iKey < numberColumns) { if (gubSlackIn_ < 0) array[number2] = 1.0; else array[number2] = -1.0; pivotVariable[numberRows+iNew] = iKey; // Do I need to recompute? double sol; assert (getStatus(iSetIn) != ClpSimplex::basic); if (getStatus(iSetIn) == ClpSimplex::atLowerBound) sol = lower_[iSetIn]; else sol = upper_[iSetIn]; if ((gubType_ & 8) != 0) { int iColumn = next_[iKey]; // sum all non-key variables while(iColumn >= 0) { sol -= solution[iColumn]; iColumn = next_[iColumn]; } } else { // bounds exist - sum over all except key int stop = -(iKey + 1); int iColumn = next_[iKey]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; sol -= solution[iColumn]; iColumn = next_[iColumn]; } } solution[iKey] = sol; if (model->algorithm() > 0) model->nonLinearCost()->setOne(iKey, sol); //assert (fabs(sol-solution[iKey])<1.0e-3); } else { // gub slack is basic array[number2] = -1.0; pivotVariable[numberRows+iNew] = iNew + numberTotal; model->djRegion()[iNew+numberTotal] = 0.0; double sol = 0.0; if ((gubType_ & 8) != 0) { int iColumn = next_[iKey]; // sum all non-key variables while(iColumn >= 0) { sol += solution[iColumn]; iColumn = next_[iColumn]; } } else { // bounds exist - sum over all except key int stop = -(iKey + 1); int iColumn = next_[iKey]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; sol += solution[iColumn]; iColumn = next_[iColumn]; } } solution[iNew+numberTotal] = sol; // and do cost in nonLinearCost if (model->algorithm() > 0) model->nonLinearCost()->setOne(iNew + numberTotal, sol, lower_[iSetIn], upper_[iSetIn]); if (sol > upper_[iSetIn] + primalTolerance) { setAbove(iSetIn); lower[iNew+numberTotal] = upper_[iSetIn]; upper[iNew+numberTotal] = COIN_DBL_MAX; } else if (sol < lower_[iSetIn] - primalTolerance) { setBelow(iSetIn); lower[iNew+numberTotal] = -COIN_DBL_MAX; upper[iNew+numberTotal] = lower_[iSetIn]; } else { setFeasible(iSetIn); lower[iNew+numberTotal] = lower_[iSetIn]; upper[iNew+numberTotal] = upper_[iSetIn]; } cost[iNew+numberTotal] = weight(iSetIn) * infeasibilityCost; } number2++; } // mark end fromIndex_[number2-number] = -1; returnCode = number2 - number; // make sure lower_ upper_ adjusted synchronize(model, 9); } else { // take off? if (number > saveNumber_) { // clear double theta = model->theta(); double * solution = model->solutionRegion(); for (i = saveNumber_; i < number; i++) { int iRow = index[i]; int iColumn = pivotVariable[iRow]; #ifdef CLP_DEBUG_PRINT printf("Column %d (set %d) lower %g, upper %g - alpha %g - old value %g, new %g (theta %g)\n", iColumn, fromIndex_[i-saveNumber_], lower[iColumn], upper[iColumn], array[i], solution[iColumn], solution[iColumn] - model->theta()*array[i], model->theta()); #endif double value = array[i]; array[i] = 0.0; int iSet = fromIndex_[i-saveNumber_]; toIndex_[iSet] = -1; if (iSet == iSetIn && iColumn < numberColumns) { // update as may need value solution[iColumn] -= theta * value; } } } #ifdef CLP_DEBUG for (i = 0; i < numberSets_; i++) assert(toIndex_[i] == -1); #endif number2 = saveNumber_; } update->setNumElements(number2); return returnCode; } /* utility primal function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpGubMatrix::primalExpanded(ClpSimplex * model, int mode) { int numberColumns = model->numberColumns(); switch (mode) { // If key variable then slot in gub rhs so will get correct contribution case 0: { int i; double * solution = model->solutionRegion(); ClpSimplex::Status iStatus; for (i = 0; i < numberSets_; i++) { int iColumn = keyVariable_[i]; if (iColumn < numberColumns) { // key is structural - where is slack iStatus = getStatus(i); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) solution[iColumn] = lower_[i]; else solution[iColumn] = upper_[i]; } } } break; // Compute values of key variables case 1: { int i; double * solution = model->solutionRegion(); //const int * columnLength = matrix_->getVectorLengths(); //const CoinBigIndex * columnStart = matrix_->getVectorStarts(); //const int * row = matrix_->getIndices(); //const double * elementByColumn = matrix_->getElements(); //int * pivotVariable = model->pivotVariable(); sumPrimalInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; double primalTolerance = model->primalTolerance(); double relaxedTolerance = primalTolerance; // we can't really trust infeasibilities if there is primal error double error = CoinMin(1.0e-2, model->largestPrimalError()); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; // but we will be using difference relaxedTolerance -= primalTolerance; sumOfRelaxedPrimalInfeasibilities_ = 0.0; for (i = 0; i < numberSets_; i++) { // Could just be over basics (esp if no bounds) int kColumn = keyVariable_[i]; double value = 0.0; if ((gubType_ & 8) != 0) { int iColumn = next_[kColumn]; // sum all non-key variables while(iColumn >= 0) { value += solution[iColumn]; iColumn = next_[iColumn]; } } else { // bounds exist - sum over all except key int stop = -(kColumn + 1); int iColumn = next_[kColumn]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; value += solution[iColumn]; iColumn = next_[iColumn]; } } if (kColumn < numberColumns) { // make sure key is basic - so will be skipped in values pass model->setStatus(kColumn, ClpSimplex::basic); // feasibility will be done later assert (getStatus(i) != ClpSimplex::basic); if (getStatus(i) == ClpSimplex::atUpperBound) solution[kColumn] = upper_[i] - value; else solution[kColumn] = lower_[i] - value; //printf("Value of key structural %d for set %d is %g\n",kColumn,i,solution[kColumn]); } else { // slack is key assert (getStatus(i) == ClpSimplex::basic); double infeasibility = 0.0; if (value > upper_[i] + primalTolerance) { infeasibility = value - upper_[i] - primalTolerance; setAbove(i); } else if (value < lower_[i] - primalTolerance) { infeasibility = lower_[i] - value - primalTolerance ; setBelow(i); } else { setFeasible(i); } //printf("Value of key slack for set %d is %g\n",i,value); if (infeasibility > 0.0) { sumPrimalInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedPrimalInfeasibilities_ += infeasibility; numberPrimalInfeasibilities_ ++; } } } } break; // Report on infeasibilities of key variables case 2: { model->setSumPrimalInfeasibilities(model->sumPrimalInfeasibilities() + sumPrimalInfeasibilities_); model->setNumberPrimalInfeasibilities(model->numberPrimalInfeasibilities() + numberPrimalInfeasibilities_); model->setSumOfRelaxedPrimalInfeasibilities(model->sumOfRelaxedPrimalInfeasibilities() + sumOfRelaxedPrimalInfeasibilities_); } break; } } /* utility dual function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpGubMatrix::dualExpanded(ClpSimplex * model, CoinIndexedVector * array, double * /*other*/, int mode) { switch (mode) { // modify costs before transposeUpdate case 0: { int i; double * cost = model->costRegion(); // not dual values yet //assert (!other); //double * work = array->denseVector(); double infeasibilityCost = model->infeasibilityCost(); int * pivotVariable = model->pivotVariable(); int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns) { int iSet = backward_[iPivot]; if (iSet >= 0) { int kColumn = keyVariable_[iSet]; double costValue; if (kColumn < numberColumns) { // structural has cost costValue = cost[kColumn]; } else { // slack is key assert (getStatus(iSet) == ClpSimplex::basic); // negative as -1.0 for slack costValue = -weight(iSet) * infeasibilityCost; } array->add(i, -costValue); // was work[i]-costValue } } } } break; // create duals for key variables (without check on dual infeasible) case 1: { // If key slack then dual 0.0 (if feasible) // dj for key is zero so that defines dual on set int i; double * dj = model->djRegion(); int numberColumns = model->numberColumns(); double infeasibilityCost = model->infeasibilityCost(); for (i = 0; i < numberSets_; i++) { int kColumn = keyVariable_[i]; if (kColumn < numberColumns) { // dj without set double value = dj[kColumn]; // Now subtract out from all dj[kColumn] = 0.0; int iColumn = next_[kColumn]; // modify all non-key variables while(iColumn >= 0) { dj[iColumn] -= value; iColumn = next_[iColumn]; } } else { // slack key - may not be feasible assert (getStatus(i) == ClpSimplex::basic); // negative as -1.0 for slack double value = -weight(i) * infeasibilityCost; if (value) { int iColumn = next_[kColumn]; // modify all non-key variables basic while(iColumn >= 0) { dj[iColumn] -= value; iColumn = next_[iColumn]; } } } } } break; // as 1 but check slacks and compute djs case 2: { // If key slack then dual 0.0 // If not then slack could be dual infeasible // dj for key is zero so that defines dual on set int i; // make sure fromIndex will not confuse pricing fromIndex_[0] = -1; possiblePivotKey_ = -1; // Create array int numberColumns = model->numberColumns(); int * pivotVariable = model->pivotVariable(); int numberRows = model->numberRows(); for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; if (iPivot < numberColumns) backToPivotRow_[iPivot] = i; } if (noCheck_ >= 0) { if (infeasibilityWeight_ != model->infeasibilityCost()) { // don't bother checking sumDualInfeasibilities_ = 100.0; numberDualInfeasibilities_ = 1; sumOfRelaxedDualInfeasibilities_ = 100.0; return; } } double * dj = model->djRegion(); double * dual = model->dualRowSolution(); double * cost = model->costRegion(); ClpSimplex::Status iStatus; const int * columnLength = matrix_->getVectorLengths(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * row = matrix_->getIndices(); const double * elementByColumn = matrix_->getElements(); double infeasibilityCost = model->infeasibilityCost(); sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; double dualTolerance = model->dualTolerance(); double relaxedTolerance = dualTolerance; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, model->largestDualError()); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; // but we will be using difference relaxedTolerance -= dualTolerance; sumOfRelaxedDualInfeasibilities_ = 0.0; for (i = 0; i < numberSets_; i++) { int kColumn = keyVariable_[i]; if (kColumn < numberColumns) { // dj without set double value = cost[kColumn]; for (CoinBigIndex j = columnStart[kColumn]; j < columnStart[kColumn] + columnLength[kColumn]; j++) { int iRow = row[j]; value -= dual[iRow] * elementByColumn[j]; } // Now subtract out from all dj[kColumn] -= value; int stop = -(kColumn + 1); kColumn = next_[kColumn]; while (kColumn != stop) { if (kColumn < 0) kColumn = -kColumn - 1; double djValue = dj[kColumn] - value; dj[kColumn] = djValue;; double infeasibility = 0.0; iStatus = model->getStatus(kColumn); if (iStatus == ClpSimplex::atLowerBound) { if (djValue < -dualTolerance) infeasibility = -djValue - dualTolerance; } else if (iStatus == ClpSimplex::atUpperBound) { // at upper bound if (djValue > dualTolerance) infeasibility = djValue - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } kColumn = next_[kColumn]; } // check slack iStatus = getStatus(i); assert (iStatus != ClpSimplex::basic); double infeasibility = 0.0; // dj of slack is -(-1.0)value if (iStatus == ClpSimplex::atLowerBound) { if (value < -dualTolerance) infeasibility = -value - dualTolerance; } else if (iStatus == ClpSimplex::atUpperBound) { // at upper bound if (value > dualTolerance) infeasibility = value - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } else { // slack key - may not be feasible assert (getStatus(i) == ClpSimplex::basic); // negative as -1.0 for slack double value = -weight(i) * infeasibilityCost; if (value) { // Now subtract out from all int kColumn = i + numberColumns; int stop = -(kColumn + 1); kColumn = next_[kColumn]; while (kColumn != stop) { if (kColumn < 0) kColumn = -kColumn - 1; double djValue = dj[kColumn] - value; dj[kColumn] = djValue;; double infeasibility = 0.0; iStatus = model->getStatus(kColumn); if (iStatus == ClpSimplex::atLowerBound) { if (djValue < -dualTolerance) infeasibility = -djValue - dualTolerance; } else if (iStatus == ClpSimplex::atUpperBound) { // at upper bound if (djValue > dualTolerance) infeasibility = djValue - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } kColumn = next_[kColumn]; } } } } // and get statistics for column generation synchronize(model, 4); infeasibilityWeight_ = -1.0; } break; // Report on infeasibilities of key variables case 3: { model->setSumDualInfeasibilities(model->sumDualInfeasibilities() + sumDualInfeasibilities_); model->setNumberDualInfeasibilities(model->numberDualInfeasibilities() + numberDualInfeasibilities_); model->setSumOfRelaxedDualInfeasibilities(model->sumOfRelaxedDualInfeasibilities() + sumOfRelaxedDualInfeasibilities_); } break; // modify costs before transposeUpdate for partial pricing case 4: { // First compute new costs etc for interesting gubs int iLook = 0; int iSet = fromIndex_[0]; double primalTolerance = model->primalTolerance(); const double * cost = model->costRegion(); double * solution = model->solutionRegion(); double infeasibilityCost = model->infeasibilityCost(); int numberColumns = model->numberColumns(); int numberChanged = 0; int * pivotVariable = model->pivotVariable(); while (iSet >= 0) { int key = keyVariable_[iSet]; double value = 0.0; // sum over all except key if ((gubType_ & 8) != 0) { int iColumn = next_[key]; // sum all non-key variables while(iColumn >= 0) { value += solution[iColumn]; iColumn = next_[iColumn]; } } else { // bounds exist - sum over all except key int stop = -(key + 1); int iColumn = next_[key]; // sum all non-key variables while(iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; value += solution[iColumn]; iColumn = next_[iColumn]; } } double costChange; double oldCost = changeCost_[iLook]; if (key < numberColumns) { assert (getStatus(iSet) != ClpSimplex::basic); double sol; if (getStatus(iSet) == ClpSimplex::atUpperBound) sol = upper_[iSet] - value; else sol = lower_[iSet] - value; solution[key] = sol; // fix up cost model->nonLinearCost()->setOne(key, sol); #ifdef CLP_DEBUG_PRINT printf("yy Value of key structural %d for set %d is %g - cost %g old cost %g\n", key, iSet, sol, cost[key], oldCost); #endif costChange = cost[key] - oldCost; } else { // slack is key if (value > upper_[iSet] + primalTolerance) { setAbove(iSet); } else if (value < lower_[iSet] - primalTolerance) { setBelow(iSet); } else { setFeasible(iSet); } // negative as -1.0 for slack costChange = -weight(iSet) * infeasibilityCost - oldCost; #ifdef CLP_DEBUG_PRINT printf("yy Value of key slack for set %d is %g - cost %g old cost %g\n", iSet, value, weight(iSet)*infeasibilityCost, oldCost); #endif } if (costChange) { fromIndex_[numberChanged] = iSet; toIndex_[iSet] = numberChanged; changeCost_[numberChanged++] = costChange; } iSet = fromIndex_[++iLook]; } if (numberChanged || possiblePivotKey_ >= 0) { // first do those in list already int number = array->getNumElements(); array->setPacked(); int i; double * work = array->denseVector(); int * which = array->getIndices(); for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (iPivot < numberColumns) { int iSet = backward_[iPivot]; if (iSet >= 0 && toIndex_[iSet] >= 0) { double newValue = work[i] + changeCost_[toIndex_[iSet]]; if (!newValue) newValue = 1.0e-100; work[i] = newValue; // mark as done backward_[iPivot] = -1; } } if (possiblePivotKey_ == iRow) { double newValue = work[i] - model->dualIn(); if (!newValue) newValue = 1.0e-100; work[i] = newValue; possiblePivotKey_ = -1; } } // now do rest and clean up for (i = 0; i < numberChanged; i++) { int iSet = fromIndex_[i]; int key = keyVariable_[iSet]; int iColumn = next_[key]; double change = changeCost_[i]; while (iColumn >= 0) { if (backward_[iColumn] >= 0) { int iRow = backToPivotRow_[iColumn]; assert (iRow >= 0); work[number] = change; if (possiblePivotKey_ == iRow) { double newValue = work[number] - model->dualIn(); if (!newValue) newValue = 1.0e-100; work[number] = newValue; possiblePivotKey_ = -1; } which[number++] = iRow; } else { // reset backward_[iColumn] = iSet; } iColumn = next_[iColumn]; } toIndex_[iSet] = -1; } if (possiblePivotKey_ >= 0) { work[number] = -model->dualIn(); which[number++] = possiblePivotKey_; possiblePivotKey_ = -1; } fromIndex_[0] = -1; array->setNumElements(number); } } break; } } // This is local to Gub to allow synchronization when status is good int ClpGubMatrix::synchronize(ClpSimplex *, int) { return 0; } /* general utility function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ int ClpGubMatrix::generalExpanded(ClpSimplex * model, int mode, int &number) { int returnCode = 0; int numberColumns = model->numberColumns(); switch (mode) { // Fill in pivotVariable but not for key variables case 0: { if (!next_ ) { // do ordering assert (!rhsOffset_); // create and do gub crash useEffectiveRhs(model, false); } int i; int numberBasic = number; // Use different array so can build from true pivotVariable_ //int * pivotVariable = model->pivotVariable(); int * pivotVariable = model->rowArray(0)->getIndices(); for (i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) { int iSet = backward_[i]; if (iSet < 0 || i != keyVariable_[iSet]) pivotVariable[numberBasic++] = i; } } number = numberBasic; if (model->numberIterations()) assert (number == model->numberRows()); } break; // Make all key variables basic case 1: { int i; for (i = 0; i < numberSets_; i++) { int iColumn = keyVariable_[i]; if (iColumn < numberColumns) model->setColumnStatus(iColumn, ClpSimplex::basic); } } break; // Do initial extra rows + maximum basic case 2: { returnCode = getNumRows() + 1; number = model->numberRows() + numberSets_; } break; // Before normal replaceColumn case 3: { int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); int pivotRow = model->pivotRow(); if (gubSlackIn_ >= 0) assert (sequenceIn > numberRows + numberColumns); if (sequenceIn == sequenceOut) return -1; int iSetIn = -1; int iSetOut = -1; if (sequenceOut < numberColumns) { iSetOut = backward_[sequenceOut]; } else if (sequenceOut >= numberRows + numberColumns) { assert (pivotRow >= numberRows); int iExtra = pivotRow - numberRows; assert (iExtra >= 0); if (iSetOut < 0) iSetOut = fromIndex_[iExtra]; else assert(iSetOut == fromIndex_[iExtra]); } if (sequenceIn < numberColumns) { iSetIn = backward_[sequenceIn]; } else if (gubSlackIn_ >= 0) { iSetIn = gubSlackIn_; } possiblePivotKey_ = -1; number = 0; // say do ordinary int * pivotVariable = model->pivotVariable(); if (pivotRow >= numberRows) { int iExtra = pivotRow - numberRows; //const int * length = matrix_->getVectorLengths(); assert (sequenceOut >= numberRows + numberColumns || sequenceOut == keyVariable_[iSetOut]); int incomingColumn = sequenceIn; // to be used in updates if (iSetIn != iSetOut) { // We need to find a possible pivot for incoming // look through rowArray_[1] int n = model->rowArray(1)->getNumElements(); int * which = model->rowArray(1)->getIndices(); double * array = model->rowArray(1)->denseVector(); double bestAlpha = 1.0e-5; //int shortest=numberRows+1; for (int i = 0; i < n; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (iPivot < numberColumns && backward_[iPivot] == iSetOut) { if (fabs(array[i]) > fabs(bestAlpha)) { bestAlpha = array[i]; possiblePivotKey_ = iRow; } } } assert (possiblePivotKey_ >= 0); // could set returnCode=4 number = 1; if (sequenceIn >= numberRows + numberColumns) { number = 3; // need swap as gub slack in and must become key // is this best way int key = keyVariable_[iSetIn]; assert (key < numberColumns); // check other basic int iColumn = next_[key]; // set new key to be used by unpack keyVariable_[iSetIn] = iSetIn + numberColumns; // change cost in changeCost { int iLook = 0; int iSet = fromIndex_[0]; while (iSet >= 0) { if (iSet == iSetIn) { changeCost_[iLook] = 0.0; break; } iSet = fromIndex_[++iLook]; } } while (iColumn >= 0) { if (iColumn != sequenceOut) { // need partial ftran and skip accuracy check in replaceColumn #ifdef CLP_DEBUG_PRINT printf("TTTTTry 5\n"); #endif int iRow = backToPivotRow_[iColumn]; assert (iRow >= 0); unpack(model, model->rowArray(3), iColumn); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(3)); double alpha = model->rowArray(3)->denseVector()[iRow]; //if (!alpha) //printf("zero alpha a\n"); int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(3), iRow, alpha); returnCode = CoinMax(updateStatus, returnCode); model->rowArray(3)->clear(); if (returnCode) break; } iColumn = next_[iColumn]; } if (!returnCode) { // now factorization looks as if key is out // pivot back in #ifdef CLP_DEBUG_PRINT printf("TTTTTry 6\n"); #endif unpack(model, model->rowArray(3), key); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(3)); pivotRow = possiblePivotKey_; double alpha = model->rowArray(3)->denseVector()[pivotRow]; //if (!alpha) //printf("zero alpha b\n"); int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(3), pivotRow, alpha); returnCode = CoinMax(updateStatus, returnCode); model->rowArray(3)->clear(); } // restore key keyVariable_[iSetIn] = key; // now alternate column can replace key on out incomingColumn = pivotVariable[possiblePivotKey_]; } else { #ifdef CLP_DEBUG_PRINT printf("TTTTTTry 4 %d\n", possiblePivotKey_); #endif int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(1), possiblePivotKey_, bestAlpha); returnCode = CoinMax(updateStatus, returnCode); incomingColumn = pivotVariable[possiblePivotKey_]; } //returnCode=4; // need swap } else { // key swap number = -1; } int key = keyVariable_[iSetOut]; if (key < numberColumns) assert(key == sequenceOut); // check if any other basic int iColumn = next_[key]; if (returnCode) iColumn = -1; // skip if error on previous // set new key to be used by unpack if (incomingColumn < numberColumns) keyVariable_[iSetOut] = incomingColumn; else keyVariable_[iSetOut] = iSetIn + numberColumns; double * cost = model->costRegion(); if (possiblePivotKey_ < 0) { double dj = model->djRegion()[sequenceIn] - cost[sequenceIn]; changeCost_[iExtra] = -dj; #ifdef CLP_DEBUG_PRINT printf("modifying changeCost %d by %g - cost %g\n", iExtra, dj, cost[sequenceIn]); #endif } while (iColumn >= 0) { if (iColumn != incomingColumn) { number = -2; // need partial ftran and skip accuracy check in replaceColumn #ifdef CLP_DEBUG_PRINT printf("TTTTTTry 1\n"); #endif int iRow = backToPivotRow_[iColumn]; assert (iRow >= 0 && iRow < numberRows); unpack(model, model->rowArray(3), iColumn); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(3)); double * array = model->rowArray(3)->denseVector(); double alpha = array[iRow]; //if (!alpha) //printf("zero alpha d\n"); int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(3), iRow, alpha); returnCode = CoinMax(updateStatus, returnCode); model->rowArray(3)->clear(); if (returnCode) break; } iColumn = next_[iColumn]; } // restore key keyVariable_[iSetOut] = key; } else if (sequenceIn >= numberRows + numberColumns) { number = 2; //returnCode=4; // need swap as gub slack in and must become key // is this best way int key = keyVariable_[iSetIn]; assert (key < numberColumns); // check other basic int iColumn = next_[key]; // set new key to be used by unpack keyVariable_[iSetIn] = iSetIn + numberColumns; // change cost in changeCost { int iLook = 0; int iSet = fromIndex_[0]; while (iSet >= 0) { if (iSet == iSetIn) { changeCost_[iLook] = 0.0; break; } iSet = fromIndex_[++iLook]; } } while (iColumn >= 0) { if (iColumn != sequenceOut) { // need partial ftran and skip accuracy check in replaceColumn #ifdef CLP_DEBUG_PRINT printf("TTTTTry 2\n"); #endif int iRow = backToPivotRow_[iColumn]; assert (iRow >= 0); unpack(model, model->rowArray(3), iColumn); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(3)); double alpha = model->rowArray(3)->denseVector()[iRow]; //if (!alpha) //printf("zero alpha e\n"); int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(3), iRow, alpha); returnCode = CoinMax(updateStatus, returnCode); model->rowArray(3)->clear(); if (returnCode) break; } iColumn = next_[iColumn]; } if (!returnCode) { // now factorization looks as if key is out // pivot back in #ifdef CLP_DEBUG_PRINT printf("TTTTTry 3\n"); #endif unpack(model, model->rowArray(3), key); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(3)); double alpha = model->rowArray(3)->denseVector()[pivotRow]; //if (!alpha) //printf("zero alpha f\n"); int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(3), pivotRow, alpha); returnCode = CoinMax(updateStatus, returnCode); model->rowArray(3)->clear(); } // restore key keyVariable_[iSetIn] = key; } else { // normal - but might as well do here returnCode = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(1), model->pivotRow(), model->alpha()); } } #ifdef CLP_DEBUG_PRINT printf("Update type after %d - status %d - pivot row %d\n", number, returnCode, model->pivotRow()); #endif // see if column generation says time to re-factorize returnCode = CoinMax(returnCode, synchronize(model, 5)); number = -1; // say no need for normal replaceColumn break; // To see if can dual or primal case 4: { returnCode = 1; } break; // save status case 5: { synchronize(model, 0); CoinMemcpyN(status_, numberSets_, saveStatus_); CoinMemcpyN(keyVariable_, numberSets_, savedKeyVariable_); } break; // restore status case 6: { CoinMemcpyN(saveStatus_, numberSets_, status_); CoinMemcpyN(savedKeyVariable_, numberSets_, keyVariable_); // restore firstAvailable_ synchronize(model, 7); // redo next_ int i; int * last = new int[numberSets_]; for (i = 0; i < numberSets_; i++) { int iKey = keyVariable_[i]; assert(iKey >= numberColumns || backward_[iKey] == i); last[i] = iKey; // make sure basic //if (iKeysetStatus(iKey,ClpSimplex::basic); } for (i = 0; i < numberColumns; i++) { int iSet = backward_[i]; if (iSet >= 0) { next_[last[iSet]] = i; last[iSet] = i; } } for (i = 0; i < numberSets_; i++) { next_[last[i]] = -(keyVariable_[i] + 1); redoSet(model, keyVariable_[i], keyVariable_[i], i); } delete [] last; // redo pivotVariable int * pivotVariable = model->pivotVariable(); int iRow; int numberBasic = 0; int numberRows = model->numberRows(); for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) == ClpSimplex::basic) { numberBasic++; pivotVariable[iRow] = iRow + numberColumns; } else { pivotVariable[iRow] = -1; } } i = 0; int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getStatus(iColumn) == ClpSimplex::basic) { int iSet = backward_[iColumn]; if (iSet < 0 || keyVariable_[iSet] != iColumn) { while (pivotVariable[i] >= 0) { i++; assert (i < numberRows); } pivotVariable[i] = iColumn; backToPivotRow_[iColumn] = i; numberBasic++; } } } assert (numberBasic == numberRows); rhsOffset(model, true); } break; // flag a variable case 7: { assert (number == model->sequenceIn()); synchronize(model, 1); synchronize(model, 8); } break; // unflag all variables case 8: { returnCode = synchronize(model, 2); } break; // redo costs in primal case 9: { returnCode = synchronize(model, 3); } break; // return 1 if there may be changing bounds on variable (column generation) case 10: { returnCode = synchronize(model, 6); } break; // make sure set is clean case 11: { assert (number == model->sequenceIn()); returnCode = synchronize(model, 8); } break; default: break; } return returnCode; } // Sets up an effective RHS and does gub crash if needed void ClpGubMatrix::useEffectiveRhs(ClpSimplex * model, bool cheapest) { // Do basis - cheapest or slack if feasible (unless cheapest set) int longestSet = 0; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) longestSet = CoinMax(longestSet, end_[iSet] - start_[iSet]); double * upper = new double[longestSet+1]; double * cost = new double[longestSet+1]; double * lower = new double[longestSet+1]; double * solution = new double[longestSet+1]; assert (!next_); int numberColumns = getNumCols(); const int * columnLength = matrix_->getVectorLengths(); const double * columnLower = model->lowerRegion(); const double * columnUpper = model->upperRegion(); double * columnSolution = model->solutionRegion(); const double * objective = model->costRegion(); int numberRows = getNumRows(); toIndex_ = new int[numberSets_]; for (iSet = 0; iSet < numberSets_; iSet++) toIndex_[iSet] = -1; fromIndex_ = new int [getNumRows()+1]; double tolerance = model->primalTolerance(); bool noNormalBounds = true; gubType_ &= ~8; bool gotBasis = false; for (iSet = 0; iSet < numberSets_; iSet++) { if (keyVariable_[iSet] < numberColumns) gotBasis = true; CoinBigIndex j; CoinBigIndex iStart = start_[iSet]; CoinBigIndex iEnd = end_[iSet]; for (j = iStart; j < iEnd; j++) { if (columnLower[j] && columnLower[j] > -1.0e20) noNormalBounds = false; if (columnUpper[j] && columnUpper[j] < 1.0e20) noNormalBounds = false; } } if (noNormalBounds) gubType_ |= 8; if (!gotBasis) { for (iSet = 0; iSet < numberSets_; iSet++) { CoinBigIndex j; int numberBasic = 0; int iBasic = -1; CoinBigIndex iStart = start_[iSet]; CoinBigIndex iEnd = end_[iSet]; // find one with smallest length int smallest = numberRows + 1; double value = 0.0; for (j = iStart; j < iEnd; j++) { if (model->getStatus(j) == ClpSimplex::basic) { if (columnLength[j] < smallest) { smallest = columnLength[j]; iBasic = j; } numberBasic++; } value += columnSolution[j]; } bool done = false; if (numberBasic > 1 || (numberBasic == 1 && getStatus(iSet) == ClpSimplex::basic)) { if (getStatus(iSet) == ClpSimplex::basic) iBasic = iSet + numberColumns; // slack key - use done = true; } else if (numberBasic == 1) { // see if can be key double thisSolution = columnSolution[iBasic]; if (thisSolution > columnUpper[iBasic]) { value -= thisSolution - columnUpper[iBasic]; thisSolution = columnUpper[iBasic]; columnSolution[iBasic] = thisSolution; } if (thisSolution < columnLower[iBasic]) { value -= thisSolution - columnLower[iBasic]; thisSolution = columnLower[iBasic]; columnSolution[iBasic] = thisSolution; } // try setting slack to a bound assert (upper_[iSet] < 1.0e20 || lower_[iSet] > -1.0e20); double cost1 = COIN_DBL_MAX; int whichBound = -1; if (upper_[iSet] < 1.0e20) { // try slack at ub double newBasic = thisSolution + upper_[iSet] - value; if (newBasic >= columnLower[iBasic] - tolerance && newBasic <= columnUpper[iBasic] + tolerance) { // can go whichBound = 1; cost1 = newBasic * objective[iBasic]; // But if exact then may be good solution if (fabs(upper_[iSet] - value) < tolerance) cost1 = -COIN_DBL_MAX; } } if (lower_[iSet] > -1.0e20) { // try slack at lb double newBasic = thisSolution + lower_[iSet] - value; if (newBasic >= columnLower[iBasic] - tolerance && newBasic <= columnUpper[iBasic] + tolerance) { // can go but is it cheaper double cost2 = newBasic * objective[iBasic]; // But if exact then may be good solution if (fabs(lower_[iSet] - value) < tolerance) cost2 = -COIN_DBL_MAX; if (cost2 < cost1) whichBound = 0; } } if (whichBound != -1) { // key done = true; if (whichBound) { // slack to upper columnSolution[iBasic] = thisSolution + upper_[iSet] - value; setStatus(iSet, ClpSimplex::atUpperBound); } else { // slack to lower columnSolution[iBasic] = thisSolution + lower_[iSet] - value; setStatus(iSet, ClpSimplex::atLowerBound); } } } if (!done) { if (!cheapest) { // see if slack can be key if (value >= lower_[iSet] - tolerance && value <= upper_[iSet] + tolerance) { done = true; setStatus(iSet, ClpSimplex::basic); iBasic = iSet + numberColumns; } } if (!done) { // set non basic if there was one if (iBasic >= 0) model->setStatus(iBasic, ClpSimplex::atLowerBound); // find cheapest int numberInSet = iEnd - iStart; CoinMemcpyN(columnLower + iStart, numberInSet, lower); CoinMemcpyN(columnUpper + iStart, numberInSet, upper); CoinMemcpyN(columnSolution + iStart, numberInSet, solution); // and slack iBasic = numberInSet; solution[iBasic] = -value; lower[iBasic] = -upper_[iSet]; upper[iBasic] = -lower_[iSet]; int kphase; if (value >= lower_[iSet] - tolerance && value <= upper_[iSet] + tolerance) { // feasible kphase = 1; cost[iBasic] = 0.0; CoinMemcpyN(objective + iStart, numberInSet, cost); } else { // infeasible kphase = 0; // remember bounds are flipped so opposite to natural if (value < lower_[iSet] - tolerance) cost[iBasic] = 1.0; else cost[iBasic] = -1.0; CoinZeroN(cost, numberInSet); } double dualTolerance = model->dualTolerance(); for (int iphase = kphase; iphase < 2; iphase++) { if (iphase) { cost[numberInSet] = 0.0; CoinMemcpyN(objective + iStart, numberInSet, cost); } // now do one row lp bool improve = true; while (improve) { improve = false; double dual = cost[iBasic]; int chosen = -1; double best = dualTolerance; int way = 0; for (int i = 0; i <= numberInSet; i++) { double dj = cost[i] - dual; double improvement = 0.0; if (iphase || i < numberInSet) assert (solution[i] >= lower[i] && solution[i] <= upper[i]); if (dj > dualTolerance) improvement = dj * (solution[i] - lower[i]); else if (dj < -dualTolerance) improvement = dj * (solution[i] - upper[i]); if (improvement > best) { best = improvement; chosen = i; if (dj < 0.0) { way = 1; } else { way = -1; } } } if (chosen >= 0) { improve = true; // now see how far if (way > 0) { // incoming increasing so basic decreasing // if phase 0 then go to nearest bound double distance = upper[chosen] - solution[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] > upper[iBasic]); basicDistance = solution[iBasic] - upper[iBasic]; } else { basicDistance = solution[iBasic] - lower[iBasic]; } // need extra coding for unbounded assert (CoinMin(distance, basicDistance) < 1.0e20); if (distance > basicDistance) { // incoming becomes basic solution[chosen] += basicDistance; if (!iphase) solution[iBasic] = upper[iBasic]; else solution[iBasic] = lower[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = upper[chosen]; solution[iBasic] -= distance; } } else { // incoming decreasing so basic increasing // if phase 0 then go to nearest bound double distance = solution[chosen] - lower[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] < lower[iBasic]); basicDistance = lower[iBasic] - solution[iBasic]; } else { basicDistance = upper[iBasic] - solution[iBasic]; } // need extra coding for unbounded - for now just exit if (CoinMin(distance, basicDistance) > 1.0e20) { printf("unbounded on set %d\n", iSet); iphase = 1; iBasic = numberInSet; break; } if (distance > basicDistance) { // incoming becomes basic solution[chosen] -= basicDistance; if (!iphase) solution[iBasic] = lower[iBasic]; else solution[iBasic] = upper[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = lower[chosen]; solution[iBasic] += distance; } } if (!iphase) { if(iBasic < numberInSet) break; // feasible else if (solution[iBasic] >= lower[iBasic] && solution[iBasic] <= upper[iBasic]) break; // feasible (on flip) } } } } // convert iBasic back and do bounds if (iBasic == numberInSet) { // slack basic setStatus(iSet, ClpSimplex::basic); iBasic = iSet + numberColumns; } else { iBasic += start_[iSet]; model->setStatus(iBasic, ClpSimplex::basic); // remember bounds flipped if (upper[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::isFixed); else if (solution[numberInSet] == upper[numberInSet]) setStatus(iSet, ClpSimplex::atLowerBound); else if (solution[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::atUpperBound); else abort(); } for (j = iStart; j < iEnd; j++) { if (model->getStatus(j) != ClpSimplex::basic) { int inSet = j - iStart; columnSolution[j] = solution[inSet]; if (upper[inSet] == lower[inSet]) model->setStatus(j, ClpSimplex::isFixed); else if (solution[inSet] == upper[inSet]) model->setStatus(j, ClpSimplex::atUpperBound); else if (solution[inSet] == lower[inSet]) model->setStatus(j, ClpSimplex::atLowerBound); } } } } keyVariable_[iSet] = iBasic; } } delete [] lower; delete [] solution; delete [] upper; delete [] cost; // make sure matrix is in good shape matrix_->orderMatrix(); // create effective rhs delete [] rhsOffset_; rhsOffset_ = new double[numberRows]; delete [] next_; next_ = new int[numberColumns+numberSets_+2*longestSet]; char * mark = new char[numberColumns]; memset(mark, 0, numberColumns); for (int iColumn = 0; iColumn < numberColumns; iColumn++) next_[iColumn] = COIN_INT_MAX; int i; int * keys = new int[numberSets_]; for (i = 0; i < numberSets_; i++) keys[i] = COIN_INT_MAX; // set up chains for (i = 0; i < numberColumns; i++) { if (model->getStatus(i) == ClpSimplex::basic) mark[i] = 1; int iSet = backward_[i]; if (iSet >= 0) { int iNext = keys[iSet]; next_[i] = iNext; keys[iSet] = i; } } for (i = 0; i < numberSets_; i++) { int j; if (getStatus(i) != ClpSimplex::basic) { // make sure fixed if it is if (upper_[i] == lower_[i]) setStatus(i, ClpSimplex::isFixed); // slack not key - choose one with smallest length int smallest = numberRows + 1; int key = -1; j = keys[i]; if (j != COIN_INT_MAX) { while (1) { if (mark[j] && columnLength[j] < smallest && !gotBasis) { key = j; smallest = columnLength[j]; } if (next_[j] != COIN_INT_MAX) { j = next_[j]; } else { // correct end next_[j] = -(keys[i] + 1); break; } } } else { next_[i+numberColumns] = -(numberColumns + i + 1); } if (gotBasis) key = keyVariable_[i]; if (key >= 0) { keyVariable_[i] = key; } else { // nothing basic - make slack key //((ClpGubMatrix *)this)->setStatus(i,ClpSimplex::basic); // fudge to avoid const problem status_[i] = 1; } } else { // slack key keyVariable_[i] = numberColumns + i; int j; double sol = 0.0; j = keys[i]; if (j != COIN_INT_MAX) { while (1) { sol += columnSolution[j]; if (next_[j] != COIN_INT_MAX) { j = next_[j]; } else { // correct end next_[j] = -(keys[i] + 1); break; } } } else { next_[i+numberColumns] = -(numberColumns + i + 1); } if (sol > upper_[i] + tolerance) { setAbove(i); } else if (sol < lower_[i] - tolerance) { setBelow(i); } else { setFeasible(i); } } // Create next_ int key = keyVariable_[i]; redoSet(model, key, keys[i], i); } delete [] keys; delete [] mark; rhsOffset(model, true); } // redoes next_ for a set. void ClpGubMatrix::redoSet(ClpSimplex * model, int newKey, int oldKey, int iSet) { int numberColumns = model->numberColumns(); int * save = next_ + numberColumns + numberSets_; int number = 0; int stop = -(oldKey + 1); int j = next_[oldKey]; while (j != stop) { if (j < 0) j = -j - 1; if (j != newKey) save[number++] = j; j = next_[j]; } // and add oldkey if (newKey != oldKey) save[number++] = oldKey; // now do basic int lastMarker = -(newKey + 1); keyVariable_[iSet] = newKey; next_[newKey] = lastMarker; int last = newKey; for ( j = 0; j < number; j++) { int iColumn = save[j]; if (iColumn < numberColumns) { if (model->getStatus(iColumn) == ClpSimplex::basic) { next_[last] = iColumn; next_[iColumn] = lastMarker; last = iColumn; } } } // now add in non-basic for ( j = 0; j < number; j++) { int iColumn = save[j]; if (iColumn < numberColumns) { if (model->getStatus(iColumn) != ClpSimplex::basic) { next_[last] = -(iColumn + 1); next_[iColumn] = lastMarker; last = iColumn; } } } } /* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpGubMatrix::rhsOffset(ClpSimplex * model, bool forceRefresh, bool #ifdef CLP_DEBUG check #endif ) { //forceRefresh=true; if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; double * rhs = new double[numberRows]; CoinMemcpyN(model->solutionRegion(), numberColumns, solution); CoinZeroN(rhs, numberRows); int iRow; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } for (int iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) solution[iColumn] = 0.0; } times(-1.0, solution, rhs); delete [] solution; const double * columnSolution = model->solutionRegion(); // and now subtract out non basic ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lower_[iSet]; else b = upper_[iSet]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(iColumn + 1); int jColumn = next_[iColumn]; // sum all non-basic variables - first skip basic while(jColumn >= 0) jColumn = next_[jColumn]; while(jColumn != stop) { assert (jColumn < 0); jColumn = -jColumn - 1; b -= columnSolution[jColumn]; jColumn = next_[jColumn]; } } // subtract out ClpPackedMatrix::add(model, rhs, iColumn, -b); } } for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** bad effective %d - true %g old %g\n", iRow, rhs[iRow], rhsOffset_[iRow]); } delete [] rhs; } #endif if (forceRefresh || (refreshFrequency_ && model->numberIterations() >= lastRefresh_ + refreshFrequency_)) { // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; CoinMemcpyN(model->solutionRegion(), numberColumns, solution); CoinZeroN(rhsOffset_, numberRows); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } int iSet; for ( iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) solution[iColumn] = 0.0; } times(-1.0, solution, rhsOffset_); delete [] solution; lastRefresh_ = model->numberIterations(); const double * columnSolution = model->solutionRegion(); // and now subtract out non basic ClpSimplex::Status iStatus; for ( iSet = 0; iSet < numberSets_; iSet++) { int iColumn = keyVariable_[iSet]; if (iColumn < numberColumns) { double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lower_[iSet]; else b = upper_[iSet]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(iColumn + 1); int jColumn = next_[iColumn]; // sum all non-basic variables - first skip basic while(jColumn >= 0) jColumn = next_[jColumn]; while(jColumn != stop) { assert (jColumn < 0); jColumn = -jColumn - 1; b -= columnSolution[jColumn]; jColumn = next_[jColumn]; } } // subtract out if (b) ClpPackedMatrix::add(model, rhsOffset_, iColumn, -b); } } } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpGubMatrix::updatePivot(ClpSimplex * model, double oldInValue, double /*oldOutValue*/) { int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); double * solution = model->solutionRegion(); int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); int pivotRow = model->pivotRow(); int iSetIn; // Correct sequence in trueSequenceIn_ = sequenceIn; if (sequenceIn < numberColumns) { iSetIn = backward_[sequenceIn]; } else if (sequenceIn < numberColumns + numberRows) { iSetIn = -1; } else { iSetIn = gubSlackIn_; trueSequenceIn_ = numberColumns + numberRows + iSetIn; } int iSetOut = -1; trueSequenceOut_ = sequenceOut; if (sequenceOut < numberColumns) { iSetOut = backward_[sequenceOut]; } else if (sequenceOut >= numberRows + numberColumns) { assert (pivotRow >= numberRows); int iExtra = pivotRow - numberRows; assert (iExtra >= 0); if (iSetOut < 0) iSetOut = fromIndex_[iExtra]; else assert(iSetOut == fromIndex_[iExtra]); trueSequenceOut_ = numberColumns + numberRows + iSetOut; } if (rhsOffset_) { // update effective rhs if (sequenceIn == sequenceOut) { assert (sequenceIn < numberRows + numberColumns); // should be easy to deal with if (sequenceIn < numberColumns) add(model, rhsOffset_, sequenceIn, oldInValue - solution[sequenceIn]); } else { if (sequenceIn < numberColumns) { // we need to test if WILL be key ClpPackedMatrix::add(model, rhsOffset_, sequenceIn, oldInValue); if (iSetIn >= 0) { // old contribution to rhsOffset_ int key = keyVariable_[iSetIn]; if (key < numberColumns) { double oldB = 0.0; ClpSimplex::Status iStatus = getStatus(iSetIn); if (iStatus == ClpSimplex::atLowerBound) oldB = lower_[iSetIn]; else oldB = upper_[iSetIn]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(key + 1); int iColumn = next_[key]; // skip basic while (iColumn >= 0) iColumn = next_[iColumn]; // sum all non-key variables while(iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; if (iColumn == sequenceIn) oldB -= oldInValue; else if ( iColumn != sequenceOut ) oldB -= solution[iColumn]; iColumn = next_[iColumn]; } } if (oldB) ClpPackedMatrix::add(model, rhsOffset_, key, oldB); } } } else if (sequenceIn < numberRows + numberColumns) { //rhsOffset_[sequenceIn-numberColumns] -= oldInValue; } else { #ifdef CLP_DEBUG_PRINT printf("** in is key slack %d\n", sequenceIn); #endif // old contribution to rhsOffset_ int key = keyVariable_[iSetIn]; if (key < numberColumns) { double oldB = 0.0; ClpSimplex::Status iStatus = getStatus(iSetIn); if (iStatus == ClpSimplex::atLowerBound) oldB = lower_[iSetIn]; else oldB = upper_[iSetIn]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(key + 1); int iColumn = next_[key]; // skip basic while (iColumn >= 0) iColumn = next_[iColumn]; // sum all non-key variables while(iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; if ( iColumn != sequenceOut ) oldB -= solution[iColumn]; iColumn = next_[iColumn]; } } if (oldB) ClpPackedMatrix::add(model, rhsOffset_, key, oldB); } } if (sequenceOut < numberColumns) { ClpPackedMatrix::add(model, rhsOffset_, sequenceOut, -solution[sequenceOut]); if (iSetOut >= 0) { // old contribution to rhsOffset_ int key = keyVariable_[iSetOut]; if (key < numberColumns && iSetIn != iSetOut) { double oldB = 0.0; ClpSimplex::Status iStatus = getStatus(iSetOut); if (iStatus == ClpSimplex::atLowerBound) oldB = lower_[iSetOut]; else oldB = upper_[iSetOut]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(key + 1); int iColumn = next_[key]; // skip basic while (iColumn >= 0) iColumn = next_[iColumn]; // sum all non-key variables while(iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; if (iColumn == sequenceIn) oldB -= oldInValue; else if ( iColumn != sequenceOut ) oldB -= solution[iColumn]; iColumn = next_[iColumn]; } } if (oldB) ClpPackedMatrix::add(model, rhsOffset_, key, oldB); } } } else if (sequenceOut < numberRows + numberColumns) { //rhsOffset_[sequenceOut-numberColumns] -= -solution[sequenceOut]; } else { #ifdef CLP_DEBUG_PRINT printf("** out is key slack %d\n", sequenceOut); #endif assert (pivotRow >= numberRows); } } } int * pivotVariable = model->pivotVariable(); // may need to deal with key // Also need coding to mark/allow key slack entering if (pivotRow >= numberRows) { assert (sequenceOut >= numberRows + numberColumns || sequenceOut == keyVariable_[iSetOut]); #ifdef CLP_DEBUG_PRINT if (sequenceIn >= numberRows + numberColumns) printf("key slack %d in, set out %d\n", gubSlackIn_, iSetOut); printf("** danger - key out for set %d in %d (set %d)\n", iSetOut, sequenceIn, iSetIn); #endif // if slack out mark correctly if (sequenceOut >= numberRows + numberColumns) { double value = model->valueOut(); if (value == upper_[iSetOut]) { setStatus(iSetOut, ClpSimplex::atUpperBound); } else if (value == lower_[iSetOut]) { setStatus(iSetOut, ClpSimplex::atLowerBound); } else { if (fabs(value - upper_[iSetOut]) < fabs(value - lower_[iSetOut])) { setStatus(iSetOut, ClpSimplex::atUpperBound); } else { setStatus(iSetOut, ClpSimplex::atLowerBound); } } if (upper_[iSetOut] == lower_[iSetOut]) setStatus(iSetOut, ClpSimplex::isFixed); setFeasible(iSetOut); } if (iSetOut == iSetIn) { // key swap int key; if (sequenceIn >= numberRows + numberColumns) { key = numberColumns + iSetIn; setStatus(iSetIn, ClpSimplex::basic); } else { key = sequenceIn; } redoSet(model, key, keyVariable_[iSetIn], iSetIn); } else { // key was chosen assert (possiblePivotKey_ >= 0 && possiblePivotKey_ < numberRows); int key = pivotVariable[possiblePivotKey_]; // and set incoming here if (sequenceIn >= numberRows + numberColumns) { // slack in - so use old key sequenceIn = keyVariable_[iSetIn]; model->setStatus(sequenceIn, ClpSimplex::basic); setStatus(iSetIn, ClpSimplex::basic); redoSet(model, iSetIn + numberColumns, keyVariable_[iSetIn], iSetIn); } //? do not do if iSetIn<0 ? as will be done later pivotVariable[possiblePivotKey_] = sequenceIn; if (sequenceIn < numberColumns) backToPivotRow_[sequenceIn] = possiblePivotKey_; redoSet(model, key, keyVariable_[iSetOut], iSetOut); } } else { if (sequenceOut < numberColumns) { if (iSetIn >= 0 && iSetOut == iSetIn) { // key not out - only problem is if slack in int key; if (sequenceIn >= numberRows + numberColumns) { key = numberColumns + iSetIn; setStatus(iSetIn, ClpSimplex::basic); assert (pivotRow < numberRows); // must swap with current key int key = keyVariable_[iSetIn]; model->setStatus(key, ClpSimplex::basic); pivotVariable[pivotRow] = key; backToPivotRow_[key] = pivotRow; } else { key = keyVariable_[iSetIn]; } redoSet(model, key, keyVariable_[iSetIn], iSetIn); } else if (iSetOut >= 0) { // just redo set int key = keyVariable_[iSetOut];; redoSet(model, key, keyVariable_[iSetOut], iSetOut); } } } if (iSetIn >= 0 && iSetIn != iSetOut) { int key = keyVariable_[iSetIn]; if (sequenceIn == numberColumns + 2 * numberRows) { // key slack in assert (pivotRow < numberRows); // must swap with current key model->setStatus(key, ClpSimplex::basic); pivotVariable[pivotRow] = key; backToPivotRow_[key] = pivotRow; setStatus(iSetIn, ClpSimplex::basic); key = iSetIn + numberColumns; } // redo set to allow for new one redoSet(model, key, keyVariable_[iSetIn], iSetIn); } // update pivot if (sequenceIn < numberColumns) { if (pivotRow < numberRows) { backToPivotRow_[sequenceIn] = pivotRow; } else { if (possiblePivotKey_ >= 0) { assert (possiblePivotKey_ < numberRows); backToPivotRow_[sequenceIn] = possiblePivotKey_; pivotVariable[possiblePivotKey_] = sequenceIn; } } } else if (sequenceIn >= numberRows + numberColumns) { // key in - something should have been done before int key = keyVariable_[iSetIn]; assert (key == numberColumns + iSetIn); //pivotVariable[pivotRow]=key; //backToPivotRow_[key]=pivotRow; //model->setStatus(key,ClpSimplex::basic); //key=numberColumns+iSetIn; setStatus(iSetIn, ClpSimplex::basic); redoSet(model, key, keyVariable_[iSetIn], iSetIn); } #ifdef CLP_DEBUG { char * xx = new char[numberColumns+numberRows]; memset(xx, 0, numberRows + numberColumns); for (int i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; assert (iPivot < numberRows + numberColumns); assert (!xx[iPivot]); xx[iPivot] = 1; if (iPivot < numberColumns) { int iBack = backToPivotRow_[iPivot]; assert (i == iBack); } } delete [] xx; } #endif if (rhsOffset_) { // update effective rhs if (sequenceIn != sequenceOut) { if (sequenceIn < numberColumns) { if (iSetIn >= 0) { // new contribution to rhsOffset_ int key = keyVariable_[iSetIn]; if (key < numberColumns) { double newB = 0.0; ClpSimplex::Status iStatus = getStatus(iSetIn); if (iStatus == ClpSimplex::atLowerBound) newB = lower_[iSetIn]; else newB = upper_[iSetIn]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(key + 1); int iColumn = next_[key]; // skip basic while (iColumn >= 0) iColumn = next_[iColumn]; // sum all non-key variables while(iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; newB -= solution[iColumn]; iColumn = next_[iColumn]; } } if (newB) ClpPackedMatrix::add(model, rhsOffset_, key, -newB); } } } if (iSetOut >= 0) { // new contribution to rhsOffset_ int key = keyVariable_[iSetOut]; if (key < numberColumns && iSetIn != iSetOut) { double newB = 0.0; ClpSimplex::Status iStatus = getStatus(iSetOut); if (iStatus == ClpSimplex::atLowerBound) newB = lower_[iSetOut]; else newB = upper_[iSetOut]; // subtract out others at bounds if ((gubType_ & 8) == 0) { int stop = -(key + 1); int iColumn = next_[key]; // skip basic while (iColumn >= 0) iColumn = next_[iColumn]; // sum all non-key variables while(iColumn != stop) { assert (iColumn < 0); iColumn = -iColumn - 1; newB -= solution[iColumn]; iColumn = next_[iColumn]; } } if (newB) ClpPackedMatrix::add(model, rhsOffset_, key, -newB); } } } } #ifdef CLP_DEBUG // debug { int i; char * xxxx = new char[numberColumns]; memset(xxxx, 0, numberColumns); for (i = 0; i < numberRows; i++) { int iPivot = pivotVariable[i]; assert (model->getStatus(iPivot) == ClpSimplex::basic); if (iPivot < numberColumns && backward_[iPivot] >= 0) xxxx[iPivot] = 1; } double primalTolerance = model->primalTolerance(); for (i = 0; i < numberSets_; i++) { int key = keyVariable_[i]; double value = 0.0; // sum over all except key int iColumn = next_[key]; // sum all non-key variables int k = 0; int stop = -(key + 1); while (iColumn != stop) { if (iColumn < 0) iColumn = -iColumn - 1; value += solution[iColumn]; k++; assert (k < 100); assert (backward_[iColumn] == i); iColumn = next_[iColumn]; } iColumn = next_[key]; if (key < numberColumns) { // feasibility will be done later assert (getStatus(i) != ClpSimplex::basic); double sol; if (getStatus(i) == ClpSimplex::atUpperBound) sol = upper_[i] - value; else sol = lower_[i] - value; //printf("xx Value of key structural %d for set %d is %g - cost %g\n",key,i,sol, // cost[key]); //if (fabs(sol-solution[key])>1.0e-3) //printf("** stored value was %g\n",solution[key]); } else { // slack is key double infeasibility = 0.0; if (value > upper_[i] + primalTolerance) { infeasibility = value - upper_[i] - primalTolerance; //setAbove(i); } else if (value < lower_[i] - primalTolerance) { infeasibility = lower_[i] - value - primalTolerance ; //setBelow(i); } else { //setFeasible(i); } //printf("xx Value of key slack for set %d is %g\n",i,value); } while (iColumn >= 0) { assert (xxxx[iColumn]); xxxx[iColumn] = 0; iColumn = next_[iColumn]; } } for (i = 0; i < numberColumns; i++) { if (i < numberColumns && backward_[i] >= 0) { assert (!xxxx[i] || i == keyVariable_[backward_[i]]); } } delete [] xxxx; } #endif return 0; } // Switches off dj checking each factorization (for BIG models) void ClpGubMatrix::switchOffCheck() { noCheck_ = 0; infeasibilityWeight_ = 0.0; } // Correct sequence in and out to give true value void ClpGubMatrix::correctSequence(const ClpSimplex * /*model*/, int & sequenceIn, int & sequenceOut) { if (sequenceIn != -999) { sequenceIn = trueSequenceIn_; sequenceOut = trueSequenceOut_; } } Clp-1.15.10/src/Makefile.in0000644000076600007660000014043112253625222013713 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_ABC_TRUE@am__append_1 = \ @COIN_HAS_ABC_TRUE@ AbcCommon.hpp \ @COIN_HAS_ABC_TRUE@ AbcDualRowDantzig.cpp AbcDualRowDantzig.hpp \ @COIN_HAS_ABC_TRUE@ AbcDualRowPivot.cpp AbcDualRowPivot.hpp \ @COIN_HAS_ABC_TRUE@ AbcDualRowSteepest.cpp AbcDualRowSteepest.hpp \ @COIN_HAS_ABC_TRUE@ AbcMatrix.cpp AbcMatrix.hpp \ @COIN_HAS_ABC_TRUE@ AbcNonLinearCost.cpp AbcNonLinearCost.hpp \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnDantzig.cpp AbcPrimalColumnDantzig.hpp \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnPivot.cpp AbcPrimalColumnPivot.hpp \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnSteepest.cpp AbcPrimalColumnSteepest.hpp \ @COIN_HAS_ABC_TRUE@ AbcSimplex.cpp AbcSimplex.hpp \ @COIN_HAS_ABC_TRUE@ AbcSimplexDual.cpp AbcSimplexDual.hpp \ @COIN_HAS_ABC_TRUE@ AbcSimplexPrimal.cpp AbcSimplexPrimal.hpp \ @COIN_HAS_ABC_TRUE@ AbcSimplexParallel.cpp \ @COIN_HAS_ABC_TRUE@ AbcSimplexFactorization.cpp AbcSimplexFactorization.hpp \ @COIN_HAS_ABC_TRUE@ AbcWarmStart.cpp AbcWarmStart.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization1.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization2.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization3.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization4.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization5.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcCommonFactorization.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcCommon.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcDenseFactorization.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcDenseFactorization.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization1.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization2.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization3.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization4.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization5.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcHelperFunctions.cpp CoinAbcHelperFunctions.hpp \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization1.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization2.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization3.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization4.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization5.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization1.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization2.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization3.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization4.cpp \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization5.cpp # if AMD, CHOLMOD, or GLPK is available, then compile ClpCholeskyUfl.cpp @COIN_HAS_AMD_TRUE@am__append_2 = ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_TRUE@am__append_3 = ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_FALSE@@COIN_HAS_GLPK_TRUE@am__append_4 = ClpCholeskyUfl.cpp ClpCholeskyUfl.hpp @COIN_HAS_MUMPS_TRUE@am__append_5 = ClpCholeskyMumps.cpp ClpCholeskyMumps.hpp @COIN_HAS_WSMP_TRUE@am__append_6 = ClpCholeskyWssmp.cpp ClpCholeskyWssmp.hpp ClpCholeskyWssmpKKT.cpp ClpCholeskyWssmpKKT.hpp bin_PROGRAMS = clp$(EXEEXT) @COIN_HAS_CHOLMOD_TRUE@am__append_7 = -I`$(CYGPATH_W) $(CHOLMODINCDIR)` @COIN_HAS_AMD_TRUE@am__append_8 = -I`$(CYGPATH_W) $(AMDINCDIR)` @COIN_HAS_ABC_TRUE@am__append_9 = AbcSimplex.hpp CoinAbcCommon.hpp AbcCommon.hpp # if AMD, CHOLMOD, or GLPK is available, then install ClpCholeskyUfl.hpp (for advanced users) @COIN_HAS_AMD_TRUE@am__append_10 = ClpCholeskyUfl.hpp @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_TRUE@am__append_11 = ClpCholeskyUfl.hpp @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_FALSE@@COIN_HAS_GLPK_TRUE@am__append_12 = ClpCholeskyUfl.hpp @COIN_HAS_MUMPS_TRUE@am__append_13 = ClpCholeskyMumps.hpp @COIN_HAS_WSMP_TRUE@am__append_14 = ClpCholeskyWssmp.hpp ClpCholeskyWssmpKKT.hpp subdir = src DIST_COMMON = $(am__includecoin_HEADERS_DIST) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/config_clp.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_clp.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@libClp_la_DEPENDENCIES = \ @DEPENDENCY_LINKING_TRUE@ $(am__DEPENDENCIES_1) am__libClp_la_SOURCES_DIST = ClpConfig.h ClpCholeskyBase.cpp \ ClpCholeskyBase.hpp ClpCholeskyDense.cpp ClpCholeskyDense.hpp \ ClpConstraint.cpp ClpConstraint.hpp ClpConstraintLinear.cpp \ ClpConstraintLinear.hpp ClpConstraintQuadratic.cpp \ ClpConstraintQuadratic.hpp Clp_C_Interface.cpp \ Clp_C_Interface.h ClpDualRowDantzig.cpp ClpDualRowDantzig.hpp \ ClpDualRowPivot.cpp ClpDualRowPivot.hpp ClpDualRowSteepest.cpp \ ClpDualRowSteepest.hpp ClpDummyMatrix.cpp ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.cpp ClpDynamicExampleMatrix.hpp \ ClpDynamicMatrix.cpp ClpDynamicMatrix.hpp ClpEventHandler.cpp \ ClpEventHandler.hpp ClpFactorization.cpp ClpFactorization.hpp \ ClpGubDynamicMatrix.cpp ClpGubDynamicMatrix.hpp \ ClpGubMatrix.cpp ClpGubMatrix.hpp ClpHelperFunctions.cpp \ ClpHelperFunctions.hpp ClpInterior.cpp ClpInterior.hpp \ ClpLinearObjective.cpp ClpLinearObjective.hpp \ ClpMatrixBase.cpp ClpMatrixBase.hpp ClpMessage.cpp \ ClpMessage.hpp ClpModel.cpp ClpModel.hpp ClpNetworkBasis.cpp \ ClpNetworkBasis.hpp ClpNetworkMatrix.cpp ClpNetworkMatrix.hpp \ ClpNonLinearCost.cpp ClpNonLinearCost.hpp ClpNode.cpp \ ClpNode.hpp ClpObjective.cpp ClpObjective.hpp \ ClpPackedMatrix.cpp ClpPackedMatrix.hpp ClpParameters.hpp \ ClpPlusMinusOneMatrix.cpp ClpPlusMinusOneMatrix.hpp \ ClpPredictorCorrector.cpp ClpPredictorCorrector.hpp \ ClpPdco.cpp ClpPdco.hpp ClpPdcoBase.cpp ClpPdcoBase.hpp \ ClpLsqr.cpp ClpLsqr.hpp ClpPresolve.cpp ClpPresolve.hpp \ ClpPrimalColumnDantzig.cpp ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.cpp ClpPrimalColumnPivot.hpp \ ClpPrimalColumnSteepest.cpp ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.cpp ClpQuadraticObjective.hpp \ ClpSimplex.cpp ClpSimplex.hpp ClpSimplexDual.cpp \ ClpSimplexDual.hpp ClpSimplexNonlinear.cpp \ ClpSimplexNonlinear.hpp ClpSimplexOther.cpp \ ClpSimplexOther.hpp ClpSimplexPrimal.cpp ClpSimplexPrimal.hpp \ ClpSolve.cpp ClpSolve.hpp Idiot.cpp Idiot.hpp IdiSolve.cpp \ AbcCommon.hpp AbcDualRowDantzig.cpp AbcDualRowDantzig.hpp \ AbcDualRowPivot.cpp AbcDualRowPivot.hpp AbcDualRowSteepest.cpp \ AbcDualRowSteepest.hpp AbcMatrix.cpp AbcMatrix.hpp \ AbcNonLinearCost.cpp AbcNonLinearCost.hpp \ AbcPrimalColumnDantzig.cpp AbcPrimalColumnDantzig.hpp \ AbcPrimalColumnPivot.cpp AbcPrimalColumnPivot.hpp \ AbcPrimalColumnSteepest.cpp AbcPrimalColumnSteepest.hpp \ AbcSimplex.cpp AbcSimplex.hpp AbcSimplexDual.cpp \ AbcSimplexDual.hpp AbcSimplexPrimal.cpp AbcSimplexPrimal.hpp \ AbcSimplexParallel.cpp AbcSimplexFactorization.cpp \ AbcSimplexFactorization.hpp AbcWarmStart.cpp AbcWarmStart.hpp \ CoinAbcBaseFactorization.hpp CoinAbcBaseFactorization1.cpp \ CoinAbcBaseFactorization2.cpp CoinAbcBaseFactorization3.cpp \ CoinAbcBaseFactorization4.cpp CoinAbcBaseFactorization5.cpp \ CoinAbcCommonFactorization.hpp CoinAbcCommon.hpp \ CoinAbcDenseFactorization.cpp CoinAbcDenseFactorization.hpp \ CoinAbcFactorization.hpp CoinAbcFactorization1.cpp \ CoinAbcFactorization2.cpp CoinAbcFactorization3.cpp \ CoinAbcFactorization4.cpp CoinAbcFactorization5.cpp \ CoinAbcHelperFunctions.cpp CoinAbcHelperFunctions.hpp \ CoinAbcOrderedFactorization1.cpp \ CoinAbcOrderedFactorization2.cpp \ CoinAbcOrderedFactorization3.cpp \ CoinAbcOrderedFactorization4.cpp \ CoinAbcOrderedFactorization5.cpp \ CoinAbcSmallFactorization1.cpp CoinAbcSmallFactorization2.cpp \ CoinAbcSmallFactorization3.cpp CoinAbcSmallFactorization4.cpp \ CoinAbcSmallFactorization5.cpp ClpCholeskyUfl.cpp \ ClpCholeskyUfl.hpp ClpCholeskyMumps.cpp ClpCholeskyMumps.hpp \ ClpCholeskyWssmp.cpp ClpCholeskyWssmp.hpp \ ClpCholeskyWssmpKKT.cpp ClpCholeskyWssmpKKT.hpp @COIN_HAS_ABC_TRUE@am__objects_1 = AbcDualRowDantzig.lo \ @COIN_HAS_ABC_TRUE@ AbcDualRowPivot.lo AbcDualRowSteepest.lo \ @COIN_HAS_ABC_TRUE@ AbcMatrix.lo AbcNonLinearCost.lo \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnDantzig.lo \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnPivot.lo \ @COIN_HAS_ABC_TRUE@ AbcPrimalColumnSteepest.lo AbcSimplex.lo \ @COIN_HAS_ABC_TRUE@ AbcSimplexDual.lo AbcSimplexPrimal.lo \ @COIN_HAS_ABC_TRUE@ AbcSimplexParallel.lo \ @COIN_HAS_ABC_TRUE@ AbcSimplexFactorization.lo AbcWarmStart.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization1.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization2.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization3.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization4.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcBaseFactorization5.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcDenseFactorization.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization1.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization2.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization3.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization4.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcFactorization5.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcHelperFunctions.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization1.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization2.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization3.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization4.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcOrderedFactorization5.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization1.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization2.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization3.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization4.lo \ @COIN_HAS_ABC_TRUE@ CoinAbcSmallFactorization5.lo @COIN_HAS_AMD_TRUE@am__objects_2 = ClpCholeskyUfl.lo @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_TRUE@am__objects_3 = \ @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_TRUE@ ClpCholeskyUfl.lo @COIN_HAS_AMD_FALSE@@COIN_HAS_CHOLMOD_FALSE@@COIN_HAS_GLPK_TRUE@am__objects_4 = ClpCholeskyUfl.lo @COIN_HAS_MUMPS_TRUE@am__objects_5 = ClpCholeskyMumps.lo @COIN_HAS_WSMP_TRUE@am__objects_6 = ClpCholeskyWssmp.lo \ @COIN_HAS_WSMP_TRUE@ ClpCholeskyWssmpKKT.lo am_libClp_la_OBJECTS = ClpCholeskyBase.lo ClpCholeskyDense.lo \ ClpConstraint.lo ClpConstraintLinear.lo \ ClpConstraintQuadratic.lo Clp_C_Interface.lo \ ClpDualRowDantzig.lo ClpDualRowPivot.lo ClpDualRowSteepest.lo \ ClpDummyMatrix.lo ClpDynamicExampleMatrix.lo \ ClpDynamicMatrix.lo ClpEventHandler.lo ClpFactorization.lo \ ClpGubDynamicMatrix.lo ClpGubMatrix.lo ClpHelperFunctions.lo \ ClpInterior.lo ClpLinearObjective.lo ClpMatrixBase.lo \ ClpMessage.lo ClpModel.lo ClpNetworkBasis.lo \ ClpNetworkMatrix.lo ClpNonLinearCost.lo ClpNode.lo \ ClpObjective.lo ClpPackedMatrix.lo ClpPlusMinusOneMatrix.lo \ ClpPredictorCorrector.lo ClpPdco.lo ClpPdcoBase.lo ClpLsqr.lo \ ClpPresolve.lo ClpPrimalColumnDantzig.lo \ ClpPrimalColumnPivot.lo ClpPrimalColumnSteepest.lo \ ClpQuadraticObjective.lo ClpSimplex.lo ClpSimplexDual.lo \ ClpSimplexNonlinear.lo ClpSimplexOther.lo ClpSimplexPrimal.lo \ ClpSolve.lo Idiot.lo IdiSolve.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) libClp_la_OBJECTS = $(am_libClp_la_OBJECTS) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_clp_OBJECTS = ClpMain.$(OBJEXT) CbcOrClpParam.$(OBJEXT) \ MyEventHandler.$(OBJEXT) MyMessageHandler.$(OBJEXT) \ unitTest.$(OBJEXT) clp_OBJECTS = $(am_clp_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 = $(libClp_la_SOURCES) $(clp_SOURCES) DIST_SOURCES = $(am__libClp_la_SOURCES_DIST) $(clp_SOURCES) am__includecoin_HEADERS_DIST = Clp_C_Interface.h ClpCholeskyBase.hpp \ ClpCholeskyDense.hpp ClpConstraint.hpp ClpConstraintLinear.hpp \ ClpConstraintQuadratic.hpp ClpDualRowDantzig.hpp \ ClpDualRowPivot.hpp ClpDualRowSteepest.hpp ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.hpp ClpDynamicMatrix.hpp \ ClpEventHandler.hpp ClpFactorization.hpp \ ClpGubDynamicMatrix.hpp ClpGubMatrix.hpp ClpInterior.hpp \ ClpLinearObjective.hpp ClpMatrixBase.hpp ClpMessage.hpp \ ClpModel.hpp ClpNetworkMatrix.hpp ClpNonLinearCost.hpp \ ClpNode.hpp ClpObjective.hpp ClpPackedMatrix.hpp \ ClpPdcoBase.hpp ClpPlusMinusOneMatrix.hpp ClpParameters.hpp \ ClpPresolve.hpp ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.hpp ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.hpp ClpSimplex.hpp \ ClpSimplexNonlinear.hpp ClpSimplexOther.hpp ClpSimplexDual.hpp \ ClpSimplexPrimal.hpp ClpSolve.hpp CbcOrClpParam.hpp Idiot.hpp \ AbcSimplex.hpp CoinAbcCommon.hpp AbcCommon.hpp \ ClpCholeskyUfl.hpp ClpCholeskyMumps.hpp ClpCholeskyWssmp.hpp \ ClpCholeskyWssmpKKT.hpp CbcOrClpParam.cpp 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@ ADD_FFLAGS = @ADD_FFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMDINCDIR = @AMDINCDIR@ AMDLIB = @AMDLIB@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BLAS_CFLAGS = @BLAS_CFLAGS@ BLAS_CFLAGS_INSTALLED = @BLAS_CFLAGS_INSTALLED@ BLAS_DATA = @BLAS_DATA@ BLAS_DATA_INSTALLED = @BLAS_DATA_INSTALLED@ BLAS_DEPENDENCIES = @BLAS_DEPENDENCIES@ BLAS_LIBS = @BLAS_LIBS@ BLAS_LIBS_INSTALLED = @BLAS_LIBS_INSTALLED@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CHOLMODINCDIR = @CHOLMODINCDIR@ CHOLMODLIB = @CHOLMODLIB@ CLPLIB_CFLAGS = @CLPLIB_CFLAGS@ CLPLIB_CFLAGS_INSTALLED = @CLPLIB_CFLAGS_INSTALLED@ CLPLIB_DEPENDENCIES = @CLPLIB_DEPENDENCIES@ CLPLIB_LIBS = @CLPLIB_LIBS@ CLPLIB_LIBS_INSTALLED = @CLPLIB_LIBS_INSTALLED@ CLPLIB_PCLIBS = @CLPLIB_PCLIBS@ CLPLIB_PCREQUIRES = @CLPLIB_PCREQUIRES@ CLP_SVN_REV = @CLP_SVN_REV@ COINUTILS_CFLAGS = @COINUTILS_CFLAGS@ COINUTILS_CFLAGS_INSTALLED = @COINUTILS_CFLAGS_INSTALLED@ COINUTILS_DATA = @COINUTILS_DATA@ COINUTILS_DATA_INSTALLED = @COINUTILS_DATA_INSTALLED@ COINUTILS_DEPENDENCIES = @COINUTILS_DEPENDENCIES@ COINUTILS_LIBS = @COINUTILS_LIBS@ COINUTILS_LIBS_INSTALLED = @COINUTILS_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_ABC_FALSE = @COIN_HAS_ABC_FALSE@ COIN_HAS_ABC_TRUE = @COIN_HAS_ABC_TRUE@ COIN_HAS_AMD_FALSE = @COIN_HAS_AMD_FALSE@ COIN_HAS_AMD_TRUE = @COIN_HAS_AMD_TRUE@ COIN_HAS_BLAS_FALSE = @COIN_HAS_BLAS_FALSE@ COIN_HAS_BLAS_TRUE = @COIN_HAS_BLAS_TRUE@ COIN_HAS_CHOLMOD_FALSE = @COIN_HAS_CHOLMOD_FALSE@ COIN_HAS_CHOLMOD_TRUE = @COIN_HAS_CHOLMOD_TRUE@ COIN_HAS_COINUTILS_FALSE = @COIN_HAS_COINUTILS_FALSE@ COIN_HAS_COINUTILS_TRUE = @COIN_HAS_COINUTILS_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_MUMPS_FALSE = @COIN_HAS_MUMPS_FALSE@ COIN_HAS_MUMPS_TRUE = @COIN_HAS_MUMPS_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_OSI_FALSE = @COIN_HAS_OSI_FALSE@ COIN_HAS_OSI_TRUE = @COIN_HAS_OSI_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_WSMP_FALSE = @COIN_HAS_WSMP_FALSE@ COIN_HAS_WSMP_TRUE = @COIN_HAS_WSMP_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DBG_FFLAGS = @DBG_FFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FLIBS = @FLIBS@ 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@ 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@ MPICC = @MPICC@ MPICXX = @MPICXX@ MPIF77 = @MPIF77@ MUMPS_CFLAGS = @MUMPS_CFLAGS@ MUMPS_CFLAGS_INSTALLED = @MUMPS_CFLAGS_INSTALLED@ MUMPS_DATA = @MUMPS_DATA@ MUMPS_DATA_INSTALLED = @MUMPS_DATA_INSTALLED@ MUMPS_DEPENDENCIES = @MUMPS_DEPENDENCIES@ MUMPS_LIBS = @MUMPS_LIBS@ MUMPS_LIBS_INSTALLED = @MUMPS_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@ OPT_FFLAGS = @OPT_FFLAGS@ OSICLPLIB_CFLAGS = @OSICLPLIB_CFLAGS@ OSICLPLIB_CFLAGS_INSTALLED = @OSICLPLIB_CFLAGS_INSTALLED@ OSICLPLIB_DEPENDENCIES = @OSICLPLIB_DEPENDENCIES@ OSICLPLIB_LIBS = @OSICLPLIB_LIBS@ OSICLPLIB_LIBS_INSTALLED = @OSICLPLIB_LIBS_INSTALLED@ OSICLPLIB_PCLIBS = @OSICLPLIB_PCLIBS@ OSICLPLIB_PCREQUIRES = @OSICLPLIB_PCREQUIRES@ 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@ OSI_CFLAGS = @OSI_CFLAGS@ OSI_CFLAGS_INSTALLED = @OSI_CFLAGS_INSTALLED@ OSI_DATA = @OSI_DATA@ OSI_DATA_INSTALLED = @OSI_DATA_INSTALLED@ OSI_DEPENDENCIES = @OSI_DEPENDENCIES@ OSI_LIBS = @OSI_LIBS@ OSI_LIBS_INSTALLED = @OSI_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@ STRIP = @STRIP@ VERSION = @VERSION@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ 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 ######################################################################## # libClp # ######################################################################## # Name of the library compiled in this directory. We want it to be installed # in the 'lib' directory lib_LTLIBRARIES = libClp.la # List all source files for this library, including headers libClp_la_SOURCES = ClpConfig.h ClpCholeskyBase.cpp \ ClpCholeskyBase.hpp ClpCholeskyDense.cpp ClpCholeskyDense.hpp \ ClpConstraint.cpp ClpConstraint.hpp ClpConstraintLinear.cpp \ ClpConstraintLinear.hpp ClpConstraintQuadratic.cpp \ ClpConstraintQuadratic.hpp Clp_C_Interface.cpp \ Clp_C_Interface.h ClpDualRowDantzig.cpp ClpDualRowDantzig.hpp \ ClpDualRowPivot.cpp ClpDualRowPivot.hpp ClpDualRowSteepest.cpp \ ClpDualRowSteepest.hpp ClpDummyMatrix.cpp ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.cpp ClpDynamicExampleMatrix.hpp \ ClpDynamicMatrix.cpp ClpDynamicMatrix.hpp ClpEventHandler.cpp \ ClpEventHandler.hpp ClpFactorization.cpp ClpFactorization.hpp \ ClpGubDynamicMatrix.cpp ClpGubDynamicMatrix.hpp \ ClpGubMatrix.cpp ClpGubMatrix.hpp ClpHelperFunctions.cpp \ ClpHelperFunctions.hpp ClpInterior.cpp ClpInterior.hpp \ ClpLinearObjective.cpp ClpLinearObjective.hpp \ ClpMatrixBase.cpp ClpMatrixBase.hpp ClpMessage.cpp \ ClpMessage.hpp ClpModel.cpp ClpModel.hpp ClpNetworkBasis.cpp \ ClpNetworkBasis.hpp ClpNetworkMatrix.cpp ClpNetworkMatrix.hpp \ ClpNonLinearCost.cpp ClpNonLinearCost.hpp ClpNode.cpp \ ClpNode.hpp ClpObjective.cpp ClpObjective.hpp \ ClpPackedMatrix.cpp ClpPackedMatrix.hpp ClpParameters.hpp \ ClpPlusMinusOneMatrix.cpp ClpPlusMinusOneMatrix.hpp \ ClpPredictorCorrector.cpp ClpPredictorCorrector.hpp \ ClpPdco.cpp ClpPdco.hpp ClpPdcoBase.cpp ClpPdcoBase.hpp \ ClpLsqr.cpp ClpLsqr.hpp ClpPresolve.cpp ClpPresolve.hpp \ ClpPrimalColumnDantzig.cpp ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.cpp ClpPrimalColumnPivot.hpp \ ClpPrimalColumnSteepest.cpp ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.cpp ClpQuadraticObjective.hpp \ ClpSimplex.cpp ClpSimplex.hpp ClpSimplexDual.cpp \ ClpSimplexDual.hpp ClpSimplexNonlinear.cpp \ ClpSimplexNonlinear.hpp ClpSimplexOther.cpp \ ClpSimplexOther.hpp ClpSimplexPrimal.cpp ClpSimplexPrimal.hpp \ ClpSolve.cpp ClpSolve.hpp Idiot.cpp Idiot.hpp IdiSolve.cpp \ $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) # List all additionally required libraries @DEPENDENCY_LINKING_TRUE@libClp_la_LIBADD = $(CLPLIB_LIBS) # This is for libtool libClp_la_LDFLAGS = $(LT_LDFLAGS) # List all source files for this executable, including headers clp_SOURCES = \ ClpMain.cpp \ CbcOrClpParam.cpp CbcOrClpParam.hpp \ MyEventHandler.cpp MyEventHandler.hpp \ MyMessageHandler.cpp MyMessageHandler.hpp \ unitTest.cpp # List all additionally required libraries clp_LDADD = libClp.la $(CLPLIB_LIBS) # List all dependency libraries (similar to LDADD, but without -l, -L flags) clp_DEPENDENCIES = libClp.la $(CLPLIB_DEPENDENCIES) ######################################################################## # Additional flags # ######################################################################## # CbcOrClpParam seem to require COIN_HAS_CLP so that it knows that it is build within Clp AM_CPPFLAGS = $(CLPLIB_CFLAGS) -DCOIN_HAS_CLP $(am__append_7) \ $(am__append_8) # This line is necessary to allow VPATH compilation DEFAULT_INCLUDES = -I. -I`$(CYGPATH_W) $(srcdir)` ######################################################################## # 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 # needed by Cbc includecoin_HEADERS = Clp_C_Interface.h ClpCholeskyBase.hpp \ ClpCholeskyDense.hpp ClpConstraint.hpp ClpConstraintLinear.hpp \ ClpConstraintQuadratic.hpp ClpDualRowDantzig.hpp \ ClpDualRowPivot.hpp ClpDualRowSteepest.hpp ClpDummyMatrix.hpp \ ClpDynamicExampleMatrix.hpp ClpDynamicMatrix.hpp \ ClpEventHandler.hpp ClpFactorization.hpp \ ClpGubDynamicMatrix.hpp ClpGubMatrix.hpp ClpInterior.hpp \ ClpLinearObjective.hpp ClpMatrixBase.hpp ClpMessage.hpp \ ClpModel.hpp ClpNetworkMatrix.hpp ClpNonLinearCost.hpp \ ClpNode.hpp ClpObjective.hpp ClpPackedMatrix.hpp \ ClpPdcoBase.hpp ClpPlusMinusOneMatrix.hpp ClpParameters.hpp \ ClpPresolve.hpp ClpPrimalColumnDantzig.hpp \ ClpPrimalColumnPivot.hpp ClpPrimalColumnSteepest.hpp \ ClpQuadraticObjective.hpp ClpSimplex.hpp \ ClpSimplexNonlinear.hpp ClpSimplexOther.hpp ClpSimplexDual.hpp \ ClpSimplexPrimal.hpp ClpSolve.hpp CbcOrClpParam.hpp Idiot.hpp \ $(am__append_9) $(am__append_10) $(am__append_11) \ $(am__append_12) $(am__append_13) $(am__append_14) \ CbcOrClpParam.cpp all: config.h config_clp.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_clp.h: stamp-h2 @if test ! -f $@; then \ rm -f stamp-h2; \ $(MAKE) stamp-h2; \ else :; fi stamp-h2: $(srcdir)/config_clp.h.in $(top_builddir)/config.status @rm -f stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status src/config_clp.h distclean-hdr: -rm -f config.h stamp-h1 config_clp.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 libClp.la: $(libClp_la_OBJECTS) $(libClp_la_DEPENDENCIES) $(CXXLINK) -rpath $(libdir) $(libClp_la_LDFLAGS) $(libClp_la_OBJECTS) $(libClp_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 clp$(EXEEXT): $(clp_OBJECTS) $(clp_DEPENDENCIES) @rm -f clp$(EXEEXT) $(CXXLINK) $(clp_LDFLAGS) $(clp_OBJECTS) $(clp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcDualRowDantzig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcDualRowPivot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcDualRowSteepest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcNonLinearCost.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcPrimalColumnDantzig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcPrimalColumnPivot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcPrimalColumnSteepest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcSimplex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcSimplexDual.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcSimplexFactorization.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcSimplexParallel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcSimplexPrimal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AbcWarmStart.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CbcOrClpParam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyBase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyDense.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyMumps.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyUfl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyWssmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpCholeskyWssmpKKT.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpConstraint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpConstraintLinear.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpConstraintQuadratic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDualRowDantzig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDualRowPivot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDualRowSteepest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDummyMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDynamicExampleMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpDynamicMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpEventHandler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpFactorization.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpGubDynamicMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpGubMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpHelperFunctions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpInterior.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpLinearObjective.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpLsqr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpMain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpMatrixBase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpMessage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpModel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpNetworkBasis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpNetworkMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpNode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpNonLinearCost.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpObjective.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPackedMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPdco.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPdcoBase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPlusMinusOneMatrix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPredictorCorrector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPresolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPrimalColumnDantzig.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPrimalColumnPivot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpPrimalColumnSteepest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpQuadraticObjective.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSimplex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSimplexDual.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSimplexNonlinear.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSimplexOther.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSimplexPrimal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClpSolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Clp_C_Interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcBaseFactorization1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcBaseFactorization2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcBaseFactorization3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcBaseFactorization4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcBaseFactorization5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcDenseFactorization.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcFactorization1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcFactorization2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcFactorization3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcFactorization4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcFactorization5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcHelperFunctions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcOrderedFactorization1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcOrderedFactorization2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcOrderedFactorization3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcOrderedFactorization4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcOrderedFactorization5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcSmallFactorization1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcSmallFactorization2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcSmallFactorization3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcSmallFactorization4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CoinAbcSmallFactorization5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IdiSolve.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Idiot.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MyEventHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MyMessageHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unitTest.Po@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_clp.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in config_clp.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_clp.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in config_clp.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_clp.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 clp.exe.manifest && \ @COIN_CXX_IS_CL_TRUE@ mt -manifest clp.exe.manifest -outputresource:clp.exe;\ @COIN_CXX_IS_CL_TRUE@ cp clp.exe $(bindir)/clp.exe ####################################################################### # Create the Config.h file that has all public defines and install it # ####################################################################### install-exec-local: $(install_sh_DATA) config_clp.h $(DESTDIR)$(includecoindir)/ClpConfig.h uninstall-local: rm -f $(DESTDIR)$(includecoindir)/ClpConfig.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: Clp-1.15.10/src/ClpCholeskyDense.hpp0000644000076600007660000001327612101105055015551 0ustar coincoin/* $Id: ClpCholeskyDense.hpp 1910 2013-01-27 02:00:13Z 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 ClpCholeskyDense_H #define ClpCholeskyDense_H #include "ClpCholeskyBase.hpp" class ClpMatrixBase; class ClpCholeskyDense : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ /**@{*/ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /** Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const CoinWorkDouble * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (CoinWorkDouble * region) ; /**@}*/ /**@name Non virtual methods for ClpCholeskyDense */ /**@{*/ /** Reserves space. If factor not NULL then just uses passed space Returns non-zero if not enough memory */ int reserveSpace(const ClpCholeskyBase * factor, int numberRows) ; /** Returns space needed */ CoinBigIndex space( int numberRows) const; /** part 2 of Factorize - filling in rowsDropped */ void factorizePart2(int * rowsDropped) ; /** part 2 of Factorize - filling in rowsDropped - blocked */ void factorizePart3(int * rowsDropped) ; /** Forward part of solve */ void solveF1(longDouble * a, int n, CoinWorkDouble * region); void solveF2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2); /** Backward part of solve */ void solveB1(longDouble * a, int n, CoinWorkDouble * region); void solveB2(longDouble * a, int n, CoinWorkDouble * region, CoinWorkDouble * region2); int bNumber(const longDouble * array, int &, int&); /** A */ inline longDouble * aMatrix() const { return sparseFactor_; } /** Diagonal */ inline longDouble * diagonal() const { return diagonal_; } /**@}*/ /**@name Constructors, destructor */ /**@{*/ /** Default constructor. */ ClpCholeskyDense(); /** Destructor */ virtual ~ClpCholeskyDense(); /** Copy */ ClpCholeskyDense(const ClpCholeskyDense&); /** Assignment */ ClpCholeskyDense& operator=(const ClpCholeskyDense&); /** Clone */ virtual ClpCholeskyBase * clone() const ; /**@}*/ private: /**@name Data members */ /**@{*/ /** Just borrowing space */ bool borrowSpace_; /**@}*/ }; /* structure for C */ typedef struct { longDouble * diagonal_; longDouble * a; longDouble * work; int * rowsDropped; double doubleParameters_[1]; /* corresponds to 10 */ int integerParameters_[2]; /* corresponds to 34, nThreads */ int n; int numberBlocks; } ClpCholeskyDenseC; extern "C" { void ClpCholeskySpawn(void *); } /**Non leaf recursive factor */ void ClpCholeskyCfactor(ClpCholeskyDenseC * thisStruct, longDouble * a, int n, int numberBlocks, longDouble * diagonal, longDouble * work, int * rowsDropped); /**Non leaf recursive triangle rectangle update */ void ClpCholeskyCtriRec(ClpCholeskyDenseC * thisStruct, longDouble * aTri, int nThis, longDouble * aUnder, longDouble * diagonal, longDouble * work, int nLeft, int iBlock, int jBlock, int numberBlocks); /**Non leaf recursive rectangle triangle update */ void ClpCholeskyCrecTri(ClpCholeskyDenseC * thisStruct, longDouble * aUnder, int nTri, int nDo, int iBlock, int jBlock, longDouble * aTri, longDouble * diagonal, longDouble * work, int numberBlocks); /** Non leaf recursive rectangle rectangle update, nUnder is number of rows in iBlock, nUnderK is number of rows in kBlock */ void ClpCholeskyCrecRec(ClpCholeskyDenseC * thisStruct, longDouble * above, int nUnder, int nUnderK, int nDo, longDouble * aUnder, longDouble *aOther, longDouble * work, int iBlock, int jBlock, int numberBlocks); /**Leaf recursive factor */ void ClpCholeskyCfactorLeaf(ClpCholeskyDenseC * thisStruct, longDouble * a, int n, longDouble * diagonal, longDouble * work, int * rowsDropped); /**Leaf recursive triangle rectangle update */ void ClpCholeskyCtriRecLeaf(/*ClpCholeskyDenseC * thisStruct,*/ longDouble * aTri, longDouble * aUnder, longDouble * diagonal, longDouble * work, int nUnder); /**Leaf recursive rectangle triangle update */ void ClpCholeskyCrecTriLeaf(/*ClpCholeskyDenseC * thisStruct, */ longDouble * aUnder, longDouble * aTri, /*longDouble * diagonal,*/ longDouble * work, int nUnder); /** Leaf recursive rectangle rectangle update, nUnder is number of rows in iBlock, nUnderK is number of rows in kBlock */ void ClpCholeskyCrecRecLeaf(/*ClpCholeskyDenseC * thisStruct, */ const longDouble * COIN_RESTRICT above, const longDouble * COIN_RESTRICT aUnder, longDouble * COIN_RESTRICT aOther, const longDouble * COIN_RESTRICT work, int nUnder); #endif Clp-1.15.10/src/CoinAbcOrderedFactorization3.cpp0000644000076600007660000000107712101105055017764 0ustar coincoin/* $Id: CoinAbcOrderedFactorization3.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -1 #define ABC_ORDERED_FACTORIZATION #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization3.cpp" #endif Clp-1.15.10/src/ClpObjective.cpp0000644000076600007660000000406311510657452014730 0ustar coincoin/* $Id: ClpObjective.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpObjective.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpObjective::ClpObjective () : offset_(0.0), type_(-1), activated_(1) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpObjective::ClpObjective (const ClpObjective & source) : offset_(source.offset_), type_(source.type_), activated_(source.activated_) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpObjective::~ClpObjective () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpObjective & ClpObjective::operator=(const ClpObjective& rhs) { if (this != &rhs) { offset_ = rhs.offset_; type_ = rhs.type_; activated_ = rhs.activated_; } return *this; } /* Subset clone. Duplicates are allowed and order is as given. */ ClpObjective * ClpObjective::subsetClone (int, const int * ) const { std::cerr << "subsetClone not supported - ClpObjective" << std::endl; abort(); return NULL; } /* Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ int ClpObjective::markNonlinear(char *) { return 0; } Clp-1.15.10/src/ClpCholeskyWssmpKKT.cpp0000644000076600007660000005262411552601036016202 0ustar coincoin/* $Id: ClpCholeskyWssmpKKT.cpp 1723 2011-04-17 15:07:10Z 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 "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpCholeskyWssmpKKT.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyWssmpKKT::ClpCholeskyWssmpKKT (int denseThreshold) : ClpCholeskyBase(denseThreshold) { type_ = 21; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyWssmpKKT::ClpCholeskyWssmpKKT (const ClpCholeskyWssmpKKT & rhs) : ClpCholeskyBase(rhs) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyWssmpKKT::~ClpCholeskyWssmpKKT () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyWssmpKKT & ClpCholeskyWssmpKKT::operator=(const ClpCholeskyWssmpKKT& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyWssmpKKT::clone() const { return new ClpCholeskyWssmpKKT(*this); } // At present I can't get wssmp to work as my libraries seem to be out of sync // so I have linked in ekkwssmp which is an older version #ifndef USE_EKKWSSMP extern "C" { void F77_FUNC(wsetmaxthrds,WSETMAXTHRDS)(const int* NTHREADS); void F77_FUNC(wssmp,WSSMP)(const int* N, const int* IA, const int* JA, const double* AVALS, double* DIAG, int* PERM, int* INVP, double* B, const int* LDB, const int* NRHS, double* AUX, const int* NAUX, int* MRP, int* IPARM, double* DPARM); void F77_FUNC_(wsmp_clear,WSMP_CLEAR)(void); } #else /* minimum needed for user */ typedef struct EKKModel EKKModel; typedef struct EKKContext EKKContext; extern "C" { EKKContext * ekk_initializeContext(); void ekk_endContext(EKKContext * context); EKKModel * ekk_newModel(EKKContext * env, const char * name); int ekk_deleteModel(EKKModel * model); } static EKKModel * model = NULL; static EKKContext * context = NULL; extern "C" void ekkwssmp(EKKModel *, int * n, int * columnStart , int * rowIndex , double * element, double * diagonal , int * perm , int * invp , double * rhs , int * ldb , int * nrhs , double * aux , int * naux , int * mrp , int * iparm , double * dparm); static void F77_FUNC(wssmp,WSSMP)( int *n, int *ia, int *ja, double *avals, double *diag, int *perm, int *invp, double *b, int *ldb, int *nrhs, double *aux, int * naux, int *mrp, int *iparm, double *dparm) { if (!context) { /* initialize OSL environment */ context = ekk_initializeContext(); model = ekk_newModel(context, ""); } ekkwssmp(model, n, ia, ja, avals, diag, perm, invp, b, ldb, nrhs, aux, naux, mrp, iparm, dparm); //ekk_deleteModel(model); //ekk_endContext(context); } #endif /* Orders rows and saves pointer to model */ int ClpCholeskyWssmpKKT::order(ClpInterior * model) { int numberRowsModel = model->numberRows(); int numberColumns = model->numberColumns(); int numberTotal = numberColumns + numberRowsModel; numberRows_ = 2 * numberRowsModel + numberColumns; rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); int numberElements = model_->clpMatrix()->getNumElements(); numberElements = numberElements + 2 * numberRowsModel + numberTotal; if (quadratic) numberElements += quadratic->getNumElements(); // Space for starts choleskyStart_ = new CoinBigIndex[numberRows_+1]; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); //const double * element = model_->clpMatrix()->getElements(); // Now we have size - create arrays and fill in try { choleskyRow_ = new int [numberElements]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[numberElements]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } int iRow, iColumn; sizeFactor_ = 0; // matrix if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; choleskyRow_[sizeFactor_++] = iColumn; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[sizeFactor_++] = row[j] + numberTotal; } } } else { // Quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); //const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; choleskyRow_[sizeFactor_++] = iColumn; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) choleskyRow_[sizeFactor_++] = jColumn; } CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[sizeFactor_++] = row[j] + numberTotal; } } } // slacks for (; iColumn < numberTotal; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; choleskyRow_[sizeFactor_++] = iColumn; choleskyRow_[sizeFactor_++] = iColumn - numberColumns + numberTotal; } // Transpose - nonzero diagonal (may regularize) for (iRow = 0; iRow < numberRowsModel; iRow++) { choleskyStart_[iRow+numberTotal] = sizeFactor_; // diagonal choleskyRow_[sizeFactor_++] = iRow + numberTotal; } choleskyStart_[numberRows_] = sizeFactor_; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; integerParameters_[0] = 0; int i0 = 0; int i1 = 1; #ifndef USE_EKKWSSMP int i2 = 1; if (model->numberThreads() <= 0) i2 = 1; else i2 = model->numberThreads(); F77_FUNC(wsetmaxthrds,WSETMAXTHRDS)(&i2); #endif F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, 0, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); integerParameters_[1] = 1; //order and symbolic integerParameters_[2] = 2; integerParameters_[3] = 0; //CSR integerParameters_[4] = 0; //C style integerParameters_[13] = 1; //reuse initial factorization space integerParameters_[15+0] = 1; //ordering integerParameters_[15+1] = 0; integerParameters_[15+2] = 1; integerParameters_[15+3] = 0; integerParameters_[15+4] = 1; doubleParameters_[10] = 1.0e-20; doubleParameters_[11] = 1.0e-15; #if 1 integerParameters_[1] = 2; //just symbolic for (int iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } #endif F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); //std::cout<<"Ordering and symbolic factorization took "<numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; int newDropped = 0; double largest = 0.0; double smallest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = sqrt(perturbation);; perturbation = 1.0; } // need to recreate every time int iRow, iColumn; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); CoinBigIndex numberElements = 0; CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); // matrix if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = numberElements; double value = diagonal[iColumn]; if (fabs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, fabs(value)); sparseFactor_[numberElements] = -value; choleskyRow_[numberElements++] = iColumn; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[numberElements] = row[j] + numberTotal; sparseFactor_[numberElements++] = element[j]; largest = CoinMax(largest, fabs(element[j])); } } else { sparseFactor_[numberElements] = -1.0e100; choleskyRow_[numberElements++] = iColumn; } } } else { // Quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = numberElements; CoinBigIndex savePosition = numberElements; choleskyRow_[numberElements++] = iColumn; double value = diagonal[iColumn]; if (fabs(value) > 1.0e-100) { value = 1.0 / value; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) { sparseFactor_[numberElements] = -quadraticElement[j]; choleskyRow_[numberElements++] = jColumn; } else if (iColumn == jColumn) { value += quadraticElement[j]; } } largest = CoinMax(largest, fabs(value)); sparseFactor_[savePosition] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[numberElements] = row[j] + numberTotal; sparseFactor_[numberElements++] = element[j]; largest = CoinMax(largest, fabs(element[j])); } } else { value = 1.0e100; sparseFactor_[savePosition] = -value; } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { assert (sparseFactor_[choleskyStart_[iColumn]] < 0.0); } // slacks for (iColumn = numberColumns; iColumn < numberTotal; iColumn++) { choleskyStart_[iColumn] = numberElements; double value = diagonal[iColumn]; if (fabs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, fabs(value)); } else { value = 1.0e100; } sparseFactor_[numberElements] = -value; choleskyRow_[numberElements++] = iColumn; choleskyRow_[numberElements] = iColumn - numberColumns + numberTotal; sparseFactor_[numberElements++] = -1.0; } // Finish diagonal double delta2 = model_->delta(); // add delta*delta to bottom delta2 *= delta2; for (iRow = 0; iRow < numberRowsModel; iRow++) { choleskyStart_[iRow+numberTotal] = numberElements; choleskyRow_[numberElements] = iRow + numberTotal; sparseFactor_[numberElements++] = delta2; } choleskyStart_[numberRows_] = numberElements; int i1 = 1; int i0 = 0; integerParameters_[1] = 3; integerParameters_[2] = 3; integerParameters_[10] = 2; //integerParameters_[11]=1; integerParameters_[12] = 2; // LDLT integerParameters_[30] = 1; doubleParameters_[20] = 1.0e100; double largest2 = largest * 1.0e-20; largest = CoinMin(largest2, 1.0e-11); doubleParameters_[10] = CoinMax(1.0e-20, largest); if (doubleParameters_[10] > 1.0e-3) integerParameters_[9] = 1; else integerParameters_[9] = 0; #ifndef WSMP // Set up LDL cutoff integerParameters_[34] = numberTotal; doubleParameters_[20] = 1.0e-15; doubleParameters_[34] = 1.0e-12; //printf("tol is %g\n",doubleParameters_[10]); //doubleParameters_[10]=1.0e-17; #endif int * rowsDropped2 = new int[numberRows_]; CoinZeroN(rowsDropped2, numberRows_); F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1, NULL, &i0, rowsDropped2, integerParameters_, doubleParameters_); //std::cout<<"factorization took "<primalR(); double * dualR = model_->dualR(); for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped2[iRow]) { n1++; //printf("row region1 %d dropped\n",iRow); //rowsDropped_[iRow]=1; rowsDropped_[iRow] = 0; primalR[iRow] = doubleParameters_[20]; } else { rowsDropped_[iRow] = 0; primalR[iRow] = 0.0; } } for (; iRow < numberRows_; iRow++) { if (rowsDropped2[iRow]) { n2++; //printf("row region2 %d dropped\n",iRow); //rowsDropped_[iRow]=1; rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = doubleParameters_[34]; } else { rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = 0.0; } } //printf("%d rows dropped in region1, %d in region2\n",n1,n2); #endif delete [] rowsDropped2; //if (integerParameters_[20]) //std::cout<messageHandler()->logLevel() > 1) std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl; choleskyCondition_ = largest / smallest; if (integerParameters_[63] < 0) return -1; // out of memory status_ = 0; return 0; } /* Uses factorization to solve. */ void ClpCholeskyWssmpKKT::solve (double * region) { abort(); } /* Uses factorization to solve. */ void ClpCholeskyWssmpKKT::solveKKT (double * region1, double * region2, const double * diagonal, double diagonalScaleFactor) { int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; double * array = new double [numberRows_]; CoinMemcpyN(region1, numberTotal, array); CoinMemcpyN(region2, numberRowsModel, array + numberTotal); int i1 = 1; int i0 = 0; integerParameters_[1] = 4; integerParameters_[2] = 4; #if 0 integerParameters_[5] = 3; doubleParameters_[5] = 1.0e-10; integerParameters_[6] = 6; #endif F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, array, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); #if 0 int iRow; for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped_[iRow] && fabs(array[iRow]) > 1.0e-8) { printf("row region1 %d dropped %g\n", iRow, array[iRow]); } } for (; iRow < numberRows_; iRow++) { if (rowsDropped_[iRow] && fabs(array[iRow]) > 1.0e-8) { printf("row region2 %d dropped %g\n", iRow, array[iRow]); } } #endif CoinMemcpyN(array + numberTotal, numberRowsModel, region2); #if 1 CoinMemcpyN(array, numberTotal, region1); #else multiplyAdd(region2, numberRowsModel, -1.0, array + numberColumns, 0.0); CoinZeroN(array, numberColumns); model_->clpMatrix()->transposeTimes(1.0, region2, array); for (int iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = diagonal[iColumn] * (array[iColumn] - region1[iColumn]); #endif delete [] array; #if 0 if (integerParameters_[5]) { std::cout << integerParameters_[5] << " refinements "; } std::cout << doubleParameters_[6] << std::endl; #endif } Clp-1.15.10/src/ClpLsqr.hpp0000644000076600007660000001131111510657452013736 0ustar coincoin/* $Id: ClpLsqr.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpLsqr_H_ #define ClpLsqr_H_ #include "CoinDenseVector.hpp" #include "ClpInterior.hpp" /** This class implements LSQR @verbatim LSQR solves Ax = b or min ||b - Ax||_2 if damp = 0, or min || (b) - ( A )x || otherwise. || (0) (damp I) ||2 A is an m by n matrix defined by user provided routines matVecMult(mode, y, x) which performs the matrix-vector operations where y and x are references or pointers to CoinDenseVector objects. If mode = 1, matVecMult must return y = Ax without altering x. If mode = 2, matVecMult must return y = A'x without altering x. ----------------------------------------------------------------------- LSQR uses an iterative (conjugate-gradient-like) method. For further information, see 1. C. C. Paige and M. A. Saunders (1982a). LSQR: An algorithm for sparse linear equations and sparse least squares, ACM TOMS 8(1), 43-71. 2. C. C. Paige and M. A. Saunders (1982b). Algorithm 583. LSQR: Sparse linear equations and least squares problems, ACM TOMS 8(2), 195-209. 3. M. A. Saunders (1995). Solution of sparse rectangular systems using LSQR and CRAIG, BIT 35, 588-604. Input parameters: atol, btol are stopping tolerances. If both are 1.0e-9 (say), the final residual norm should be accurate to about 9 digits. (The final x will usually have fewer correct digits, depending on cond(A) and the size of damp.) conlim is also a stopping tolerance. lsqr terminates if an estimate of cond(A) exceeds conlim. For compatible systems Ax = b, conlim could be as large as 1.0e+12 (say). For least-squares problems, conlim should be less than 1.0e+8. Maximum precision can be obtained by setting atol = btol = conlim = zero, but the number of iterations may then be excessive. itnlim is an explicit limit on iterations (for safety). show = 1 gives an iteration log, show = 0 suppresses output. info is a structure special to pdco.m, used to test if was small enough, and continuing if necessary with smaller atol. Output parameters: x is the final solution. *istop gives the reason for termination. *istop = 1 means x is an approximate solution to Ax = b. = 2 means x approximately solves the least-squares problem. rnorm = norm(r) if damp = 0, where r = b - Ax, = sqrt( norm(r)**2 + damp**2 * norm(x)**2 ) otherwise. xnorm = norm(x). var estimates diag( inv(A'A) ). Omitted in this special version. outfo is a structure special to pdco.m, returning information about whether atol had to be reduced. Other potential output parameters: anorm, acond, arnorm, xnorm @endverbatim */ class ClpLsqr { private: /**@name Private member data */ //@{ //@} public: /**@name Public member data */ //@{ /// Row dimension of matrix int nrows_; /// Column dimension of matrix int ncols_; /// Pointer to Model object for this instance ClpInterior *model_; /// Diagonal array 1 double *diag1_; /// Constant diagonal 2 double diag2_; //@} /**@name Constructors and destructors */ /** Default constructor */ ClpLsqr(); /** Constructor for use with Pdco model (note modified for pdco!!!!) */ ClpLsqr(ClpInterior *model); /// Copy constructor ClpLsqr(const ClpLsqr &); /// Assignment operator. This copies the data ClpLsqr & operator=(const ClpLsqr & rhs); /** Destructor */ ~ClpLsqr(); //@} /**@name Methods */ //@{ /// Set an int parameter bool setParam(char *parmName, int parmValue); /// Call the Lsqr algorithm void do_lsqr( CoinDenseVector &b, double damp, double atol, double btol, double conlim, int itnlim, bool show, Info info, CoinDenseVector &x , int *istop, int *itn, Outfo *outfo, bool precon, CoinDenseVector &Pr ); /// Matrix-vector multiply - implemented by user void matVecMult( int, CoinDenseVector *, CoinDenseVector *); void matVecMult( int, CoinDenseVector &, CoinDenseVector &); /// diag1 - we just borrow as it is part of a CoinDenseVector void borrowDiag1(double * array) { diag1_ = array; }; //@} }; #endif Clp-1.15.10/src/MyEventHandler.hpp0000644000076600007660000000231711510657452015251 0ustar coincoin/* $Id: MyEventHandler.hpp 1665 2011-01-04 17:55:54Z 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 MyEventHandler_H #define MyEventHandler_H #include "ClpEventHandler.hpp" /** This is so user can trap events and do useful stuff. This is used in Clp/Test/unitTest.cpp ClpSimplex model_ is available as well as anything else you care to pass in */ class MyEventHandler : public ClpEventHandler { public: /**@name Overrides */ //@{ virtual int event(Event whichEvent); //@} /**@name Constructors, destructor etc*/ //@{ /** Default constructor. */ MyEventHandler(); /// Constructor with pointer to model (redundant as setEventHandler does) MyEventHandler(ClpSimplex * model); /** Destructor */ virtual ~MyEventHandler(); /** The copy constructor. */ MyEventHandler(const MyEventHandler & rhs); /// Assignment MyEventHandler& operator=(const MyEventHandler & rhs); /// Clone virtual ClpEventHandler * clone() const ; //@} protected: // data goes here }; #endif Clp-1.15.10/src/ClpSimplexOther.hpp0000644000076600007660000003140012045774650015445 0ustar coincoin/* $Id: ClpSimplexOther.hpp 1884 2012-11-05 17:38:48Z 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). /* Authors John Forrest */ #ifndef ClpSimplexOther_H #define ClpSimplexOther_H #include "ClpSimplex.hpp" /** This is for Simplex stuff which is neither dual nor primal It inherits from ClpSimplex. It has no data of its own and is never created - only cast from a ClpSimplex object at algorithm time. */ class ClpSimplexOther : public ClpSimplex { public: /**@name Methods */ //@{ /** Dual ranging. This computes increase/decrease in cost for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For non-basic variables the information is trivial to compute and the change in cost is just minus the reduced cost and the sequence number will be that of the non-basic variables. For basic variables a ratio test is between the reduced costs for non-basic variables and the row of the tableau corresponding to the basic variable. The increase/decrease value is always >= 0.0 Up to user to provide correct length arrays where each array is of length numberCheck. which contains list of variables for which information is desired. All other arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays will be information for variable 7. If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with the value of variable if such a change in cost were made (the existing bounds are ignored) When here - guaranteed optimal */ void dualRanging(int numberCheck, const int * which, double * costIncrease, int * sequenceIncrease, double * costDecrease, int * sequenceDecrease, double * valueIncrease = NULL, double * valueDecrease = NULL); /** Primal ranging. This computes increase/decrease in value for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. This should only be used for non-basic variabls as otherwise information is pretty useless For basic variables the sequence number will be that of the basic variables. Up to user to provide correct length arrays where each array is of length numberCheck. which contains list of variables for which information is desired. All other arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays will be information for variable 7. When here - guaranteed optimal */ void primalRanging(int numberCheck, const int * which, double * valueIncrease, int * sequenceIncrease, double * valueDecrease, int * sequenceDecrease); /** Parametrics This is an initial slow version. The code uses current bounds + theta * change (if change array not NULL) and similarly for objective. It starts at startingTheta and returns ending theta in endingTheta. If reportIncrement 0.0 it will report on any movement If reportIncrement >0.0 it will report at startingTheta+k*reportIncrement. If it can not reach input endingTheta return code will be 1 for infeasible, 2 for unbounded, if error on ranges -1, otherwise 0. Normal report is just theta and objective but if event handler exists it may do more On exit endingTheta is maximum reached (can be used for next startingTheta) */ int parametrics(double startingTheta, double & endingTheta, double reportIncrement, const double * changeLowerBound, const double * changeUpperBound, const double * changeLowerRhs, const double * changeUpperRhs, const double * changeObjective); /** Version of parametrics which reads from file See CbcClpParam.cpp for details of format Returns -2 if unable to open file */ int parametrics(const char * dataFile); /** Parametrics This is an initial slow version. The code uses current bounds + theta * change (if change array not NULL) It starts at startingTheta and returns ending theta in endingTheta. If it can not reach input endingTheta return code will be 1 for infeasible, 2 for unbounded, if error on ranges -1, otherwise 0. Event handler may do more On exit endingTheta is maximum reached (can be used for next startingTheta) */ int parametrics(double startingTheta, double & endingTheta, const double * changeLowerBound, const double * changeUpperBound, const double * changeLowerRhs, const double * changeUpperRhs); int parametricsObj(double startingTheta, double & endingTheta, const double * changeObjective); /// Finds best possible pivot double bestPivot(bool justColumns=false); typedef struct { double startingTheta; double endingTheta; double maxTheta; double acceptableMaxTheta; // if this far then within tolerances double * lowerChange; // full array of lower bound changes int * lowerList; // list of lower bound changes double * upperChange; // full array of upper bound changes int * upperList; // list of upper bound changes char * markDone; // mark which ones looked at int * backwardBasic; // from sequence to pivot row int * lowerActive; double * lowerGap; double * lowerCoefficient; int * upperActive; double * upperGap; double * upperCoefficient; int unscaledChangesOffset; bool firstIteration; // so can update rhs for accuracy } parametricsData; private: /** Parametrics - inner loop This first attempt is when reportIncrement non zero and may not report endingTheta correctly If it can not reach input endingTheta return code will be 1 for infeasible, 2 for unbounded, otherwise 0. Normal report is just theta and objective but if event handler exists it may do more */ int parametricsLoop(parametricsData & paramData, double reportIncrement, const double * changeLower, const double * changeUpper, const double * changeObjective, ClpDataSave & data, bool canTryQuick); int parametricsLoop(parametricsData & paramData, ClpDataSave & data,bool canSkipFactorization=false); int parametricsObjLoop(parametricsData & paramData, ClpDataSave & data,bool canSkipFactorization=false); /** Refactorizes if necessary Checks if finished. Updates status. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved */ void statusOfProblemInParametrics(int type, ClpDataSave & saveData); void statusOfProblemInParametricsObj(int type, ClpDataSave & saveData); /** This has the flow between re-factorizations Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int whileIterating(parametricsData & paramData, double reportIncrement, const double * changeObjective); /** Computes next theta and says if objective or bounds (0= bounds, 1 objective, -1 none). theta is in theta_. type 1 bounds, 2 objective, 3 both. */ int nextTheta(int type, double maxTheta, parametricsData & paramData, const double * changeObjective); int whileIteratingObj(parametricsData & paramData); int nextThetaObj(double maxTheta, parametricsData & paramData); /// Restores bound to original bound void originalBound(int iSequence, double theta, const double * changeLower, const double * changeUpper); /// Compute new rowLower_ etc (return negative if infeasible - otherwise largest change) double computeRhsEtc(parametricsData & paramData); /// Redo lower_ from rowLower_ etc void redoInternalArrays(); /** Row array has row part of pivot row Column array has column part. This is used in dual ranging */ void checkDualRatios(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double & costIncrease, int & sequenceIncrease, double & alphaIncrease, double & costDecrease, int & sequenceDecrease, double & alphaDecrease); /** Row array has pivot column This is used in primal ranging */ void checkPrimalRatios(CoinIndexedVector * rowArray, int direction); /// Returns new value of whichOther when whichIn enters basis double primalRanging1(int whichIn, int whichOther); public: /** Write the basis in MPS format to the specified file. If writeValues true writes values of structurals (and adds VALUES to end of NAME card) Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex (later)
Returns non-zero on I/O error */ int writeBasis(const char *filename, bool writeValues = false, int formatType = 0) const; /// Read a basis from the given filename int readBasis(const char *filename); /** Creates dual of a problem if looks plausible (defaults will always create model) fractionRowRanges is fraction of rows allowed to have ranges fractionColumnRanges is fraction of columns allowed to have ranges */ ClpSimplex * dualOfModel(double fractionRowRanges = 1.0, double fractionColumnRanges = 1.0) const; /** Restores solution from dualized problem non-zero return code indicates minor problems */ int restoreFromDual(const ClpSimplex * dualProblem, bool checkAccuracy=false); /** Does very cursory presolve. rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. */ ClpSimplex * crunch(double * rhs, int * whichRows, int * whichColumns, int & nBound, bool moreBounds = false, bool tightenBounds = false); /** After very cursory presolve. rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. */ void afterCrunch(const ClpSimplex & small, const int * whichRows, const int * whichColumns, int nBound); /** Returns gub version of model or NULL whichRows has to be numberRows whichColumns has to be numberRows+numberColumns */ ClpSimplex * gubVersion(int * whichRows, int * whichColumns, int neededGub, int factorizationFrequency=50); /// Sets basis from original void setGubBasis(ClpSimplex &original,const int * whichRows, const int * whichColumns); /// Restores basis to original void getGubBasis(ClpSimplex &original,const int * whichRows, const int * whichColumns) const; /// Quick try at cleaning up duals if postsolve gets wrong void cleanupAfterPostsolve(); /** Tightens integer bounds - returns number tightened or -1 if infeasible */ int tightenIntegerBounds(double * rhsSpace); /** 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 expandKnapsack(int knapsackRow, int & numberOutput, double * buildObj, CoinBigIndex * buildStart, int * buildRow, double * buildElement, int reConstruct = -1) const; //@} }; #endif Clp-1.15.10/src/AbcPrimalColumnSteepest.cpp0000644000076600007660000025053312101105055017071 0ustar coincoin/* $Id: AbcPrimalColumnSteepest.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "AbcSimplex.hpp" #include "AbcPrimalColumnSteepest.hpp" #include "CoinIndexedVector.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcNonLinearCost.hpp" #include "ClpMessage.hpp" #include "CoinHelperFunctions.hpp" #undef COIN_DETAIL_PRINT #define COIN_DETAIL_PRINT(s) s #include //#define CLP_DEBUG //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcPrimalColumnSteepest::AbcPrimalColumnSteepest (int mode) : AbcPrimalColumnPivot(), devex_(0.0), weights_(NULL), infeasible_(NULL), alternateWeights_(NULL), savedWeights_(NULL), reference_(NULL), state_(-1), mode_(mode), persistence_(normal), numberSwitched_(0), pivotSequence_(-1), savedPivotSequence_(-1), savedSequenceOut_(-1), sizeFactorization_(0) { type_ = 2 + 64 * mode; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcPrimalColumnSteepest::AbcPrimalColumnSteepest (const AbcPrimalColumnSteepest & rhs) : AbcPrimalColumnPivot(rhs) { state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; numberSwitched_ = rhs.numberSwitched_; model_ = rhs.model_; pivotSequence_ = rhs.pivotSequence_; savedPivotSequence_ = rhs.savedPivotSequence_; savedSequenceOut_ = rhs.savedSequenceOut_; sizeFactorization_ = rhs.sizeFactorization_; devex_ = rhs.devex_; if ((model_ && model_->whatsChanged() & 1) != 0) { if (rhs.infeasible_) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } reference_ = NULL; if (rhs.weights_) { assert(model_); int number = model_->numberRows() + model_->numberColumns(); assert (number == rhs.model_->numberRows() + rhs.model_->numberColumns()); weights_ = new double[number]; CoinMemcpyN(rhs.weights_, number, weights_); savedWeights_ = new double[number]; CoinMemcpyN(rhs.savedWeights_, number, savedWeights_); if (mode_ != 1) { reference_ = CoinCopyOfArray(rhs.reference_, (number + 31) >> 5); } } else { weights_ = NULL; savedWeights_ = NULL; } if (rhs.alternateWeights_) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } } else { infeasible_ = NULL; reference_ = NULL; weights_ = NULL; savedWeights_ = NULL; alternateWeights_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcPrimalColumnSteepest::~AbcPrimalColumnSteepest () { delete [] weights_; delete infeasible_; delete alternateWeights_; delete [] savedWeights_; delete [] reference_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcPrimalColumnSteepest & AbcPrimalColumnSteepest::operator=(const AbcPrimalColumnSteepest& rhs) { if (this != &rhs) { AbcPrimalColumnPivot::operator=(rhs); state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; numberSwitched_ = rhs.numberSwitched_; model_ = rhs.model_; pivotSequence_ = rhs.pivotSequence_; savedPivotSequence_ = rhs.savedPivotSequence_; savedSequenceOut_ = rhs.savedSequenceOut_; sizeFactorization_ = rhs.sizeFactorization_; devex_ = rhs.devex_; delete [] weights_; delete [] reference_; reference_ = NULL; delete infeasible_; delete alternateWeights_; delete [] savedWeights_; savedWeights_ = NULL; if (rhs.infeasible_ != NULL) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_ != NULL) { assert(model_); int number = model_->numberRows() + model_->numberColumns(); assert (number == rhs.model_->numberRows() + rhs.model_->numberColumns()); weights_ = new double[number]; CoinMemcpyN(rhs.weights_, number, weights_); savedWeights_ = new double[number]; CoinMemcpyN(rhs.savedWeights_, number, savedWeights_); if (mode_ != 1) { reference_ = CoinCopyOfArray(rhs.reference_, (number + 31) >> 5); } } else { weights_ = NULL; } if (rhs.alternateWeights_ != NULL) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } } return *this; } // These have to match ClpPackedMatrix version #define TRY_NORM 1.0e-4 #define ADD_ONE 1.0 // Returns pivot column, -1 if none /* The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row*/ int AbcPrimalColumnSteepest::pivotColumn(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1) { assert(model_); int number = 0; int * index; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); int anyUpdates; double * infeas = infeasible_->denseVector(); // Local copy of mode so can decide what to do int switchType; if (mode_ == 4) switchType = 5 - numberSwitched_; else if (mode_ >= 10) switchType = 3; else switchType = mode_; /* switchType - 0 - all exact devex 1 - all steepest 2 - some exact devex 3 - auto some exact devex 4 - devex 5 - dantzig 10 - can go to mini-sprint */ if (updates->getNumElements() > 1) { // would have to have two goes for devex, three for steepest anyUpdates = 2; } else if (updates->getNumElements()) { if (updates->getIndices()[0] == pivotRow && fabs(updates->denseVector()[pivotRow]) > 1.0e-6) { //&& fabs(updates->denseVector()[pivotRow]) < 1.0e6) { // reasonable size anyUpdates = 1; //if (fabs(model_->dualIn())<1.0e-4||fabs(fabs(model_->dualIn())-fabs(updates->denseVector()[0]))>1.0e-5) //printf("dualin %g pivot %g\n",model_->dualIn(),updates->denseVector()[0]); } else { // too small anyUpdates = 2; } } else if (pivotSequence_ >= 0) { // just after re-factorization anyUpdates = -1; } else { // sub flip - nothing to do anyUpdates = 0; } int sequenceOut = model_->sequenceOut(); if (switchType == 5) { pivotSequence_ = -1; pivotRow = -1; // See if to switch int numberRows = model_->numberRows(); int numberWanted = 10; int numberColumns = model_->numberColumns(); double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); // Number of dual infeasibilities at last invert int numberDual = model_->numberDualInfeasibilities(); int numberLook = CoinMin(numberDual, numberColumns / 10); if (ratio < 1.0) { numberWanted = 100; numberLook /= 20; numberWanted = CoinMax(numberWanted, numberLook); } else if (ratio < 3.0) { numberWanted = 500; numberLook /= 15; numberWanted = CoinMax(numberWanted, numberLook); } else if (ratio < 4.0 || mode_ == 5) { numberWanted = 1000; numberLook /= 10; numberWanted = CoinMax(numberWanted, numberLook); } else if (mode_ != 5) { switchType = 4; // initialize numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; //work space int whichArray[2]; for (int i=0;i<2;i++) whichArray[i]=model_->getAvailableArray(); CoinIndexedVector * array1 = model_->usefulArray(whichArray[0]); CoinIndexedVector * array2 = model_->usefulArray(whichArray[1]); model_->computeDuals(NULL,array1,array2); for (int i=0;i<2;i++) model_->setAvailableArray(whichArray[i]); saveWeights(model_, 4); anyUpdates = 0; COIN_DETAIL_PRINT(printf("switching to devex %d nel ratio %g\n", sizeFactorization_, ratio)); } if (switchType == 5) { numberLook *= 5; // needs tuning for gub if (model_->numberIterations() % 1000 == 0 && model_->logLevel() > 1) { COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d look %d\n", sizeFactorization_, ratio, numberWanted, numberLook)); } // Update duals and row djs // Do partial pricing return partialPricing(updates, numberWanted, numberLook); } } if (switchType == 5) { if (anyUpdates > 0) { justDjs(updates,spareColumn1); } } else if (anyUpdates == 1) { if (switchType < 4) { // exact etc when can use dj doSteepestWork(updates,spareRow2,spareColumn1,2); } else { // devex etc when can use dj djsAndDevex(updates, spareRow2, spareColumn1); } } else if (anyUpdates == -1) { if (switchType < 4) { // exact etc when djs okay //if (model_->maximumIterations()!=1000) doSteepestWork(updates,spareRow2,spareColumn1,1); } else { // devex etc when djs okay justDevex(updates, spareColumn1); } } else if (anyUpdates == 2) { if (switchType < 4) { // exact etc when have to use pivot doSteepestWork(updates,spareRow2,spareColumn1,3); } else { // devex etc when have to use pivot djsAndDevex2(updates, spareColumn1); } } #ifdef CLP_DEBUG alternateWeights_->checkClear(); #endif // make sure outgoing from last iteration okay if (sequenceOut >= 0) { AbcSimplex::Status status = model_->getInternalStatus(sequenceOut); double value = model_->reducedCost(sequenceOut); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case AbcSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case AbcSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } } } // update of duals finished - now do pricing // See what sort of pricing int numberWanted = 10; number = infeasible_->getNumElements(); int numberColumns = model_->numberColumns(); if (switchType == 5) { pivotSequence_ = -1; pivotRow = -1; // See if to switch int numberRows = model_->numberRows(); // ratio is done on number of columns here //double ratio = static_cast sizeFactorization_/static_cast numberColumns; double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); if (ratio < 1.0) { numberWanted = CoinMax(100, number / 200); } else if (ratio < 2.0 - 1.0) { numberWanted = CoinMax(500, number / 40); } else if (ratio < 4.0 - 3.0 || mode_ == 5) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 30); } else if (mode_ != 5) { switchType = 4; // initialize numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to devex %d nel ratio %g\n", sizeFactorization_, ratio)); } //if (model_->numberIterations()%1000==0) //printf("numels %d ratio %g wanted %d\n",sizeFactorization_,ratio,numberWanted); } int numberRows = model_->numberRows(); // ratio is done on number of rows here double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); if(switchType == 4) { // Still in devex mode // Go to steepest if lot of iterations? if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else if (ratio < 7.0) { numberWanted = CoinMax(2000, number / 5); numberWanted = CoinMax(numberWanted, numberColumns / 10); } else { // we can zero out updates->clear(); spareColumn1->clear(); switchType = 3; // initialize pivotSequence_ = -1; pivotRow = -1; numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to exact %d nel ratio %g\n", sizeFactorization_, ratio)); updates->clear(); } if (model_->numberIterations() % 1000 == 0) COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d type x\n", sizeFactorization_, ratio, numberWanted)); } if (switchType < 4) { if (switchType < 2 ) { numberWanted = number + 1; } else if (switchType == 2) { numberWanted = CoinMax(2000, number / 8); } else { if (ratio < 1.0) { numberWanted = CoinMax(2000, number / 20); } else if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 40); } else if (ratio < 10.0) { numberWanted = CoinMax(2000, number / 8); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else { ratio = number * (ratio / 80.0); if (ratio > number) { numberWanted = number + 1; } else { numberWanted = CoinMax(2000, static_cast (ratio)); numberWanted = CoinMax(numberWanted, numberColumns / 10); } } } //if (model_->numberIterations()%1000==0) //printf("numels %d ratio %g wanted %d type %d\n",sizeFactorization_,ratio,numberWanted, //switchType); } double bestDj = 1.0e-30; int bestSequence = -1; int i, iSequence; index = infeasible_->getIndices(); number = infeasible_->getNumElements(); if(model_->numberIterations() < model_->lastBadIteration() + 200 && model_->factorization()->pivots() > 10) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } #ifdef CLP_DEBUG if (model_->numberDualInfeasibilities() == 1) printf("** %g %g %g %x %x %d\n", tolerance, model_->dualTolerance(), model_->largestDualError(), model_, model_->messageHandler(), number); #endif // stop last one coming immediately double saveOutInfeasibility = 0.0; if (sequenceOut >= 0) { saveOutInfeasibility = infeas[sequenceOut]; infeas[sequenceOut] = 0.0; } if (model_->factorization()->pivots() && model_->numberPrimalInfeasibilities()) tolerance = CoinMax(tolerance, 1.0e-10 * model_->infeasibilityCost()); tolerance *= tolerance; // as we are using squares int iPass; // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; //double largestWeight=0.0; //double smallestWeight=1.0e100; for (iPass = 0; iPass < 2; iPass++) { int end = start[2*iPass+1]; if (switchType < 5) { for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; double weight = weights_[iSequence]; if (value > tolerance) { //weight=1.0; if (value > bestDj * weight) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value / weight; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } numberWanted--; } if (!numberWanted) break; } } else { // Dantzig for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; if (value > tolerance) { if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } numberWanted--; } if (!numberWanted) break; } } if (!numberWanted) break; } if (sequenceOut >= 0) { infeas[sequenceOut] = saveOutInfeasibility; } /*if (model_->numberIterations()%100==0) printf("%d best %g\n",bestSequence,bestDj);*/ #ifndef NDEBUG if (bestSequence >= 0) { if (model_->getInternalStatus(bestSequence) == AbcSimplex::atLowerBound) assert(model_->reducedCost(bestSequence) < 0.0); if (model_->getInternalStatus(bestSequence) == AbcSimplex::atUpperBound) { assert(model_->reducedCost(bestSequence) > 0.0); } } #endif #if 1 if (model_->logLevel()==127) { double * reducedCost=model_->djRegion(); for (int i=0;i1.0e-13 ? infeas[i]: 0.0,reducedCost[i]); for (int i=numberRows;i1.0e-13 ? infeas[i]: 0.0,reducedCost[i]); } #endif #if SOME_DEBUG_1 if (switchType<4) { // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getInternalStatus(iCheck) != AbcSimplex::basic && model_->getInternalStatus(iCheck) != AbcSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates); } } #endif #if 0 for (int iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getInternalStatus(iCheck) != AbcSimplex::basic && model_->getInternalStatus(iCheck) != AbcSimplex::isFixed) assert (fabs(model_->costRegion()[iCheck])<1.0e9); } #endif return bestSequence; } /* Does steepest work type - 0 - just djs 1 - just steepest 2 - both using scaleFactor 3 - both using extra array */ int AbcPrimalColumnSteepest::doSteepestWork(CoinPartitionedVector * updates, CoinPartitionedVector * spareRow2, CoinPartitionedVector * spareColumn1, int type) { int pivotRow = model_->pivotRow(); if (type==1) { pivotRow=pivotSequence_; if (pivotRow<0) type=-1; } else if (pivotSequence_<0) { assert (model_->sequenceIn()==model_->sequenceOut()); type=0; } // see if reference int sequenceIn = pivotRow>=0 ? model_->sequenceIn() : -1; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; double referenceIn; if (mode_ != 1) { if(sequenceIn>=0&&reference(sequenceIn)) referenceIn = 1.0; else referenceIn = 0.0; } else { referenceIn = -1.0; } double * infeasibilities=infeasible_->denseVector(); if (sequenceIn>=0) infeasibilities[sequenceIn]=0.0; double * array=updates->denseVector(); double scaleFactor; double devex=devex_; if (type==0) { // just djs - to keep clean swap scaleFactor=1.0; CoinPartitionedVector * temp = updates; updates=spareRow2; spareRow2=temp; assert (!alternateWeights_->getNumElements()); devex=0.0; } else if (type==1) { // just steepest updates->clear(); scaleFactor=COIN_DBL_MAX; // might as well set dj to 1 double dj = -1.0; assert (pivotRow>=0); spareRow2->createUnpacked(1, &pivotRow, &dj); } else if (type==2) { // using scaleFactor - swap assert (pivotRow>=0); scaleFactor=-array[pivotRow]; array[pivotRow]=-1.0; CoinPartitionedVector * temp = updates; updates=spareRow2; spareRow2=temp; } else if (type==3) { // need two arrays scaleFactor=0.0; // might as well set dj to 1 double dj = -1.0; assert (pivotRow>=0); spareRow2->createUnpacked(1, &pivotRow, &dj); } if (type>=0) { // parallelize this if (type==0) { model_->factorization()->updateColumnTranspose(*spareRow2); } else if (type<3) { cilk_spawn model_->factorization()->updateColumnTransposeCpu(*spareRow2,0); model_->factorization()->updateColumnTransposeCpu(*alternateWeights_,1); cilk_sync; } else { cilk_spawn model_->factorization()->updateColumnTransposeCpu(*updates,0); cilk_spawn model_->factorization()->updateColumnTransposeCpu(*spareRow2,1); model_->factorization()->updateColumnTransposeCpu(*alternateWeights_,2); cilk_sync; } model_->abcMatrix()->primalColumnDouble(*spareRow2, *updates, *alternateWeights_, *spareColumn1, *infeasible_,referenceIn,devex, reference_,weights_,scaleFactor); } pivotSequence_=-1; // later do pricing here // later move pricing into abcmatrix // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; alternateWeights_->clear(); updates->clear(); spareRow2->clear(); return 0; } // Just update djs void AbcPrimalColumnSteepest::justDjs(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1) { int iSection, j; int number = 0; double multiplier; int * index; double * updateBy; double * reducedCost; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(*updates); // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); // normal reducedCost = model_->djRegion(); for (iSection = 0; iSection < 2; iSection++) { int addSequence; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER double slack_multiplier; #endif if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = 0; multiplier=-1; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = CLP_PRIMAL_SLACK_MULTIPLIER; #endif } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = model_->maximumAbcNumberRows(); multiplier=1; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = 1.0; #endif } for (j = 0; j < number; j++) { int iSequence = index[j]; double tableauValue=updateBy[iSequence]; updateBy[iSequence] = 0.0; iSequence += addSequence; double value = reducedCost[iSequence]; value -= multiplier*tableauValue; reducedCost[iSequence] = value; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: infeasible_->zero(iSequence); case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence , value * value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atUpperBound: if (value > tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atLowerBound: if (value < -tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } } updates->setNumElements(0); spareColumn1->setNumElements(0); if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); } } // Update djs, weights for Devex void AbcPrimalColumnSteepest::djsAndDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1) { int j; int number = 0; int * index; double * updateBy; double * reducedCost; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // for weights update we use pivotSequence // unset in case sub flip assert (pivotSequence_ >= 0); assert (model_->pivotVariable()[pivotSequence_] == model_->sequenceIn()); double scaleFactor = 1.0 / updates->denseVector()[pivotSequence_]; // as formula is with 1.0 pivotSequence_ = -1; double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(*updates); // and we can see if reference //double referenceIn = 0.0; int sequenceIn = model_->sequenceIn(); //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); // update weights double * weight; // rows reducedCost = model_->djRegion(); number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_; // Devex for (j = 0; j < number; j++) { double thisWeight; double pivot; double value3; int iSequence = index[j]; double value = reducedCost[iSequence]; double value2 = updateBy[iSequence]; updateBy[iSequence] = 0.0; value -= -value2; reducedCost[iSequence] = value; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: infeasible_->zero(iSequence); case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence , value * value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atUpperBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value > tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence , value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atLowerBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value < -tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence , value); } else { infeasible_->zero(iSequence); } } } // columns int addSequence = model_->maximumAbcNumberRows(); scaleFactor = -scaleFactor; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); // Devex for (j = 0; j < number; j++) { double thisWeight; double pivot; double value3; int iSequence = index[j]; double value2=updateBy[iSequence]; updateBy[iSequence] = 0.0; iSequence += addSequence; double value = reducedCost[iSequence]; value -= value2; reducedCost[iSequence] = value; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: infeasible_->zero(iSequence); case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atUpperBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value > tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atLowerBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value < -tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } } } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; // make sure infeasibility on incoming is 0.0 infeasible_->zero(sequenceIn); spareRow2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getInternalStatus(iCheck) != AbcSimplex::basic && !model_->getInternalStatus(iCheck) != AbcSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Update djs, weights for Devex void AbcPrimalColumnSteepest::djsAndDevex2(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1) { int iSection, j; int number = 0; double multiplier; int * index; double * updateBy; double * reducedCost; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(*updates); // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); // normal reducedCost = model_->djRegion(); for (iSection = 0; iSection < 2; iSection++) { int addSequence; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER double slack_multiplier; #endif if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = 0; multiplier=-1; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = CLP_PRIMAL_SLACK_MULTIPLIER; #endif } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = model_->maximumAbcNumberRows(); multiplier=1; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = 1.0; #endif } for (j = 0; j < number; j++) { int iSequence = index[j]; double tableauValue=updateBy[iSequence]; updateBy[iSequence] = 0.0; iSequence += addSequence; double value = reducedCost[iSequence]; value -= multiplier*tableauValue; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: infeasible_->zero(iSequence); case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: reducedCost[iSequence] = value; if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence , value * value); } else { infeasible_->zero(iSequence ); } break; case AbcSimplex::atUpperBound: reducedCost[iSequence] = value; if (value > tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } break; case AbcSimplex::atLowerBound: reducedCost[iSequence] = value; if (value < -tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } } // They are empty updates->setNumElements(0); spareColumn1->setNumElements(0); // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); // for weights update we use pivotSequence if (pivotSequence_ >= 0) { pivotRow = pivotSequence_; // unset in case sub flip pivotSequence_ = -1; // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference //double referenceIn = 0.0; //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // update weights updates->setNumElements(0); spareColumn1->setNumElements(0); // might as well set dj to 1 dj = 1.0; updates->insert(pivotRow, -dj); model_->factorization()->updateColumnTranspose(*updates); // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); double * weight; int numberColumns = model_->numberColumns(); // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_; assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = - updateBy[iSequence]; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // columns number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); int addSequence = model_->maximumAbcNumberRows(); for (j = 0; j < number; j++) { int iSequence = index[j]; double pivot=updateBy[iSequence]; updateBy[iSequence] = 0.0; iSequence += addSequence; double thisWeight = weight[iSequence]; // row has -1 double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getInternalStatus(iCheck) != AbcSimplex::basic && !model_->getInternalStatus(iCheck) != AbcSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } } // Update weights for Devex void AbcPrimalColumnSteepest::justDevex(CoinIndexedVector * updates, CoinIndexedVector * spareColumn1) { int j; int number = 0; int * index; double * updateBy; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); // for weights update we use pivotSequence pivotRow = pivotSequence_; assert (pivotRow >= 0); // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); int sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference //double referenceIn = 0.0; //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; assert (!updates->getNumElements()); assert (!spareColumn1->getNumElements()); // unset in case sub flip pivotSequence_ = -1; // might as well set dj to 1 dj = -1.0; updates->createUnpacked(1, &pivotRow, &dj); model_->factorization()->updateColumnTranspose(*updates); // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); double * weight; // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_; // Devex assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = - updateBy[iSequence]; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // columns int addSequence = model_->maximumAbcNumberRows(); number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); // Devex for (j = 0; j < number; j++) { int iSequence = index[j]; double pivot=updateBy[iSequence]; updateBy[iSequence] = 0.0; iSequence += addSequence; double thisWeight = weight[iSequence]; // row has -1 double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getInternalStatus(iCheck) != AbcSimplex::basic && !model_->getInternalStatus(iCheck) != AbcSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Called when maximum pivots changes void AbcPrimalColumnSteepest::maximumPivotsChanged() { if (alternateWeights_ && alternateWeights_->capacity() != model_->numberRows() + model_->factorization()->maximumPivots()) { delete alternateWeights_; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization // enoughfor ordered alternateWeights_->reserve(2*model_->numberRows() + model_->factorization()->maximumPivots()); } } /* 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights 5) at end of values pass (so need initialization) */ void AbcPrimalColumnSteepest::saveWeights(AbcSimplex * model, int mode) { model_ = model; if (mode_ == 4 || mode_ == 5) { if (mode == 1 && !weights_) numberSwitched_ = 0; // Reset } // alternateWeights_ is defined as indexed but is treated oddly // at times int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); int maximumRows=model_->maximumAbcNumberRows(); const int * pivotVariable = model_->pivotVariable(); bool doInfeasibilities = true; if (mode == 1) { if(weights_) { // Check if size has changed if (infeasible_->capacity() == numberRows + numberColumns && alternateWeights_->capacity() == 2*numberRows + model_->factorization()->maximumPivots()) { //alternateWeights_->clear(); if (pivotSequence_ >= 0 && pivotSequence_ < numberRows) { // save pivot order CoinMemcpyN(pivotVariable, numberRows, alternateWeights_->getIndices()); // change from pivot row number to sequence number pivotSequence_ = pivotVariable[pivotSequence_]; } else { pivotSequence_ = -1; } state_ = 1; } else { // size has changed - clear everything delete [] weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete [] savedWeights_; savedWeights_ = NULL; delete [] reference_; reference_ = NULL; state_ = -1; pivotSequence_ = -1; } } } else if (mode == 2 || mode == 4 || mode == 5) { // restore if (!weights_ || state_ == -1 || mode == 5) { // Partial is only allowed with certain types of matrix if ((mode_ != 4 && mode_ != 5) || numberSwitched_ ) { // initialize weights delete [] weights_; delete alternateWeights_; weights_ = new double[numberRows+numberColumns]; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization alternateWeights_->reserve(2*numberRows + model_->factorization()->maximumPivots()); initializeWeights(); // create saved weights delete [] savedWeights_; savedWeights_ = CoinCopyOfArray(weights_, numberRows + numberColumns); // just do initialization mode = 3; } else { // Partial pricing // use region as somewhere to save non-fixed slacks // set up infeasibilities if (!infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberColumns + numberRows); } infeasible_->clear(); int number = model_->numberRows(); int iSequence; int numberLook = 0; int * which = infeasible_->getIndices(); for (iSequence = 0; iSequence < number; iSequence++) { AbcSimplex::Status status = model_->getInternalStatus(iSequence); if (status != AbcSimplex::isFixed) which[numberLook++] = iSequence; } infeasible_->setNumElements(numberLook); doInfeasibilities = false; } savedPivotSequence_ = -2; savedSequenceOut_ = -2; } else { if (mode != 4) { // save CoinMemcpyN(weights_, (numberRows + numberColumns), savedWeights_); savedPivotSequence_ = pivotSequence_; savedSequenceOut_ = model_->sequenceOut(); } else { // restore CoinMemcpyN(savedWeights_, (numberRows + numberColumns), weights_); // was - but I think should not be //pivotSequence_= savedPivotSequence_; //model_->setSequenceOut(savedSequenceOut_); pivotSequence_ = -1; model_->setSequenceOut(-1); // indices are wrong so clear by hand //alternateWeights_->clear(); CoinZeroN(alternateWeights_->denseVector(), alternateWeights_->capacity()); alternateWeights_->setNumElements(0); } } state_ = 0; // set up infeasibilities if (!infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberColumns + numberRows); } } if (mode >= 2 && mode != 5) { if (mode != 3) { if (pivotSequence_ >= 0) { // restore pivot row int iRow; // permute alternateWeights int iVector=model_->getAvailableArray(); double * temp = model_->usefulArray(iVector)->denseVector();; double * work = alternateWeights_->denseVector(); int * savePivotOrder = model_->usefulArray(iVector)->getIndices(); int * oldPivotOrder = alternateWeights_->getIndices(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = oldPivotOrder[iRow]; temp[iPivot] = work[iRow]; savePivotOrder[iRow] = iPivot; } int number = 0; int found = -1; int * which = oldPivotOrder; // find pivot row and re-create alternateWeights for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; if (iPivot == pivotSequence_) found = iRow; work[iRow] = temp[iPivot]; if (work[iRow]) which[number++] = iRow; } alternateWeights_->setNumElements(number); #ifdef CLP_DEBUG // Can happen but I should clean up assert(found >= 0); #endif pivotSequence_ = found; for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = savePivotOrder[iRow]; temp[iPivot] = 0.0; } model_->setAvailableArray(iVector); } else { // Just clean up if (alternateWeights_) alternateWeights_->clear(); } } // Save size of factorization if (!model->factorization()->pivots()) sizeFactorization_ = model_->factorization()->numberElements(); if(!doInfeasibilities) return; // don't disturb infeasibilities infeasible_->clear(); double tolerance = model_->currentDualTolerance(); int number = model_->numberRows() + model_->numberColumns(); int iSequence; double * reducedCost = model_->djRegion(); #ifndef CLP_PRIMAL_SLACK_MULTIPLIER for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case AbcSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } break; case AbcSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } } } #else // Columns for (iSequence = maximumRows; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case AbcSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } break; case AbcSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } } } // Rows for (iSequence=0 ; iSequence < numberRows; iSequence++) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case AbcSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value * CLP_PRIMAL_SLACK_MULTIPLIER); } break; case AbcSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value * CLP_PRIMAL_SLACK_MULTIPLIER); } } } #endif } } // Gets rid of last update void AbcPrimalColumnSteepest::unrollWeights() { if ((mode_ == 4 || mode_ == 5) && !numberSwitched_) return; double * saved = alternateWeights_->denseVector(); int number = alternateWeights_->getNumElements(); int * which = alternateWeights_->getIndices(); int i; for (i = 0; i < number; i++) { int iRow = which[i]; weights_[iRow] = saved[iRow]; saved[iRow] = 0.0; } alternateWeights_->setNumElements(0); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- AbcPrimalColumnPivot * AbcPrimalColumnSteepest::clone(bool CopyData) const { if (CopyData) { return new AbcPrimalColumnSteepest(*this); } else { return new AbcPrimalColumnSteepest(); } } void AbcPrimalColumnSteepest::updateWeights(CoinIndexedVector * input) { // Local copy of mode so can decide what to do int switchType = mode_; if (mode_ == 4 && numberSwitched_) switchType = 3; else if (mode_ == 4 || mode_ == 5) return; int number = input->getNumElements(); int * which = input->getIndices(); double * work = input->denseVector(); int newNumber = 0; int * newWhich = alternateWeights_->getIndices(); double * newWork = alternateWeights_->denseVector(); int i; int sequenceIn = model_->sequenceIn(); int sequenceOut = model_->sequenceOut(); const int * pivotVariable = model_->pivotVariable(); int pivotRow = model_->pivotRow(); pivotSequence_ = pivotRow; devex_ = 0.0; if (pivotRow >= 0) { if (switchType == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex_ += work[iRow] * work[iRow]; newWork[iRow] = -2.0 * work[iRow]; } newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); devex_ += ADD_ONE; weights_[sequenceOut] = 1.0 + ADD_ONE; CoinMemcpyN(which, number, newWhich); alternateWeights_->setNumElements(number); } else { if ((mode_ != 4 && mode_ != 5) || numberSwitched_ > 1) { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[iRow] * work[iRow]; newWork[iRow] = -2.0 * work[iRow]; newWhich[newNumber++] = iRow; } } if (!newWork[pivotRow] && devex_ > 0.0) newWhich[newNumber++] = pivotRow; // add if not already in newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) devex_ += work[iRow] * work[iRow]; } } if (reference(sequenceIn)) { devex_ += 1.0; } else { } if (reference(sequenceOut)) { weights_[sequenceOut] = 1.0 + 1.0; } else { weights_[sequenceOut] = 1.0; } alternateWeights_->setNumElements(newNumber); } } else { if (switchType == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex_ += work[iRow] * work[iRow]; } devex_ += ADD_ONE; } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[iRow] * work[iRow]; } } if (reference(sequenceIn)) devex_ += 1.0; } } double oldDevex = weights_[sequenceIn]; #ifdef CLP_DEBUG if ((model_->messageHandler()->logLevel() & 32)) printf("old weight %g, new %g\n", oldDevex, devex_); #endif double check = CoinMax(devex_, oldDevex) + 0.1; weights_[sequenceIn] = devex_; double testValue = 0.1; if (mode_ == 4 && numberSwitched_ == 1) testValue = 0.5; if ( fabs ( devex_ - oldDevex ) > testValue * check ) { #ifdef CLP_DEBUG if ((model_->messageHandler()->logLevel() & 48) == 16) printf("old weight %g, new %g\n", oldDevex, devex_); #endif //printf("old weight %g, new %g\n",oldDevex,devex_); testValue = 0.99; if (mode_ == 1) testValue = 1.01e1; // make unlikely to do if steepest else if (mode_ == 4 && numberSwitched_ == 1) testValue = 0.9; double difference = fabs(devex_ - oldDevex); if ( difference > testValue * check ) { // need to redo model_->messageHandler()->message(CLP_INITIALIZE_STEEP, *model_->messagesPointer()) << oldDevex << devex_ << CoinMessageEol; initializeWeights(); } } if (pivotRow >= 0) { // set outgoing weight here weights_[model_->sequenceOut()] = devex_ / (model_->alpha() * model_->alpha()); } } // Checks accuracy - just for debug void AbcPrimalColumnSteepest::checkAccuracy(int sequence, double relativeTolerance, CoinIndexedVector * rowArray1) { if ((mode_ == 4 || mode_ == 5) && !numberSwitched_) return; model_->unpack(*rowArray1, sequence); model_->factorization()->updateColumn(*rowArray1); int number = rowArray1->getNumElements(); int * which = rowArray1->getIndices(); double * work = rowArray1->denseVector(); const int * pivotVariable = model_->pivotVariable(); double devex = 0.0; int i; if (mode_ == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex += work[iRow] * work[iRow]; work[iRow] = 0.0; } devex += ADD_ONE; } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex += work[iRow] * work[iRow]; } work[iRow] = 0.0; } if (reference(sequence)) devex += 1.0; } double oldDevex = weights_[sequence]; double check = CoinMax(devex, oldDevex);; if ( fabs ( devex - oldDevex ) > relativeTolerance * check ) { COIN_DETAIL_PRINT(printf("check %d old weight %g, new %g\n", sequence, oldDevex, devex)); // update so won't print again weights_[sequence] = devex; } rowArray1->setNumElements(0); } // Initialize weights void AbcPrimalColumnSteepest::initializeWeights() { int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); int number = numberRows + numberColumns; int iSequence; if (mode_ != 1) { // initialize to 1.0 // and set reference framework if (!reference_) { int nWords = (number + 31) >> 5; reference_ = new unsigned int[nWords]; CoinZeroN(reference_, nWords); } for (iSequence = 0; iSequence < number; iSequence++) { weights_[iSequence] = 1.0; if (model_->getInternalStatus(iSequence) == AbcSimplex::basic) { setReference(iSequence, false); } else { setReference(iSequence, true); } } } else { CoinIndexedVector * temp = new CoinIndexedVector(); temp->reserve(numberRows + model_->factorization()->maximumPivots()); double * array = alternateWeights_->denseVector(); int * which = alternateWeights_->getIndices(); for (iSequence = 0; iSequence < number; iSequence++) { weights_[iSequence] = 1.0 + ADD_ONE; if (model_->getInternalStatus(iSequence) != AbcSimplex::basic && model_->getInternalStatus(iSequence) != AbcSimplex::isFixed) { model_->unpack(*alternateWeights_, iSequence); double value = ADD_ONE; model_->factorization()->updateColumn(*alternateWeights_); int number = alternateWeights_->getNumElements(); int j; for (j = 0; j < number; j++) { int iRow = which[j]; value += array[iRow] * array[iRow]; array[iRow] = 0.0; } alternateWeights_->setNumElements(0); weights_[iSequence] = value; } } delete temp; } } // Gets rid of all arrays void AbcPrimalColumnSteepest::clearArrays() { if (persistence_ == normal) { delete [] weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete [] savedWeights_; savedWeights_ = NULL; delete [] reference_; reference_ = NULL; } pivotSequence_ = -1; state_ = -1; savedPivotSequence_ = -1; savedSequenceOut_ = -1; devex_ = 0.0; } // Returns true if would not find any column bool AbcPrimalColumnSteepest::looksOptimal() const { if (looksOptimal_) return true; // user overrode //**** THIS MUST MATCH the action coding above double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (!model_->factorization()->pivots()) checkTolerance = 1.0e-6; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } int number = model_->numberRows() + model_->numberColumns(); int iSequence; double * reducedCost = model_->djRegion(); int numberInfeasible = 0; for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) numberInfeasible++; break; case AbcSimplex::atUpperBound: if (value > tolerance) numberInfeasible++; break; case AbcSimplex::atLowerBound: if (value < -tolerance) numberInfeasible++; } } return numberInfeasible == 0; } // Update djs doing partial pricing (dantzig) int AbcPrimalColumnSteepest::partialPricing(CoinIndexedVector * updates, int numberWanted, int numberLook) { int number = 0; int * index; double * updateBy; double * reducedCost; double saveTolerance = model_->currentDualTolerance(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (!model_->factorization()->pivots()) checkTolerance = 1.0e-6; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } if (model_->factorization()->pivots() && model_->numberPrimalInfeasibilities()) tolerance = CoinMax(tolerance, 1.0e-10 * model_->infeasibilityCost()); // So partial pricing can use model_->setCurrentDualTolerance(tolerance); model_->factorization()->updateColumnTranspose(*updates); int numberColumns = model_->numberColumns(); // Rows reducedCost = model_->djRegion(); number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); int j; double * duals = model_->dualRowSolution(); for (j = 0; j < number; j++) { int iSequence = index[j]; double value = duals[iSequence]; value -= updateBy[iSequence]; updateBy[iSequence] = 0.0; duals[iSequence] = value; } //#define CLP_DEBUG #ifdef CLP_DEBUG // check duals { //work space CoinIndexedVector arrayVector; arrayVector.reserve(numberRows + 1000); CoinIndexedVector workSpace; workSpace.reserve(numberRows + 1000); int iRow; double * array = arrayVector.denseVector(); int * index = arrayVector.getIndices(); int number = 0; int * pivotVariable = model_->pivotVariable(); double * cost = model_->costRegion(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = cost[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector.setNumElements(number); // Btran basic costs model_->factorization()->updateColumnTranspose(&workSpace, &arrayVector); // now look at dual solution for (iRow = 0; iRow < numberRows; iRow++) { // slack double value = array[iRow]; if (fabs(duals[iRow] - value) > 1.0e-3) printf("bad row %d old dual %g new %g\n", iRow, duals[iRow], value); //duals[iRow]=value; } } #endif #undef CLP_DEBUG double bestDj = tolerance; int bestSequence = -1; const double * cost = model_->costRegion(); model_->abcMatrix()->setOriginalWanted(numberWanted); model_->abcMatrix()->setCurrentWanted(numberWanted); int iPassR = 0, iPassC = 0; // Setup two passes // This biases towards picking row variables // This probably should be fixed int startR[4]; const int * which = infeasible_->getIndices(); int nSlacks = infeasible_->getNumElements(); startR[1] = nSlacks; startR[2] = 0; double randomR = model_->randomNumberGenerator()->randomDouble(); double dstart = static_cast (nSlacks) * randomR; startR[0] = static_cast (dstart); startR[3] = startR[0]; double startC[4]; startC[1] = 1.0; startC[2] = 0; double randomC = model_->randomNumberGenerator()->randomDouble(); startC[0] = randomC; startC[3] = randomC; reducedCost = model_->djRegion(); int sequenceOut = model_->sequenceOut(); int chunk = CoinMin(1024, (numberColumns + nSlacks) / 32); #ifdef COIN_DETAIL if (model_->numberIterations() % 1000 == 0 && model_->logLevel() > 1) { printf("%d wanted, nSlacks %d, chunk %d\n", numberWanted, nSlacks, chunk); int i; for (i = 0; i < 4; i++) printf("start R %d C %g ", startR[i], startC[i]); printf("\n"); } #endif chunk = CoinMax(chunk, 256); bool finishedR = false, finishedC = false; bool doingR = randomR > randomC; //doingR=false; int saveNumberWanted = numberWanted; while (!finishedR || !finishedC) { if (finishedR) doingR = false; if (doingR) { int saveSequence = bestSequence; int start = startR[iPassR]; int end = CoinMin(startR[iPassR+1], start + chunk / 2); int jSequence; for (jSequence = start; jSequence < end; jSequence++) { int iSequence = which[jSequence]; if (iSequence != sequenceOut) { double value; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: value = fabs(cost[iSequence] - duals[iSequence]); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case AbcSimplex::atUpperBound: value = cost[iSequence] - duals[iSequence]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case AbcSimplex::atLowerBound: value = -(cost[iSequence] - duals[iSequence]); if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } numberLook -= (end - start); if (numberLook < 0 && (10 * (saveNumberWanted - numberWanted) > saveNumberWanted)) numberWanted = 0; // give up if (saveSequence != bestSequence) { // dj reducedCost[bestSequence] = cost[bestSequence] - duals[bestSequence]; bestDj = fabs(reducedCost[bestSequence]); model_->abcMatrix()->setSavedBestSequence(bestSequence); model_->abcMatrix()->setSavedBestDj(reducedCost[bestSequence]); } model_->abcMatrix()->setCurrentWanted(numberWanted); if (!numberWanted) break; doingR = false; // update start startR[iPassR] = jSequence; if (jSequence >= startR[iPassR+1]) { if (iPassR) finishedR = true; else iPassR = 2; } } if (finishedC) doingR = true; if (!doingR) { // temp int saveSequence = bestSequence; // Columns double start = startC[iPassC]; // If we put this idea back then each function needs to update endFraction ** #if 0 double dchunk = (static_cast chunk) / (static_cast numberColumns); double end = CoinMin(startC[iPassC+1], start + dchunk);; #else double end = startC[iPassC+1]; // force end #endif model_->abcMatrix()->partialPricing(start, end, bestSequence, numberWanted); numberWanted = model_->abcMatrix()->currentWanted(); numberLook -= static_cast ((end - start) * numberColumns); if (numberLook < 0 && (10 * (saveNumberWanted - numberWanted) > saveNumberWanted)) numberWanted = 0; // give up if (bestSequence!=saveSequence) { // dj bestDj = fabs(reducedCost[bestSequence]); } if (!numberWanted) break; doingR = true; // update start startC[iPassC] = end; if (end >= startC[iPassC+1] - 1.0e-8) { if (iPassC) finishedC = true; else iPassC = 2; } } } updates->setNumElements(0); // Restore tolerance model_->setCurrentDualTolerance(saveTolerance); #ifndef NDEBUG if (bestSequence >= 0) { if (model_->getInternalStatus(bestSequence) == AbcSimplex::atLowerBound) assert(model_->reducedCost(bestSequence) < 0.0); if (model_->getInternalStatus(bestSequence) == AbcSimplex::atUpperBound) assert(model_->reducedCost(bestSequence) > 0.0); } #endif return bestSequence; } Clp-1.15.10/src/ClpPrimalQuadraticDantzig.hpp0000644000076600007660000000432111510657452017423 0ustar coincoin/* $Id: ClpPrimalQuadraticDantzig.hpp 1665 2011-01-04 17:55:54Z 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 ClpPrimalQuadraticDantzig_H #define ClpPrimalQuadraticDantzig_H #include "ClpPrimalColumnPivot.hpp" class ClpSimplexPrimalQuadratic; class ClpQuadraticInfo; //############################################################################# /** Primal Column Pivot Dantzig Algorithm Class This is simplest choice - choose largest infeasibility */ class ClpPrimalQuadraticDantzig : public ClpPrimalColumnPivot { public: ///@name Algorithmic methods //@{ /** Returns pivot column, -1 if none. Lumbers over all columns - slow updateArray has cost updates (also use pivotRow_ from last iteration) Can just do full price if you really want to be slow */ virtual int pivotColumn(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /// Just sets model virtual void saveWeights(ClpSimplex * model, int mode) { model_ = model; } //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpPrimalQuadraticDantzig(); /// Copy constructor ClpPrimalQuadraticDantzig(const ClpPrimalQuadraticDantzig &); /// Constructor from model ClpPrimalQuadraticDantzig(ClpSimplexPrimalQuadratic * model, ClpQuadraticInfo * info); /// Assignment operator ClpPrimalQuadraticDantzig & operator=(const ClpPrimalQuadraticDantzig& rhs); /// Destructor virtual ~ClpPrimalQuadraticDantzig (); /// Clone virtual ClpPrimalColumnPivot * clone(bool copyData = true) const; //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Pointer to info ClpQuadraticInfo * quadraticInfo_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyBase.cpp0000644000076600007660000051200112017705027015361 0ustar coincoin/* $Id: ClpCholeskyBase.cpp 1878 2012-08-30 15:43:19Z 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). /*----------------------------------------------------------------------------*/ /* Ordering code - courtesy of Anshul Gupta */ /* (C) Copyright IBM Corporation 1997, 2009. All Rights Reserved. */ /*----------------------------------------------------------------------------*/ /* A compact no-frills Approximate Minimum Local Fill ordering code. References: [1] Ordering Sparse Matrices Using Approximate Minimum Local Fill. Edward Rothberg, SGI Manuscript, April 1996. [2] An Approximate Minimum Degree Ordering Algorithm. T. Davis, P. Amestoy, and I. Duff, TR-94-039, CIS Department, University of Florida, December 1994. */ /*----------------------------------------------------------------------------*/ #include "CoinPragma.hpp" #include #include "ClpCholeskyBase.hpp" #include "ClpInterior.hpp" #include "ClpHelperFunctions.hpp" #include "CoinHelperFunctions.hpp" #include "CoinSort.hpp" #include "ClpCholeskyDense.hpp" #include "ClpMessage.hpp" #include "ClpQuadraticObjective.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyBase::ClpCholeskyBase (int denseThreshold) : type_(0), doKKT_(false), goDense_(0.7), choleskyCondition_(0.0), model_(NULL), numberTrials_(), numberRows_(0), status_(0), rowsDropped_(NULL), permuteInverse_(NULL), permute_(NULL), numberRowsDropped_(0), sparseFactor_(NULL), choleskyStart_(NULL), choleskyRow_(NULL), indexStart_(NULL), diagonal_(NULL), workDouble_(NULL), link_(NULL), workInteger_(NULL), clique_(NULL), sizeFactor_(0), sizeIndex_(0), firstDense_(0), rowCopy_(NULL), whichDense_(NULL), denseColumn_(NULL), dense_(NULL), denseThreshold_(denseThreshold) { memset(integerParameters_, 0, 64 * sizeof(int)); memset(doubleParameters_, 0, 64 * sizeof(double)); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyBase::ClpCholeskyBase (const ClpCholeskyBase & rhs) : type_(rhs.type_), doKKT_(rhs.doKKT_), goDense_(rhs.goDense_), choleskyCondition_(rhs.choleskyCondition_), model_(rhs.model_), numberTrials_(rhs.numberTrials_), numberRows_(rhs.numberRows_), status_(rhs.status_), numberRowsDropped_(rhs.numberRowsDropped_) { rowsDropped_ = ClpCopyOfArray(rhs.rowsDropped_, numberRows_); permuteInverse_ = ClpCopyOfArray(rhs.permuteInverse_, numberRows_); permute_ = ClpCopyOfArray(rhs.permute_, numberRows_); sizeFactor_ = rhs.sizeFactor_; sizeIndex_ = rhs.sizeIndex_; firstDense_ = rhs.firstDense_; sparseFactor_ = ClpCopyOfArray(rhs.sparseFactor_, rhs.sizeFactor_); choleskyStart_ = ClpCopyOfArray(rhs.choleskyStart_, numberRows_ + 1); indexStart_ = ClpCopyOfArray(rhs.indexStart_, numberRows_); choleskyRow_ = ClpCopyOfArray(rhs.choleskyRow_, sizeIndex_); diagonal_ = ClpCopyOfArray(rhs.diagonal_, numberRows_); #if CLP_LONG_CHOLESKY!=1 workDouble_ = ClpCopyOfArray(rhs.workDouble_, numberRows_); #else // actually long double workDouble_ = reinterpret_cast (ClpCopyOfArray(reinterpret_cast (rhs.workDouble_), numberRows_)); #endif link_ = ClpCopyOfArray(rhs.link_, numberRows_); workInteger_ = ClpCopyOfArray(rhs.workInteger_, numberRows_); clique_ = ClpCopyOfArray(rhs.clique_, numberRows_); CoinMemcpyN(rhs.integerParameters_, 64, integerParameters_); CoinMemcpyN(rhs.doubleParameters_, 64, doubleParameters_); rowCopy_ = rhs.rowCopy_->clone(); whichDense_ = NULL; denseColumn_ = NULL; dense_ = NULL; denseThreshold_ = rhs.denseThreshold_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyBase::~ClpCholeskyBase () { delete [] rowsDropped_; delete [] permuteInverse_; delete [] permute_; delete [] sparseFactor_; delete [] choleskyStart_; delete [] choleskyRow_; delete [] indexStart_; delete [] diagonal_; delete [] workDouble_; delete [] link_; delete [] workInteger_; delete [] clique_; delete rowCopy_; delete [] whichDense_; delete [] denseColumn_; delete dense_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyBase & ClpCholeskyBase::operator=(const ClpCholeskyBase& rhs) { if (this != &rhs) { type_ = rhs.type_; doKKT_ = rhs.doKKT_; goDense_ = rhs.goDense_; choleskyCondition_ = rhs.choleskyCondition_; model_ = rhs.model_; numberTrials_ = rhs.numberTrials_; numberRows_ = rhs.numberRows_; status_ = rhs.status_; numberRowsDropped_ = rhs.numberRowsDropped_; delete [] rowsDropped_; delete [] permuteInverse_; delete [] permute_; delete [] sparseFactor_; delete [] choleskyStart_; delete [] choleskyRow_; delete [] indexStart_; delete [] diagonal_; delete [] workDouble_; delete [] link_; delete [] workInteger_; delete [] clique_; delete rowCopy_; delete [] whichDense_; delete [] denseColumn_; delete dense_; rowsDropped_ = ClpCopyOfArray(rhs.rowsDropped_, numberRows_); permuteInverse_ = ClpCopyOfArray(rhs.permuteInverse_, numberRows_); permute_ = ClpCopyOfArray(rhs.permute_, numberRows_); sizeFactor_ = rhs.sizeFactor_; sizeIndex_ = rhs.sizeIndex_; firstDense_ = rhs.firstDense_; sparseFactor_ = ClpCopyOfArray(rhs.sparseFactor_, rhs.sizeFactor_); choleskyStart_ = ClpCopyOfArray(rhs.choleskyStart_, numberRows_ + 1); choleskyRow_ = ClpCopyOfArray(rhs.choleskyRow_, rhs.sizeFactor_); indexStart_ = ClpCopyOfArray(rhs.indexStart_, numberRows_); choleskyRow_ = ClpCopyOfArray(rhs.choleskyRow_, sizeIndex_); diagonal_ = ClpCopyOfArray(rhs.diagonal_, numberRows_); #if CLP_LONG_CHOLESKY!=1 workDouble_ = ClpCopyOfArray(rhs.workDouble_, numberRows_); #else // actually long double workDouble_ = reinterpret_cast (ClpCopyOfArray(reinterpret_cast (rhs.workDouble_), numberRows_)); #endif link_ = ClpCopyOfArray(rhs.link_, numberRows_); workInteger_ = ClpCopyOfArray(rhs.workInteger_, numberRows_); clique_ = ClpCopyOfArray(rhs.clique_, numberRows_); delete rowCopy_; rowCopy_ = rhs.rowCopy_->clone(); whichDense_ = NULL; denseColumn_ = NULL; dense_ = NULL; denseThreshold_ = rhs.denseThreshold_; } return *this; } // reset numberRowsDropped and rowsDropped. void ClpCholeskyBase::resetRowsDropped() { numberRowsDropped_ = 0; memset(rowsDropped_, 0, numberRows_); } /* Uses factorization to solve. - given as if KKT. region1 is rows+columns, region2 is rows */ void ClpCholeskyBase::solveKKT (CoinWorkDouble * region1, CoinWorkDouble * region2, const CoinWorkDouble * diagonal, CoinWorkDouble diagonalScaleFactor) { if (!doKKT_) { int iColumn; int numberColumns = model_->numberColumns(); int numberTotal = numberRows_ + numberColumns; CoinWorkDouble * region1Save = new CoinWorkDouble[numberTotal]; for (iColumn = 0; iColumn < numberTotal; iColumn++) { region1[iColumn] *= diagonal[iColumn]; region1Save[iColumn] = region1[iColumn]; } multiplyAdd(region1 + numberColumns, numberRows_, -1.0, region2, 1.0); model_->clpMatrix()->times(1.0, region1, region2); CoinWorkDouble maximumRHS = maximumAbsElement(region2, numberRows_); CoinWorkDouble scale = 1.0; CoinWorkDouble unscale = 1.0; if (maximumRHS > 1.0e-30) { if (maximumRHS <= 0.5) { CoinWorkDouble factor = 2.0; while (maximumRHS <= 0.5) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } else if (maximumRHS >= 2.0 && maximumRHS <= COIN_DBL_MAX) { CoinWorkDouble factor = 0.5; while (maximumRHS >= 2.0) { maximumRHS *= factor; scale *= factor; } /* endwhile */ } unscale = diagonalScaleFactor / scale; } else { //effectively zero scale = 0.0; unscale = 0.0; } multiplyAdd(NULL, numberRows_, 0.0, region2, scale); solve(region2); multiplyAdd(NULL, numberRows_, 0.0, region2, unscale); multiplyAdd(region2, numberRows_, -1.0, region1 + numberColumns, 0.0); CoinZeroN(region1, numberColumns); model_->clpMatrix()->transposeTimes(1.0, region2, region1); for (iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = region1[iColumn] * diagonal[iColumn] - region1Save[iColumn]; delete [] region1Save; } else { // KKT int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; CoinWorkDouble * array = new CoinWorkDouble [numberRows_]; CoinMemcpyN(region1, numberTotal, array); CoinMemcpyN(region2, numberRowsModel, array + numberTotal); assert (numberRows_ >= numberRowsModel + numberTotal); solve(array); int iRow; for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped_[iRow] && CoinAbs(array[iRow]) > 1.0e-8) { COIN_DETAIL_PRINT(printf("row region1 %d dropped %g\n", iRow, array[iRow])); } } for (; iRow < numberRows_; iRow++) { if (rowsDropped_[iRow] && CoinAbs(array[iRow]) > 1.0e-8) { COIN_DETAIL_PRINT(printf("row region2 %d dropped %g\n", iRow, array[iRow])); } } CoinMemcpyN(array + numberTotal, numberRowsModel, region2); CoinMemcpyN(array, numberTotal, region1); delete [] array; } } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyBase::clone() const { return new ClpCholeskyBase(*this); } // Forms ADAT - returns nonzero if not enough memory int ClpCholeskyBase::preOrder(bool lowerTriangular, bool includeDiagonal, bool doKKT) { delete rowCopy_; rowCopy_ = model_->clpMatrix()->reverseOrderedCopy(); if (!doKKT) { numberRows_ = model_->numberRows(); rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; // Space for starts choleskyStart_ = new CoinBigIndex[numberRows_+1]; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; int numberColumns = model_->numberColumns(); int numberDense = 0; //denseThreshold_=3; if (denseThreshold_ > 0) { delete [] whichDense_; delete [] denseColumn_; delete dense_; whichDense_ = new char[numberColumns]; int iColumn; used[numberRows_] = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; used[length] += 1; } int nLong = 0; int stop = CoinMax(denseThreshold_ / 2, 100); for (iRow = numberRows_; iRow >= stop; iRow--) { if (used[iRow]) COIN_DETAIL_PRINT(printf("%d columns are of length %d\n", used[iRow], iRow)); nLong += used[iRow]; if (nLong > 50 || nLong > (numberColumns >> 2)) break; } CoinZeroN(used, numberRows_); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLength[iColumn] < denseThreshold_) { whichDense_[iColumn] = 0; } else { whichDense_[iColumn] = 1; numberDense++; } } if (!numberDense || numberDense > 100) { // free delete [] whichDense_; whichDense_ = NULL; denseColumn_ = NULL; dense_ = NULL; } else { // space for dense columns denseColumn_ = new longDouble [numberDense*numberRows_]; // dense cholesky dense_ = new ClpCholeskyDense(); dense_->reserveSpace(NULL, numberDense); COIN_DETAIL_PRINT(printf("Taking %d columns as dense\n", numberDense)); } } int offset = includeDiagonal ? 0 : 1; if (lowerTriangular) offset = -offset; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 0; // make sure diagonal exists if includeDiagonal if (!offset) { which[0] = iRow; used[iRow] = 1; number = 1; } CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; if (lowerTriangular) { for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow <= iRow + offset) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } } else { for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow + offset) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } delete [] which; // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 0; // make sure diagonal exists if includeDiagonal if (!offset) { which[0] = iRow; used[iRow] = 1; number = 1; } choleskyStart_[iRow] = sizeFactor_; CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; if (lowerTriangular) { for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow <= iRow + offset) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } } else { for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow + offset) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; return 0; } else { int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; numberRows_ = 2 * numberRowsModel + numberColumns; rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); int numberElements = model_->clpMatrix()->getNumElements(); numberElements = numberElements + 2 * numberRowsModel + numberTotal; if (quadratic) numberElements += quadratic->getNumElements(); // Space for starts choleskyStart_ = new CoinBigIndex[numberRows_+1]; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); //const double * element = model_->clpMatrix()->getElements(); // Now we have size - create arrays and fill in try { choleskyRow_ = new int [numberElements]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } int iRow, iColumn; sizeFactor_ = 0; // matrix if (lowerTriangular) { if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; choleskyRow_[sizeFactor_++] = iColumn; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; if (!includeDiagonal) start++; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[sizeFactor_++] = row[j] + numberTotal; } } } else { // Quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); //const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; if (includeDiagonal) choleskyRow_[sizeFactor_++] = iColumn; CoinBigIndex j; for ( j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) choleskyRow_[sizeFactor_++] = jColumn; } CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for ( j = start; j < end; j++) { choleskyRow_[sizeFactor_++] = row[j] + numberTotal; } } } // slacks for (; iColumn < numberTotal; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; if (includeDiagonal) choleskyRow_[sizeFactor_++] = iColumn; choleskyRow_[sizeFactor_++] = iColumn - numberColumns + numberTotal; } // Transpose - nonzero diagonal (may regularize) for (iRow = 0; iRow < numberRowsModel; iRow++) { choleskyStart_[iRow+numberTotal] = sizeFactor_; // diagonal if (includeDiagonal) choleskyRow_[sizeFactor_++] = iRow + numberTotal; } choleskyStart_[numberRows_] = sizeFactor_; } else { // transpose ClpMatrixBase * rowCopy = model_->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const int * column = rowCopy->getIndices(); if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; if (includeDiagonal) choleskyRow_[sizeFactor_++] = iColumn; } } else { // Quadratic // transpose CoinPackedMatrix quadraticT; quadraticT.reverseOrderedCopyOf(*quadratic); const int * columnQuadratic = quadraticT.getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticT.getVectorStarts(); const int * columnQuadraticLength = quadraticT.getVectorLengths(); //const double * quadraticElement = quadraticT.getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { choleskyStart_[iColumn] = sizeFactor_; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn < iColumn) choleskyRow_[sizeFactor_++] = jColumn; } if (includeDiagonal) choleskyRow_[sizeFactor_++] = iColumn; } } int iRow; // slacks for (iRow = 0; iRow < numberRowsModel; iRow++) { choleskyStart_[iRow+numberColumns] = sizeFactor_; if (includeDiagonal) choleskyRow_[sizeFactor_++] = iRow + numberColumns; } for (iRow = 0; iRow < numberRowsModel; iRow++) { choleskyStart_[iRow+numberTotal] = sizeFactor_; CoinBigIndex start = rowStart[iRow]; CoinBigIndex end = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex j = start; j < end; j++) { choleskyRow_[sizeFactor_++] = column[j]; } // slack choleskyRow_[sizeFactor_++] = numberColumns + iRow; if (includeDiagonal) choleskyRow_[sizeFactor_++] = iRow + numberTotal; } choleskyStart_[numberRows_] = sizeFactor_; } } return 0; } /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyBase::order(ClpInterior * model) { model_ = model; #define BASE_ORDER 2 #if BASE_ORDER>0 if (!doKKT_ && model_->numberRows() > 6) { if (preOrder(false, true, false)) return -1; //rowsDropped_ = new char [numberRows_]; numberRowsDropped_ = 0; memset(rowsDropped_, 0, numberRows_); //rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); // approximate minimum degree return orderAMD(); } #endif int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); if (!doKKT_) { numberRows_ = model->numberRows(); } else { numberRows_ = 2 * numberRowsModel + numberColumns; } rowsDropped_ = new char [numberRows_]; numberRowsDropped_ = 0; memset(rowsDropped_, 0, numberRows_); rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; int * count = new int[numberRows_]; CoinZeroN(count, numberRows_); CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; permute_ = new int[numberRows_]; for (iRow = 0; iRow < numberRows_; iRow++) permute_[iRow] = iRow; if (!doKKT_) { int numberDense = 0; if (denseThreshold_ > 0) { delete [] whichDense_; delete [] denseColumn_; delete dense_; whichDense_ = new char[numberColumns]; int iColumn; used[numberRows_] = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; used[length] += 1; } int nLong = 0; int stop = CoinMax(denseThreshold_ / 2, 100); for (iRow = numberRows_; iRow >= stop; iRow--) { if (used[iRow]) COIN_DETAIL_PRINT(printf("%d columns are of length %d\n", used[iRow], iRow)); nLong += used[iRow]; if (nLong > 50 || nLong > (numberColumns >> 2)) break; } CoinZeroN(used, numberRows_); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLength[iColumn] < denseThreshold_) { whichDense_[iColumn] = 0; } else { whichDense_[iColumn] = 1; numberDense++; } } if (!numberDense || numberDense > 100) { // free delete [] whichDense_; whichDense_ = NULL; denseColumn_ = NULL; dense_ = NULL; } else { // space for dense columns denseColumn_ = new longDouble [numberDense*numberRows_]; // dense cholesky dense_ = new ClpCholeskyDense(); dense_->reserveSpace(NULL, numberDense); COIN_DETAIL_PRINT(printf("Taking %d columns as dense\n", numberDense)); } } /* Get row counts and size */ for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow < iRow) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; count[jRow]++; } } } } } sizeFactor_ += number; count[iRow] += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } CoinSort_2(count, count + numberRows_, permute_); } else { // KKT int numberElements = model_->clpMatrix()->getNumElements(); numberElements = numberElements + 2 * numberRowsModel + numberTotal; if (quadratic) numberElements += quadratic->getNumElements(); // off diagonal numberElements -= numberRows_; sizeFactor_ = numberElements; // If we sort we need to redo symbolic etc } delete [] which; delete [] used; delete [] count; permuteInverse_ = new int [numberRows_]; for (iRow = 0; iRow < numberRows_; iRow++) { //permute_[iRow]=iRow; // force no permute //permute_[iRow]=numberRows_-1-iRow; // force odd permute //permute_[iRow]=(iRow+1)%numberRows_; // force odd permute permuteInverse_[permute_[iRow]] = iRow; } return 0; } #if BASE_ORDER==1 /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyBase::orderAMD() { permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; // Do ordering int returnCode = 0; // get more space and full matrix int space = 6 * sizeFactor_ + 100000; int * temp = new int [space]; int * which = new int[2*numberRows_]; CoinBigIndex * tempStart = new CoinBigIndex [numberRows_+1]; memset(which, 0, numberRows_ * sizeof(int)); for (int iRow = 0; iRow < numberRows_; iRow++) { which[iRow] += choleskyStart_[iRow+1] - choleskyStart_[iRow] - 1; for (CoinBigIndex j = choleskyStart_[iRow] + 1; j < choleskyStart_[iRow+1]; j++) { int jRow = choleskyRow_[j]; which[jRow]++; } } CoinBigIndex sizeFactor = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { int length = which[iRow]; permute_[iRow] = length; tempStart[iRow] = sizeFactor; which[iRow] = sizeFactor; sizeFactor += length; } for (int iRow = 0; iRow < numberRows_; iRow++) { assert (choleskyRow_[choleskyStart_[iRow]] == iRow); for (CoinBigIndex j = choleskyStart_[iRow] + 1; j < choleskyStart_[iRow+1]; j++) { int jRow = choleskyRow_[j]; int put = which[iRow]; temp[put] = jRow; which[iRow]++; put = which[jRow]; temp[put] = iRow; which[jRow]++; } } for (int iRow = 1; iRow < numberRows_; iRow++) assert (which[iRow-1] == tempStart[iRow]); CoinBigIndex lastSpace = sizeFactor; delete [] choleskyRow_; choleskyRow_ = temp; delete [] choleskyStart_; choleskyStart_ = tempStart; // linked lists of sizes and lengths int * first = new int [numberRows_]; int * next = new int [numberRows_]; int * previous = new int [numberRows_]; char * mark = new char[numberRows_]; memset(mark, 0, numberRows_); CoinBigIndex * sort = new CoinBigIndex [numberRows_]; int * order = new int [numberRows_]; for (int iRow = 0; iRow < numberRows_; iRow++) { first[iRow] = -1; next[iRow] = -1; previous[iRow] = -1; permuteInverse_[iRow] = -1; } int large = 1000 + 2 * numberRows_; for (int iRow = 0; iRow < numberRows_; iRow++) { int n = permute_[iRow]; if (first[n] < 0) { first[n] = iRow; previous[iRow] = n + large; next[iRow] = n + 2 * large; } else { int k = first[n]; assert (k < numberRows_); first[n] = iRow; previous[iRow] = n + large; assert (previous[k] == n + large); next[iRow] = k; previous[k] = iRow; } } int smallest = 0; int done = 0; int numberCompressions = 0; int numberExpansions = 0; while (smallest < numberRows_) { if (first[smallest] < 0 || first[smallest] > numberRows_) { smallest++; continue; } int iRow = first[smallest]; if (false) { int kRow = -1; int ss = 999999; for (int jRow = numberRows_ - 1; jRow >= 0; jRow--) { if (permuteInverse_[jRow] < 0) { int length = permute_[jRow]; assert (length > 0); for (CoinBigIndex j = choleskyStart_[jRow]; j < choleskyStart_[jRow] + length; j++) { int jjRow = choleskyRow_[j]; assert (permuteInverse_[jjRow] < 0); } if (length < ss) { ss = length; kRow = jRow; } } } assert (smallest == ss); printf("list chose %d - full chose %d - length %d\n", iRow, kRow, ss); } int kNext = next[iRow]; first[smallest] = kNext; if (kNext < numberRows_) previous[kNext] = previous[iRow]; previous[iRow] = -1; next[iRow] = -1; permuteInverse_[iRow] = done; done++; // Now add edges CoinBigIndex start = choleskyStart_[iRow]; CoinBigIndex end = choleskyStart_[iRow] + permute_[iRow]; int nSave = 0; for (CoinBigIndex k = start; k < end; k++) { int kRow = choleskyRow_[k]; assert (permuteInverse_[kRow] < 0); //if (permuteInverse_[kRow]<0) which[nSave++] = kRow; } for (int i = 0; i < nSave; i++) { int kRow = which[i]; int length = permute_[kRow]; CoinBigIndex start = choleskyStart_[kRow]; CoinBigIndex end = choleskyStart_[kRow] + length; for (CoinBigIndex j = start; j < end; j++) { int jRow = choleskyRow_[j]; mark[jRow] = 1; } mark[kRow] = 1; int n = nSave; for (int j = 0; j < nSave; j++) { int jRow = which[j]; if (!mark[jRow]) { which[n++] = jRow; } } for (CoinBigIndex j = start; j < end; j++) { int jRow = choleskyRow_[j]; mark[jRow] = 0; } mark[kRow] = 0; if (n > nSave) { bool inPlace = (n - nSave == 1); if (!inPlace) { // extend int length = n - nSave + end - start; if (length + lastSpace > space) { // need to compress numberCompressions++; int newN = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { CoinBigIndex start = choleskyStart_[iRow]; if (permuteInverse_[iRow] < 0) { sort[newN] = start; order[newN++] = iRow; } else { choleskyStart_[iRow] = -1; permute_[iRow] = 0; } } CoinSort_2(sort, sort + newN, order); sizeFactor = 0; for (int k = 0; k < newN; k++) { int iRow = order[k]; int length = permute_[iRow]; CoinBigIndex start = choleskyStart_[iRow]; choleskyStart_[iRow] = sizeFactor; for (int j = 0; j < length; j++) choleskyRow_[sizeFactor+j] = choleskyRow_[start+j]; sizeFactor += length; } lastSpace = sizeFactor; if ((sizeFactor + numberRows_ + 1000) * 4 > 3 * space) { // need to expand numberExpansions++; space = (3 * space) / 2; int * temp = new int [space]; memcpy(temp, choleskyRow_, sizeFactor * sizeof(int)); delete [] choleskyRow_; choleskyRow_ = temp; } } } // Now add start = choleskyStart_[kRow]; end = choleskyStart_[kRow] + permute_[kRow]; if (!inPlace) choleskyStart_[kRow] = lastSpace; CoinBigIndex put = choleskyStart_[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = choleskyRow_[j]; if (permuteInverse_[jRow] < 0) choleskyRow_[put++] = jRow; } for (int j = nSave; j < n; j++) { int jRow = which[j]; choleskyRow_[put++] = jRow; } if (!inPlace) { permute_[kRow] = put - lastSpace; lastSpace = put; } else { permute_[kRow] = put - choleskyStart_[kRow]; } } else { // pack down for new counts CoinBigIndex put = start; for (CoinBigIndex j = start; j < end; j++) { int jRow = choleskyRow_[j]; if (permuteInverse_[jRow] < 0) choleskyRow_[put++] = jRow; } permute_[kRow] = put - start; } // take out int iNext = next[kRow]; int iPrevious = previous[kRow]; if (iPrevious < numberRows_) { next[iPrevious] = iNext; } else { assert (iPrevious == length + large); first[length] = iNext; } if (iNext < numberRows_) { previous[iNext] = iPrevious; } else { assert (iNext == length + 2 * large); } // put in length = permute_[kRow]; smallest = CoinMin(smallest, length); if (first[length] < 0 || first[length] > numberRows_) { first[length] = kRow; previous[kRow] = length + large; next[kRow] = length + 2 * large; } else { int k = first[length]; assert (k < numberRows_); first[length] = kRow; previous[kRow] = length + large; assert (previous[k] == length + large); next[kRow] = k; previous[k] = kRow; } } } // do rest for (int iRow = 0; iRow < numberRows_; iRow++) { if (permuteInverse_[iRow] < 0) permuteInverse_[iRow] = done++; } COIN_DETAIL_PRINT(printf("%d compressions, %d expansions\n", numberCompressions, numberExpansions)); assert (done == numberRows_); delete [] sort; delete [] order; delete [] which; delete [] mark; delete [] first; delete [] next; delete [] previous; delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; #ifndef NDEBUG for (int iRow = 0; iRow < numberRows_; iRow++) { permute_[iRow] = -1; } #endif for (int iRow = 0; iRow < numberRows_; iRow++) { permute_[permuteInverse_[iRow]] = iRow; } #ifndef NDEBUG for (int iRow = 0; iRow < numberRows_; iRow++) { assert(permute_[iRow] >= 0 && permute_[iRow] < numberRows_); } #endif return returnCode; } #elif BASE_ORDER==2 /*----------------------------------------------------------------------------*/ /* (C) Copyright IBM Corporation 1997, 2009. All Rights Reserved. */ /*----------------------------------------------------------------------------*/ /* A compact no-frills Approximate Minimum Local Fill ordering code. References: [1] Ordering Sparse Matrices Using Approximate Minimum Local Fill. Edward Rothberg, SGI Manuscript, April 1996. [2] An Approximate Minimum Degree Ordering Algorithm. T. Davis, P. Amestoy, and I. Duff, TR-94-039, CIS Department, University of Florida, December 1994. */ #include #include typedef int WSI; #define NORDTHRESH 7 #define MAXIW 2147000000 //#define WSSMP_DBG #ifdef WSSMP_DBG static void chk (WSI ind, WSI i, WSI lim) { if (i <= 0 || i > lim) { printf("%d: chk: myamlf: WAR**: i, lim = %d, %d\n", ind, i, lim); } } #endif static void myamlf(WSI n, WSI xadj[], WSI adjncy[], WSI dgree[], WSI varbl[], WSI snxt[], WSI perm[], WSI invp[], WSI head[], WSI lsize[], WSI flag[], WSI erscore[], WSI locaux, WSI adjln, WSI speed) { WSI l, i, j, k; double x, y; WSI maxmum, fltag, nodeg, scln, nm1, deg, tn, locatns, ipp, jpp, nnode, numpiv, node, nodeln, currloc, counter, numii, mindeg, i0, i1, i2, i4, i5, i6, i7, i9, j0, j1, j2, j3, j4, j5, j6, j7, j8, j9; /* n cannot be less than NORDTHRESH if (n < 3) { if (n > 0) perm[0] = invp[0] = 1; if (n > 1) perm[1] = invp[1] = 2; return; } */ #ifdef WSSMP_DBG printf("Myamlf: n, locaux, adjln, speed = %d,%d,%d,%d\n", n, locaux, adjln, speed); for (i = 0; i < n; i++) flag[i] = 0; k = xadj[0]; for (i = 1; i <= n; i++) { j = k + dgree[i-1]; if (j < k || k < 1) printf("ERR**: myamlf: i, j, k = %d,%d,%d\n", i, j, k); for (l = k; l < j; l++) { if (adjncy[l - 1] < 1 || adjncy[l - 1] > n || adjncy[l - 1] == i) printf("ERR**: myamlf: i, l, adjj[l] = %d,%d,%d\n", i, l, adjncy[l - 1]); if (flag[adjncy[l - 1] - 1] == i) printf("ERR**: myamlf: duplicate entry: %d - %d\n", i, adjncy[l - 1]); flag[adjncy[l - 1] - 1] = i; nm1 = adjncy[l - 1] - 1; for (fltag = xadj[nm1]; fltag < xadj[nm1] + dgree[nm1]; fltag++) { if (adjncy[fltag - 1] == i) goto L100; } printf("ERR**: Unsymmetric %d %d\n", i, fltag); L100: ; } k = j; if (k > locaux) printf("ERR**: i, j, k, locaux = %d, %d, %d, %d\n", i, j, k, locaux); } if (n*(n - 1) < locaux - 1) printf("ERR**: myamlf: too many nnz, n, ne = %d, %d\n", n, adjln); for (i = 0; i < n; i++) flag[i] = 1; if (n > 10000) printf ("Finished error checking in AMF\n"); for (i = locaux; i <= adjln; i++) adjncy[i - 1] = -22; #endif maxmum = 0; mindeg = 1; fltag = 2; locatns = locaux - 1; nm1 = n - 1; counter = 1; for (l = 0; l < n; l++) { j = erscore[l]; #ifdef WSSMP_DBG chk(1, j, n); #endif if (j > 0) { nnode = head[j - 1]; if (nnode) perm[nnode - 1] = l + 1; snxt[l] = nnode; head[j - 1] = l + 1; } else { invp[l] = -(counter++); flag[l] = xadj[l] = 0; } } while (counter <= n) { for (deg = mindeg; head[deg - 1] < 1; deg++) {}; nodeg = 0; #ifdef WSSMP_DBG chk(2, deg, n - 1); #endif node = head[deg - 1]; #ifdef WSSMP_DBG chk(3, node, n); #endif mindeg = deg; nnode = snxt[node - 1]; if (nnode) perm[nnode - 1] = 0; head[deg - 1] = nnode; nodeln = invp[node - 1]; numpiv = varbl[node - 1]; invp[node - 1] = -counter; counter += numpiv; varbl[node - 1] = -numpiv; if (nodeln) { j4 = locaux; i5 = lsize[node - 1] - nodeln; i2 = nodeln + 1; l = xadj[node - 1]; for (i6 = 1; i6 <= i2; ++i6) { if (i6 == i2) { tn = node, i0 = l, scln = i5; } else { #ifdef WSSMP_DBG chk(4, l, adjln); #endif tn = adjncy[l-1]; l++; #ifdef WSSMP_DBG chk(5, tn, n); #endif i0 = xadj[tn - 1]; scln = lsize[tn - 1]; } for (i7 = 1; i7 <= scln; ++i7) { #ifdef WSSMP_DBG chk(6, i0, adjln); #endif i = adjncy[i0 - 1]; i0++; #ifdef WSSMP_DBG chk(7, i, n); #endif numii = varbl[i - 1]; if (numii > 0) { if (locaux > adjln) { lsize[node - 1] -= i6; xadj[node - 1] = l; if (!lsize[node - 1]) xadj[node - 1] = 0; xadj[tn - 1] = i0; lsize[tn - 1] = scln - i7; if (!lsize[tn - 1]) xadj[tn - 1] = 0; for (j = 1; j <= n; j++) { i4 = xadj[j - 1]; if (i4 > 0) { xadj[j - 1] = adjncy[i4 - 1]; #ifdef WSSMP_DBG chk(8, i4, adjln); #endif adjncy[i4 - 1] = -j; } } i9 = j4 - 1; j6 = j7 = 1; while (j6 <= i9) { #ifdef WSSMP_DBG chk(9, j6, adjln); #endif j = -adjncy[j6 - 1]; j6++; if (j > 0) { #ifdef WSSMP_DBG chk(10, j7, adjln); chk(11, j, n); #endif adjncy[j7 - 1] = xadj[j - 1]; xadj[j - 1] = j7++; j8 = lsize[j - 1] - 1 + j7; for (; j7 < j8; j7++, j6++) adjncy[j7-1] = adjncy[j6-1]; } } for (j0 = j7; j4 < locaux; j4++, j7++) { #ifdef WSSMP_DBG chk(12, j4, adjln); #endif adjncy[j7 - 1] = adjncy[j4 - 1]; } j4 = j0; locaux = j7; i0 = xadj[tn - 1]; l = xadj[node - 1]; } adjncy[locaux-1] = i; locaux++; varbl[i - 1] = -numii; nodeg += numii; ipp = perm[i - 1]; nnode = snxt[i - 1]; #ifdef WSSMP_DBG if (ipp) chk(13, ipp, n); if (nnode) chk(14, nnode, n); #endif if (ipp) snxt[ipp - 1] = nnode; else head[erscore[i - 1] - 1] = nnode; if (nnode) perm[nnode - 1] = ipp; } } if (tn != node) { flag[tn - 1] = 0, xadj[tn - 1] = -node; } } currloc = (j5 = locaux) - j4; locatns += currloc; } else { i1 = (j4 = xadj[node - 1]) + lsize[node - 1]; for (j = j5 = j4; j < i1; j++) { #ifdef WSSMP_DBG chk(15, j, adjln); #endif i = adjncy[j - 1]; #ifdef WSSMP_DBG chk(16, i, n); #endif numii = varbl[i - 1]; if (numii > 0) { nodeg += numii; varbl[i - 1] = -numii; #ifdef WSSMP_DBG chk(17, j5, adjln); #endif adjncy[j5-1] = i; ipp = perm[i - 1]; nnode = snxt[i - 1]; j5++; #ifdef WSSMP_DBG if (ipp) chk(18, ipp, n); if (nnode) chk(19, nnode, n); #endif if (ipp) snxt[ipp - 1] = nnode; else head[erscore[i - 1] - 1] = nnode; if (nnode) perm[nnode - 1] = ipp; } } currloc = 0; } #ifdef WSSMP_DBG chk(20, node, n); #endif lsize[node - 1] = j5 - (xadj[node - 1] = j4); dgree[node - 1] = nodeg; if (fltag + n < 0 || fltag + n > MAXIW) { for (i = 1; i <= n; i++) if (flag[i - 1]) flag[i - 1] = 1; fltag = 2; } for (j3 = j4; j3 < j5; j3++) { #ifdef WSSMP_DBG chk(21, j3, adjln); #endif i = adjncy[j3 - 1]; #ifdef WSSMP_DBG chk(22, i, n); #endif j = invp[i - 1]; if (j > 0) { i4 = fltag - (numii = -varbl[i - 1]); i2 = xadj[i - 1] + j; for (l = xadj[i - 1]; l < i2; l++) { #ifdef WSSMP_DBG chk(23, l, adjln); #endif tn = adjncy[l - 1]; #ifdef WSSMP_DBG chk(24, tn, n); #endif j9 = flag[tn - 1]; if (j9 >= fltag) j9 -= numii; else if (j9) j9 = dgree[tn - 1] + i4; flag[tn - 1] = j9; } } } for (j3 = j4; j3 < j5; j3++) { #ifdef WSSMP_DBG chk(25, j3, adjln); #endif i = adjncy[j3 - 1]; i5 = deg = 0; #ifdef WSSMP_DBG chk(26, i, n); #endif j1 = (i4 = xadj[i - 1]) + invp[i - 1]; for (l = j0 = i4; l < j1; l++) { #ifdef WSSMP_DBG chk(27, l, adjln); #endif tn = adjncy[l - 1]; #ifdef WSSMP_DBG chk(70, tn, n); #endif j8 = flag[tn - 1]; if (j8) { deg += (j8 - fltag); #ifdef WSSMP_DBG chk(28, i4, adjln); #endif adjncy[i4-1] = tn; i5 += tn; i4++; while (i5 >= nm1) i5 -= nm1; } } invp[i - 1] = (j2 = i4) - j0 + 1; i2 = j0 + lsize[i - 1]; for (l = j1; l < i2; l++) { #ifdef WSSMP_DBG chk(29, l, adjln); #endif j = adjncy[l - 1]; #ifdef WSSMP_DBG chk(30, j, n); #endif numii = varbl[j - 1]; if (numii > 0) { deg += numii; #ifdef WSSMP_DBG chk(31, i4, adjln); #endif adjncy[i4-1] = j; i5 += j; i4++; while (i5 >= nm1) i5 -= nm1; } } if (invp[i - 1] == 1 && j2 == i4) { numii = -varbl[i - 1]; xadj[i - 1] = -node; nodeg -= numii; counter += numii; numpiv += numii; invp[i - 1] = varbl[i - 1] = 0; } else { if (dgree[i - 1] > deg) dgree[i - 1] = deg; #ifdef WSSMP_DBG chk(32, j2, adjln); chk(33, j0, adjln); #endif adjncy[i4 - 1] = adjncy[j2 - 1]; adjncy[j2 - 1] = adjncy[j0 - 1]; adjncy[j0 - 1] = node; lsize[i - 1] = i4 - j0 + 1; i5++; #ifdef WSSMP_DBG chk(35, i5, n); #endif j = head[i5 - 1]; if (j > 0) { snxt[i - 1] = perm[j - 1]; perm[j - 1] = i; } else { snxt[i - 1] = -j; head[i5 - 1] = -i; } perm[i - 1] = i5; } } #ifdef WSSMP_DBG chk(36, node, n); #endif dgree[node - 1] = nodeg; if (maxmum < nodeg) maxmum = nodeg; fltag += maxmum; #ifdef WSSMP_DBG if (fltag + n + 1 < 0) printf("ERR**: fltag = %d (A)\n", fltag); #endif for (j3 = j4; j3 < j5; ++j3) { #ifdef WSSMP_DBG chk(37, j3, adjln); #endif i = adjncy[j3 - 1]; #ifdef WSSMP_DBG chk(38, i, n); #endif if (varbl[i - 1] < 0) { i5 = perm[i - 1]; #ifdef WSSMP_DBG chk(39, i5, n); #endif j = head[i5 - 1]; if (j) { if (j < 0) { head[i5 - 1] = 0, i = -j; } else { #ifdef WSSMP_DBG chk(40, j, n); #endif i = perm[j - 1]; perm[j - 1] = 0; } while (i) { #ifdef WSSMP_DBG chk(41, i, n); #endif if (!snxt[i - 1]) { i = 0; } else { k = invp[i - 1]; i2 = xadj[i - 1] + (scln = lsize[i - 1]); for (l = xadj[i - 1] + 1; l < i2; l++) { #ifdef WSSMP_DBG chk(42, l, adjln); chk(43, adjncy[l - 1], n); #endif flag[adjncy[l - 1] - 1] = fltag; } jpp = i; j = snxt[i - 1]; while (j) { #ifdef WSSMP_DBG chk(44, j, n); #endif if (lsize[j - 1] == scln && invp[j - 1] == k) { i2 = xadj[j - 1] + scln; j8 = 1; for (l = xadj[j - 1] + 1; l < i2; l++) { #ifdef WSSMP_DBG chk(45, l, adjln); chk(46, adjncy[l - 1], n); #endif if (flag[adjncy[l - 1] - 1] != fltag) { j8 = 0; break; } } if (j8) { xadj[j - 1] = -i; varbl[i - 1] += varbl[j - 1]; varbl[j - 1] = invp[j - 1] = 0; #ifdef WSSMP_DBG chk(47, j, n); chk(48, jpp, n); #endif j = snxt[j - 1]; snxt[jpp - 1] = j; } else { jpp = j; #ifdef WSSMP_DBG chk(49, j, n); #endif j = snxt[j - 1]; } } else { jpp = j; #ifdef WSSMP_DBG chk(50, j, n); #endif j = snxt[j - 1]; } } fltag++; #ifdef WSSMP_DBG if (fltag + n + 1 < 0) printf("ERR**: fltag = %d (B)\n", fltag); #endif #ifdef WSSMP_DBG chk(51, i, n); #endif i = snxt[i - 1]; } } } } } j8 = nm1 - counter; switch (speed) { case 1: for (j = j3 = j4; j3 < j5; j3++) { #ifdef WSSMP_DBG chk(52, j3, adjln); #endif i = adjncy[j3 - 1]; #ifdef WSSMP_DBG chk(53, i, n); #endif numii = varbl[i - 1]; if (numii < 0) { k = 0; i4 = (l = xadj[i - 1]) + invp[i - 1]; for (; l < i4; l++) { #ifdef WSSMP_DBG chk(54, l, adjln); chk(55, adjncy[l - 1], n); #endif i5 = dgree[adjncy[l - 1] - 1]; if (k < i5) k = i5; } x = static_cast (k - 1); varbl[i - 1] = abs(numii); j9 = dgree[i - 1] + nodeg; deg = (j8 > j9 ? j9 : j8) + numii; if (deg < 1) deg = 1; y = static_cast (deg); dgree[i - 1] = deg; /* printf("%i %f should >= %i %f\n",deg,y,k-1,x); if (y < x) printf("** \n"); else printf("\n"); */ y = y * y - y; x = y - (x * x - x); if (x < 1.1) x = 1.1; deg = static_cast(sqrt(x)); /* if (deg < 1) deg = 1; */ erscore[i - 1] = deg; #ifdef WSSMP_DBG chk(56, deg, n - 1); #endif nnode = head[deg - 1]; if (nnode) perm[nnode - 1] = i; snxt[i - 1] = nnode; perm[i - 1] = 0; #ifdef WSSMP_DBG chk(57, j, adjln); #endif head[deg - 1] = adjncy[j-1] = i; j++; if (deg < mindeg) mindeg = deg; } } break; case 2: for (j = j3 = j4; j3 < j5; j3++) { #ifdef WSSMP_DBG chk(58, j3, adjln); #endif i = adjncy[j3 - 1]; #ifdef WSSMP_DBG chk(59, i, n); #endif numii = varbl[i - 1]; if (numii < 0) { x = static_cast (dgree[adjncy[xadj[i - 1] - 1] - 1] - 1); varbl[i - 1] = abs(numii); j9 = dgree[i - 1] + nodeg; deg = (j8 > j9 ? j9 : j8) + numii; if (deg < 1) deg = 1; y = static_cast (deg); dgree[i - 1] = deg; /* printf("%i %f should >= %i %f",deg,y,dgree[adjncy[xadj[i - 1] - 1] - 1]-1,x); if (y < x) printf("** \n"); else printf("\n"); */ y = y * y - y; x = y - (x * x - x); if (x < 1.1) x = 1.1; deg = static_cast(sqrt(x)); /* if (deg < 1) deg = 1; */ erscore[i - 1] = deg; #ifdef WSSMP_DBG chk(60, deg, n - 1); #endif nnode = head[deg - 1]; if (nnode) perm[nnode - 1] = i; snxt[i - 1] = nnode; perm[i - 1] = 0; #ifdef WSSMP_DBG chk(61, j, adjln); #endif head[deg - 1] = adjncy[j-1] = i; j++; if (deg < mindeg) mindeg = deg; } } break; default: for (j = j3 = j4; j3 < j5; j3++) { #ifdef WSSMP_DBG chk(62, j3, adjln); #endif i = adjncy[j3 - 1]; #ifdef WSSMP_DBG chk(63, i, n); #endif numii = varbl[i - 1]; if (numii < 0) { varbl[i - 1] = abs(numii); j9 = dgree[i - 1] + nodeg; deg = (j8 > j9 ? j9 : j8) + numii; if (deg < 1) deg = 1; dgree[i - 1] = deg; #ifdef WSSMP_DBG chk(64, deg, n - 1); #endif nnode = head[deg - 1]; if (nnode) perm[nnode - 1] = i; snxt[i - 1] = nnode; perm[i - 1] = 0; #ifdef WSSMP_DBG chk(65, j, adjln); #endif head[deg - 1] = adjncy[j-1] = i; j++; if (deg < mindeg) mindeg = deg; } } break; } if (currloc) { #ifdef WSSMP_DBG chk(66, node, n); #endif locatns += (lsize[node - 1] - currloc), locaux = j; } varbl[node - 1] = numpiv + nodeg; lsize[node - 1] = j - j4; if (!lsize[node - 1]) flag[node - 1] = xadj[node - 1] = 0; } for (l = 1; l <= n; l++) { if (!invp[l - 1]) { for (i = -xadj[l - 1]; invp[i - 1] >= 0; i = -xadj[i - 1]) {}; tn = i; #ifdef WSSMP_DBG chk(67, tn, n); #endif k = -invp[tn - 1]; i = l; #ifdef WSSMP_DBG chk(68, i, n); #endif while (invp[i - 1] >= 0) { nnode = -xadj[i - 1]; xadj[i - 1] = -tn; if (!invp[i - 1]) invp[i - 1] = k++; i = nnode; } invp[tn - 1] = -k; } } for (l = 0; l < n; l++) { i = abs(invp[l]); #ifdef WSSMP_DBG chk(69, i, n); #endif invp[l] = i; perm[i - 1] = l + 1; } return; } // This code is not needed, but left in in case needed sometime #if 0 /*C--------------------------------------------------------------------------*/ void amlfdr(WSI *n, WSI xadj[], WSI adjncy[], WSI dgree[], WSI *adjln, WSI *locaux, WSI varbl[], WSI snxt[], WSI perm[], WSI head[], WSI invp[], WSI lsize[], WSI flag[], WSI *ispeed) { WSI nn, nlocaux, nadjln, speed, i, j, mx, mxj, *erscore; #ifdef WSSMP_DBG printf("Calling amlfdr for n, speed = %d, %d\n", *n, *ispeed); #endif if ((nn = *n) == 0) return; #ifdef WSSMP_DBG if (nn == 31) { printf("n = %d; adjln = %d; locaux = %d; ispeed = %d\n", *n, *adjln, *locaux, *ispeed); } #endif if (nn < NORDTHRESH) { for (i = 0; i < nn; i++) lsize[i] = i; for (i = nn; i > 0; i--) { mx = dgree[0]; mxj = 0; for (j = 1; j < i; j++) if (dgree[j] > mx) { mx = dgree[j]; mxj = j; } invp[lsize[mxj]] = i; dgree[mxj] = dgree[i-1]; lsize[mxj] = lsize[i-1]; } return; } speed = *ispeed; if (speed < 3) { /* erscore = (WSI *)malloc(nn * sizeof(WSI)); if (erscore == NULL) speed = 3; */ wscmal (&nn, &i, &erscore); if (i != 0) speed = 3; } if (speed > 2) erscore = dgree; if (speed < 3) { for (i = 0; i < nn; i++) { perm[i] = 0; invp[i] = 0; head[i] = 0; flag[i] = 1; varbl[i] = 1; lsize[i] = dgree[i]; erscore[i] = dgree[i]; } } else { for (i = 0; i < nn; i++) { perm[i] = 0; invp[i] = 0; head[i] = 0; flag[i] = 1; varbl[i] = 1; lsize[i] = dgree[i]; } } nlocaux = *locaux; nadjln = *adjln; myamlf(nn, xadj, adjncy, dgree, varbl, snxt, perm, invp, head, lsize, flag, erscore, nlocaux, nadjln, speed); /* if (speed < 3) free(erscore); */ if (speed < 3) wscfr(&erscore); return; } #endif // end of taking out amlfdr /*C--------------------------------------------------------------------------*/ #endif // Orders rows int ClpCholeskyBase::orderAMD() { permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; // Do ordering int returnCode = 0; // get full matrix int space = 2 * sizeFactor_ + 10000 + 4 * numberRows_; int * temp = new int [space]; CoinBigIndex * count = new CoinBigIndex [numberRows_]; CoinBigIndex * tempStart = new CoinBigIndex [numberRows_+1]; memset(count, 0, numberRows_ * sizeof(int)); for (int iRow = 0; iRow < numberRows_; iRow++) { count[iRow] += choleskyStart_[iRow+1] - choleskyStart_[iRow] - 1; for (CoinBigIndex j = choleskyStart_[iRow] + 1; j < choleskyStart_[iRow+1]; j++) { int jRow = choleskyRow_[j]; count[jRow]++; } } #define OFFSET 1 CoinBigIndex sizeFactor = 0; for (int iRow = 0; iRow < numberRows_; iRow++) { int length = count[iRow]; permute_[iRow] = length; // add 1 to starts tempStart[iRow] = sizeFactor + OFFSET; count[iRow] = sizeFactor; sizeFactor += length; } tempStart[numberRows_] = sizeFactor + OFFSET; // add 1 to rows for (int iRow = 0; iRow < numberRows_; iRow++) { assert (choleskyRow_[choleskyStart_[iRow]] == iRow); for (CoinBigIndex j = choleskyStart_[iRow] + 1; j < choleskyStart_[iRow+1]; j++) { int jRow = choleskyRow_[j]; int put = count[iRow]; temp[put] = jRow + OFFSET; count[iRow]++; put = count[jRow]; temp[put] = iRow + OFFSET; count[jRow]++; } } for (int iRow = 1; iRow < numberRows_; iRow++) assert (count[iRow-1] == tempStart[iRow] - OFFSET); delete [] choleskyRow_; choleskyRow_ = temp; delete [] choleskyStart_; choleskyStart_ = tempStart; int locaux = sizeFactor + OFFSET; delete [] count; int speed = integerParameters_[0]; if (speed < 1 || speed > 2) speed = 3; int * use = new int [((speed<3) ? 7 : 6)*numberRows_]; int * dgree = use; int * varbl = dgree + numberRows_; int * snxt = varbl + numberRows_; int * head = snxt + numberRows_; int * lsize = head + numberRows_; int * flag = lsize + numberRows_; int * erscore; for (int i = 0; i < numberRows_; i++) { dgree[i] = choleskyStart_[i+1] - choleskyStart_[i]; head[i] = dgree[i]; snxt[i] = 0; permute_[i] = 0; permuteInverse_[i] = 0; head[i] = 0; flag[i] = 1; varbl[i] = 1; lsize[i] = dgree[i]; } if (speed < 3) { erscore = flag + numberRows_; for (int i = 0; i < numberRows_; i++) erscore[i] = dgree[i]; } else { erscore = dgree; } myamlf(numberRows_, choleskyStart_, choleskyRow_, dgree, varbl, snxt, permute_, permuteInverse_, head, lsize, flag, erscore, locaux, space, speed); for (int iRow = 0; iRow < numberRows_; iRow++) { permute_[iRow]--; } for (int iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[permute_[iRow]] = iRow; } for (int iRow = 0; iRow < numberRows_; iRow++) { assert (permuteInverse_[iRow] >= 0 && permuteInverse_[iRow] < numberRows_); } delete [] use; delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return returnCode; } /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyBase::symbolic() { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); // We need an array for counts int * used = new int[numberRows_+1]; // If KKT then re-order so negative first if (doKKT_) { int nn = 0; int np = 0; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int originalRow = permute_[iRow]; if (originalRow < numberTotal) permute_[nn++] = originalRow; else used[np++] = originalRow; } CoinMemcpyN(used, np, permute_ + nn); for (iRow = 0; iRow < numberRows_; iRow++) permuteInverse_[permute_[iRow]] = iRow; } CoinZeroN(used, numberRows_); int iRow; int iColumn; bool noMemory = false; CoinBigIndex * Astart = new CoinBigIndex[numberRows_+1]; int * Arow = NULL; try { Arow = new int [sizeFactor_]; } catch (...) { // no memory delete [] Astart; return -1; } choleskyStart_ = new int[numberRows_+1]; link_ = new int[numberRows_]; workInteger_ = new CoinBigIndex[numberRows_]; indexStart_ = new CoinBigIndex[numberRows_]; clique_ = new int[numberRows_]; // Redo so permuted upper triangular sizeFactor_ = 0; int * which = Arow; if (!doKKT_) { for (iRow = 0; iRow < numberRows_; iRow++) { int number = 0; int iOriginalRow = permute_[iRow]; Astart[iRow] = sizeFactor_; CoinBigIndex startRow = rowStart[iOriginalRow]; CoinBigIndex endRow = rowStart[iOriginalRow] + rowLength[iOriginalRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow < iRow) { if (!used[jNewRow]) { used[jNewRow] = 1; which[number++] = jNewRow; } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } else { // KKT // transpose ClpMatrixBase * rowCopy = model_->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const int * column = rowCopy->getIndices(); // temp bool permuted = false; for (iRow = 0; iRow < numberRows_; iRow++) { if (permute_[iRow] != iRow) { permuted = true; break; } } if (permuted) { // Need to permute - ugly if (!quadratic) { for (iRow = 0; iRow < numberRows_; iRow++) { Astart[iRow] = sizeFactor_; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { // A may be upper triangular by mistake iColumn = iOriginalRow; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } } else if (iOriginalRow < numberTotal) { int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } else { int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow < iRow) Arow[sizeFactor_++] = jNewRow; } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } // Sort std::sort(Arow + Astart[iRow], Arow + sizeFactor_); } } else { // quadratic // transpose CoinPackedMatrix quadraticT; quadraticT.reverseOrderedCopyOf(*quadratic); const int * columnQuadratic = quadraticT.getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticT.getVectorStarts(); const int * columnQuadraticLength = quadraticT.getVectorLengths(); for (iRow = 0; iRow < numberRows_; iRow++) { Astart[iRow] = sizeFactor_; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { // Quadratic bit CoinBigIndex j; for ( j = columnQuadraticStart[iOriginalRow]; j < columnQuadraticStart[iOriginalRow] + columnQuadraticLength[iOriginalRow]; j++) { int jColumn = columnQuadratic[j]; int jNewColumn = permuteInverse_[jColumn]; if (jNewColumn < iRow) Arow[sizeFactor_++] = jNewColumn; } // A may be upper triangular by mistake iColumn = iOriginalRow; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } } else if (iOriginalRow < numberTotal) { int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } else { int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow < iRow) Arow[sizeFactor_++] = jNewRow; } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow < iRow) Arow[sizeFactor_++] = kRow; } // Sort std::sort(Arow + Astart[iRow], Arow + sizeFactor_); } } } else { if (!quadratic) { for (iRow = 0; iRow < numberRows_; iRow++) { Astart[iRow] = sizeFactor_; } } else { // Quadratic // transpose CoinPackedMatrix quadraticT; quadraticT.reverseOrderedCopyOf(*quadratic); const int * columnQuadratic = quadraticT.getIndices(); const CoinBigIndex * columnQuadraticStart = quadraticT.getVectorStarts(); const int * columnQuadraticLength = quadraticT.getVectorLengths(); //const double * quadraticElement = quadraticT.getElements(); for (iRow = 0; iRow < numberColumns; iRow++) { int iOriginalRow = permute_[iRow]; Astart[iRow] = sizeFactor_; for (CoinBigIndex j = columnQuadraticStart[iOriginalRow]; j < columnQuadraticStart[iOriginalRow] + columnQuadraticLength[iOriginalRow]; j++) { int jColumn = columnQuadratic[j]; int jNewColumn = permuteInverse_[jColumn]; if (jNewColumn < iRow) Arow[sizeFactor_++] = jNewColumn; } } } int iRow; // slacks for (iRow = 0; iRow < numberRowsModel; iRow++) { Astart[iRow+numberColumns] = sizeFactor_; } for (iRow = 0; iRow < numberRowsModel; iRow++) { Astart[iRow+numberTotal] = sizeFactor_; CoinBigIndex start = rowStart[iRow]; CoinBigIndex end = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex j = start; j < end; j++) { Arow[sizeFactor_++] = column[j]; } // slack Arow[sizeFactor_++] = numberColumns + iRow; } } delete rowCopy; } Astart[numberRows_] = sizeFactor_; firstDense_ = numberRows_; symbolic1(Astart, Arow); // Now fill in indices try { // too big choleskyRow_ = new int[sizeFactor_]; } catch (...) { // no memory noMemory = true; } double sizeFactor = sizeFactor_; if (!noMemory) { // Do lower triangular sizeFactor_ = 0; int * which = Arow; if (!doKKT_) { for (iRow = 0; iRow < numberRows_; iRow++) { int number = 0; int iOriginalRow = permute_[iRow]; Astart[iRow] = sizeFactor_; if (!rowsDropped_[iOriginalRow]) { CoinBigIndex startRow = rowStart[iOriginalRow]; CoinBigIndex endRow = rowStart[iOriginalRow] + rowLength[iOriginalRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow > iRow && !rowsDropped_[jRow]) { if (!used[jNewRow]) { used[jNewRow] = 1; which[number++] = jNewRow; } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } } else { // KKT // temp bool permuted = false; for (iRow = 0; iRow < numberRows_; iRow++) { if (permute_[iRow] != iRow) { permuted = true; break; } } // but fake it for (iRow = 0; iRow < numberRows_; iRow++) { //permute_[iRow]=iRow; // force no permute //permuteInverse_[permute_[iRow]]=iRow; } if (permuted) { // Need to permute - ugly if (!quadratic) { for (iRow = 0; iRow < numberRows_; iRow++) { Astart[iRow] = sizeFactor_; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { iColumn = iOriginalRow; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } } else if (iOriginalRow < numberTotal) { int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } else { int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow > iRow) Arow[sizeFactor_++] = jNewRow; } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } // Sort std::sort(Arow + Astart[iRow], Arow + sizeFactor_); } } else { // quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); for (iRow = 0; iRow < numberRows_; iRow++) { Astart[iRow] = sizeFactor_; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { // Quadratic bit CoinBigIndex j; for ( j = columnQuadraticStart[iOriginalRow]; j < columnQuadraticStart[iOriginalRow] + columnQuadraticLength[iOriginalRow]; j++) { int jColumn = columnQuadratic[j]; int jNewColumn = permuteInverse_[jColumn]; if (jNewColumn > iRow) Arow[sizeFactor_++] = jNewColumn; } iColumn = iOriginalRow; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } } else if (iOriginalRow < numberTotal) { int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } else { int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow > iRow) Arow[sizeFactor_++] = jNewRow; } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow > iRow) Arow[sizeFactor_++] = kRow; } // Sort std::sort(Arow + Astart[iRow], Arow + sizeFactor_); } } } else { if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { Astart[iColumn] = sizeFactor_; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { Arow[sizeFactor_++] = row[j] + numberTotal; } } } else { // Quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); //const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { Astart[iColumn] = sizeFactor_; CoinBigIndex j; for ( j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) Arow[sizeFactor_++] = jColumn; } CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for ( j = start; j < end; j++) { Arow[sizeFactor_++] = row[j] + numberTotal; } } } // slacks for (iRow = 0; iRow < numberRowsModel; iRow++) { Astart[iRow+numberColumns] = sizeFactor_; Arow[sizeFactor_++] = iRow + numberTotal; } // Transpose - nonzero diagonal (may regularize) for (iRow = 0; iRow < numberRowsModel; iRow++) { Astart[iRow+numberTotal] = sizeFactor_; } } Astart[numberRows_] = sizeFactor_; } symbolic2(Astart, Arow); if (sizeIndex_ < sizeFactor_) { int * indices = NULL; try { indices = new int[sizeIndex_]; } catch (...) { // no memory noMemory = true; } if (!noMemory) { CoinMemcpyN(choleskyRow_, sizeIndex_, indices); delete [] choleskyRow_; choleskyRow_ = indices; } } } delete [] used; // Use cholesky regions delete [] Astart; delete [] Arow; double flops = 0.0; for (iRow = 0; iRow < numberRows_; iRow++) { int length = choleskyStart_[iRow+1] - choleskyStart_[iRow]; flops += static_cast (length) * (length + 2.0); } if (model_->messageHandler()->logLevel() > 0) std::cout << sizeFactor << " elements in sparse Cholesky, flop count " << flops << std::endl; try { sparseFactor_ = new longDouble [sizeFactor_]; #if CLP_LONG_CHOLESKY!=1 workDouble_ = new longDouble[numberRows_]; #else // actually long double workDouble_ = reinterpret_cast (new CoinWorkDouble[numberRows_]); #endif diagonal_ = new longDouble[numberRows_]; } catch (...) { // no memory noMemory = true; } if (noMemory) { delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; delete [] permuteInverse_; permuteInverse_ = NULL; delete [] permute_; permute_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; delete [] indexStart_; indexStart_ = NULL; delete [] link_; link_ = NULL; delete [] workInteger_; workInteger_ = NULL; delete [] sparseFactor_; sparseFactor_ = NULL; delete [] workDouble_; workDouble_ = NULL; delete [] diagonal_; diagonal_ = NULL; delete [] clique_; clique_ = NULL; return -1; } return 0; } int ClpCholeskyBase::symbolic1(const CoinBigIndex * Astart, const int * Arow) { int * marked = reinterpret_cast (workInteger_); int iRow; // may not need to do this here but makes debugging easier for (iRow = 0; iRow < numberRows_; iRow++) { marked[iRow] = -1; link_[iRow] = -1; choleskyStart_[iRow] = 0; // counts } for (iRow = 0; iRow < numberRows_; iRow++) { marked[iRow] = iRow; for (CoinBigIndex j = Astart[iRow]; j < Astart[iRow+1]; j++) { int kRow = Arow[j]; while (marked[kRow] != iRow ) { if (link_[kRow] < 0 ) link_[kRow] = iRow; choleskyStart_[kRow]++; marked[kRow] = iRow; kRow = link_[kRow]; } } } sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = choleskyStart_[iRow]; choleskyStart_[iRow] = sizeFactor_; sizeFactor_ += number; } choleskyStart_[numberRows_] = sizeFactor_; return sizeFactor_;; } void ClpCholeskyBase::symbolic2(const CoinBigIndex * Astart, const int * Arow) { int * mergeLink = clique_; int * marker = reinterpret_cast (workInteger_); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { marker[iRow] = -1; mergeLink[iRow] = -1; link_[iRow] = -1; // not needed but makes debugging easier } int start = 0; int end = 0; choleskyStart_[0] = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int nz = 0; int merge = mergeLink[iRow]; bool marked = false; if (merge < 0) marker[iRow] = iRow; else marker[iRow] = merge; start = end; int startSub = start; link_[iRow] = numberRows_; CoinBigIndex j; for ( j = Astart[iRow]; j < Astart[iRow+1]; j++) { int kRow = Arow[j]; int k = iRow; int linked = link_[iRow]; #ifndef NDEBUG int count = 0; #endif while (linked <= kRow) { k = linked; linked = link_[k]; #ifndef NDEBUG count++; assert (count < numberRows_); #endif } nz++; link_[k] = kRow; link_[kRow] = linked; if (marker[kRow] != marker[iRow]) marked = true; } bool reuse = false; // Check if we can re-use indices if (!marked && merge >= 0 && mergeLink[merge] < 0) { // can re-use all startSub = indexStart_[merge] + 1; nz = choleskyStart_[merge+1] - (choleskyStart_[merge] + 1); reuse = true; } else { // See if we can re-use any int k = mergeLink[iRow]; int maxLength = 0; while (k >= 0) { int length = choleskyStart_[k+1] - (choleskyStart_[k] + 1); int start = indexStart_[k] + 1; int stop = start + length; if (length > maxLength) { maxLength = length; startSub = start; } int linked = iRow; for (CoinBigIndex j = start; j < stop; j++) { int kRow = choleskyRow_[j]; int kk = linked; linked = link_[kk]; while (linked < kRow) { kk = linked; linked = link_[kk]; } if (linked != kRow) { nz++; link_[kk] = kRow; link_[kRow] = linked; linked = kRow; } } k = mergeLink[k]; } if (nz == maxLength) reuse = true; // can re-use } //reuse=false; //temp if (!reuse) { end += nz; startSub = start; int kRow = iRow; for (int j = start; j < end; j++) { kRow = link_[kRow]; choleskyRow_[j] = kRow; assert (kRow < numberRows_); marker[kRow] = iRow; } marker[iRow] = iRow; } indexStart_[iRow] = startSub; choleskyStart_[iRow+1] = choleskyStart_[iRow] + nz; if (nz > 1) { int kRow = choleskyRow_[startSub]; mergeLink[iRow] = mergeLink[kRow]; mergeLink[kRow] = iRow; } // should not be needed //std::sort(choleskyRow_+indexStart_[iRow] // ,choleskyRow_+indexStart_[iRow]+nz); //#define CLP_DEBUG #ifdef CLP_DEBUG int last = -1; for ( j = indexStart_[iRow]; j < indexStart_[iRow] + nz; j++) { int kRow = choleskyRow_[j]; assert (kRow > last); last = kRow; } #endif } sizeFactor_ = choleskyStart_[numberRows_]; sizeIndex_ = start; // find dense segment here int numberleft = numberRows_; for (iRow = 0; iRow < numberRows_; iRow++) { CoinBigIndex left = sizeFactor_ - choleskyStart_[iRow]; double n = numberleft; double threshold = n * (n - 1.0) * 0.5 * goDense_; if ( left >= threshold) break; numberleft--; } //iRow=numberRows_; int nDense = numberRows_ - iRow; #define DENSE_THRESHOLD 8 // don't do if dense columns if (nDense >= DENSE_THRESHOLD && !dense_) { COIN_DETAIL_PRINT(printf("Going dense for last %d rows\n", nDense)); // make sure we don't disturb any indices CoinBigIndex k = 0; for (int jRow = 0; jRow < iRow; jRow++) { int nz = choleskyStart_[jRow+1] - choleskyStart_[jRow]; k = CoinMax(k, indexStart_[jRow] + nz); } indexStart_[iRow] = k; int j; for (j = iRow + 1; j < numberRows_; j++) { choleskyRow_[k++] = j; indexStart_[j] = k; } sizeIndex_ = k; assert (k <= sizeFactor_); // can't happen with any reasonable defaults k = choleskyStart_[iRow]; for (j = iRow + 1; j <= numberRows_; j++) { k += numberRows_ - j; choleskyStart_[j] = k; } // allow for blocked dense ClpCholeskyDense dense; sizeFactor_ = choleskyStart_[iRow] + dense.space(nDense); firstDense_ = iRow; if (doKKT_) { // redo permute so negative ones first int putN = firstDense_; int putP = 0; int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; for (iRow = firstDense_; iRow < numberRows_; iRow++) { int originalRow = permute_[iRow]; if (originalRow < numberTotal) permute_[putN++] = originalRow; else permuteInverse_[putP++] = originalRow; } for (iRow = putN; iRow < numberRows_; iRow++) { permute_[iRow] = permuteInverse_[iRow-putN]; } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[permute_[iRow]] = iRow; } } } // Clean up clique info for (iRow = 0; iRow < numberRows_; iRow++) clique_[iRow] = 0; int lastClique = -1; bool inClique = false; for (iRow = 1; iRow < firstDense_; iRow++) { int sizeLast = choleskyStart_[iRow] - choleskyStart_[iRow-1]; int sizeThis = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (indexStart_[iRow] == indexStart_[iRow-1] + 1 && sizeThis == sizeLast - 1 && sizeThis) { // in clique if (!inClique) { inClique = true; lastClique = iRow - 1; } } else if (inClique) { int sizeClique = iRow - lastClique; for (int i = lastClique; i < iRow; i++) { clique_[i] = sizeClique; sizeClique--; } inClique = false; } } if (inClique) { int sizeClique = iRow - lastClique; for (int i = lastClique; i < iRow; i++) { clique_[i] = sizeClique; sizeClique--; } } //for (iRow=0;iRowclpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); //perturbation CoinWorkDouble perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); //perturbation=perturbation*perturbation*100000000.0; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = CoinSqrt(perturbation); perturbation = 1.0; } int iRow; int iColumn; longDouble * work = workDouble_; CoinZeroN(work, numberRows_); int newDropped = 0; CoinWorkDouble largest = 1.0; CoinWorkDouble smallest = COIN_DBL_MAX; int numberDense = 0; if (!doKKT_) { const CoinWorkDouble * diagonalSlack = diagonal + numberColumns; if (dense_) numberDense = dense_->numberRows(); if (whichDense_) { longDouble * denseDiagonal = dense_->diagonal(); longDouble * dense = denseColumn_; int iDense = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (whichDense_[iColumn]) { CoinZeroN(dense, numberRows_); CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; if (diagonal[iColumn]) { denseDiagonal[iDense++] = 1.0 / diagonal[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; dense[jRow] = element[j]; } } else { denseDiagonal[iDense++] = 1.0; } dense += numberRows_; } } } CoinWorkDouble delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; // largest in initial matrix CoinWorkDouble largest2 = 1.0e-20; for (iRow = 0; iRow < numberRows_; iRow++) { longDouble * put = sparseFactor_ + choleskyStart_[iRow]; int * which = choleskyRow_ + indexStart_[iRow]; int iOriginalRow = permute_[iRow]; int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iOriginalRow]) rowsDropped_[iOriginalRow] = 1; if (!rowsDropped_[iOriginalRow]) { CoinBigIndex startRow = rowStart[iOriginalRow]; CoinBigIndex endRow = rowStart[iOriginalRow] + rowLength[iOriginalRow]; work[iRow] = diagonalSlack[iOriginalRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; CoinWorkDouble multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow >= iRow && !rowsDropped_[jRow]) { CoinWorkDouble value = element[j] * multiplier; work[jNewRow] += value; } } } } diagonal_[iRow] = work[iRow]; largest2 = CoinMax(largest2, CoinAbs(work[iRow])); work[iRow] = 0.0; int j; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; largest2 = CoinMax(largest2, CoinAbs(work[jRow])); work[jRow] = 0.0; } } else { // dropped diagonal_[iRow] = 1.0; int j; for (j = 1; j < number; j++) { put[j] = 0.0; } } } //check sizes largest2 *= 1.0e-20; largest = CoinMin(largest2, CHOL_SMALL_VALUE); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinWorkDouble diagonal = diagonal_[iRow]; if (diagonal > largest2) { diagonal_[iRow] = diagonal + perturbation; } else { diagonal_[iRow] = diagonal + perturbation; rowsDropped[iRow] = 2; numberDroppedBefore++; //printf("dropped - small diagonal %g\n",diagonal); } } } doubleParameters_[10] = CoinMax(1.0e-20, largest); integerParameters_[20] = 0; doubleParameters_[3] = 0.0; doubleParameters_[4] = COIN_DBL_MAX; integerParameters_[34] = 0; // say all must be positive factorizePart2(rowsDropped); newDropped = integerParameters_[20] + numberDroppedBefore; largest = doubleParameters_[3]; smallest = doubleParameters_[4]; if (model_->messageHandler()->logLevel() > 1) std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl; choleskyCondition_ = largest / smallest; if (whichDense_) { int i; for ( i = 0; i < numberRows_; i++) { assert (diagonal_[i] >= 0.0); diagonal_[i] = CoinSqrt(diagonal_[i]); } // Update dense columns (just L) // Zero out dropped rows for (i = 0; i < numberDense; i++) { longDouble * a = denseColumn_ + i * numberRows_; for (int j = 0; j < numberRows_; j++) { if (rowsDropped[j]) a[j] = 0.0; } for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; workDouble_[i] = a[iRow]; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble value = workDouble_[i]; CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinBigIndex j; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; workDouble_[iRow] -= sparseFactor_[j] * value; } } for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; a[iRow] = workDouble_[i] * diagonal_[i]; } } dense_->resetRowsDropped(); longDouble * denseBlob = dense_->aMatrix(); longDouble * denseDiagonal = dense_->diagonal(); // Update dense matrix for (i = 0; i < numberDense; i++) { const longDouble * a = denseColumn_ + i * numberRows_; // do diagonal CoinWorkDouble value = denseDiagonal[i]; const longDouble * b = denseColumn_ + i * numberRows_; for (int k = 0; k < numberRows_; k++) value += a[k] * b[k]; denseDiagonal[i] = value; for (int j = i + 1; j < numberDense; j++) { CoinWorkDouble value = 0.0; const longDouble * b = denseColumn_ + j * numberRows_; for (int k = 0; k < numberRows_; k++) value += a[k] * b[k]; *denseBlob = value; denseBlob++; } } // dense cholesky (? long double) int * dropped = new int [numberDense]; dense_->factorizePart2(dropped); delete [] dropped; } // try allowing all every time //printf("trying ?\n"); //for (iRow=0;iRownumberIterations()<20||(model_->numberIterations()&1)==0) if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier if (newDropped || numberRowsDropped_) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = static_cast(rowsDropped[i]); rowsDropped_[i] = dropped; rowsDropped_[i] = 0; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(2 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = static_cast(rowsDropped[i]); rowsDropped_[i] = dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_ && 0) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } } else { //KKT CoinPackedMatrix * quadratic = NULL; ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(model_->objectiveAsObject())); if (quadraticObj) quadratic = quadraticObj->quadraticObjective(); // matrix int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; // temp bool permuted = false; for (iRow = 0; iRow < numberRows_; iRow++) { if (permute_[iRow] != iRow) { permuted = true; break; } } // but fake it for (iRow = 0; iRow < numberRows_; iRow++) { //permute_[iRow]=iRow; // force no permute //permuteInverse_[permute_[iRow]]=iRow; } if (permuted) { CoinWorkDouble delta2 = model_->delta(); // add delta*delta to bottom delta2 *= delta2; // Need to permute - ugly if (!quadratic) { for (iRow = 0; iRow < numberRows_; iRow++) { longDouble * put = sparseFactor_ + choleskyStart_[iRow]; int * which = choleskyRow_ + indexStart_[iRow]; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { iColumn = iOriginalRow; CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); diagonal_[iRow] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow > iRow) { work[kRow] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } } } else { diagonal_[iRow] = -value; } } else if (iOriginalRow < numberTotal) { CoinWorkDouble value = diagonal[iOriginalRow]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); } else { value = 1.0e100; } diagonal_[iRow] = -value; int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow > iRow) work[kRow] = -1.0; } else { diagonal_[iRow] = delta2; int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow > iRow) { work[jNewRow] = elementByRow[j]; largest = CoinMax(largest, CoinAbs(elementByRow[j])); } } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow > iRow) work[kRow] = -1.0; } CoinBigIndex j; int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } } else { // quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); const double * quadraticElement = quadratic->getElements(); for (iRow = 0; iRow < numberRows_; iRow++) { longDouble * put = sparseFactor_ + choleskyStart_[iRow]; int * which = choleskyRow_ + indexStart_[iRow]; int iOriginalRow = permute_[iRow]; if (iOriginalRow < numberColumns) { CoinBigIndex j; iColumn = iOriginalRow; CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; int jNewColumn = permuteInverse_[jColumn]; if (jNewColumn > iRow) { work[jNewColumn] = -quadraticElement[j]; } else if (iColumn == jColumn) { value += quadraticElement[j]; } } largest = CoinMax(largest, CoinAbs(value)); diagonal_[iRow] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (j = start; j < end; j++) { int kRow = row[j] + numberTotal; kRow = permuteInverse_[kRow]; if (kRow > iRow) { work[kRow] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } } } else { diagonal_[iRow] = -value; } } else if (iOriginalRow < numberTotal) { CoinWorkDouble value = diagonal[iOriginalRow]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); } else { value = 1.0e100; } diagonal_[iRow] = -value; int kRow = permuteInverse_[iOriginalRow+numberRowsModel]; if (kRow > iRow) work[kRow] = -1.0; } else { diagonal_[iRow] = delta2; int kRow = iOriginalRow - numberTotal; CoinBigIndex start = rowStart[kRow]; CoinBigIndex end = rowStart[kRow] + rowLength[kRow]; for (CoinBigIndex j = start; j < end; j++) { int jRow = column[j]; int jNewRow = permuteInverse_[jRow]; if (jNewRow > iRow) { work[jNewRow] = elementByRow[j]; largest = CoinMax(largest, CoinAbs(elementByRow[j])); } } // slack - should it be permute kRow = permuteInverse_[kRow+numberColumns]; if (kRow > iRow) work[kRow] = -1.0; } CoinBigIndex j; int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } for (j = 0; j < numberRows_; j++) assert (!work[j]); } } } else { if (!quadratic) { for (iColumn = 0; iColumn < numberColumns; iColumn++) { longDouble * put = sparseFactor_ + choleskyStart_[iColumn]; int * which = choleskyRow_ + indexStart_[iColumn]; CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); diagonal_[iColumn] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { //choleskyRow_[numberElements]=row[j]+numberTotal; //sparseFactor_[numberElements++]=element[j]; work[row[j] + numberTotal] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } } else { diagonal_[iColumn] = -value; } CoinBigIndex j; int number = choleskyStart_[iColumn+1] - choleskyStart_[iColumn]; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } } else { // Quadratic const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); const double * quadraticElement = quadratic->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { longDouble * put = sparseFactor_ + choleskyStart_[iColumn]; int * which = choleskyRow_ + indexStart_[iColumn]; int number = choleskyStart_[iColumn+1] - choleskyStart_[iColumn]; CoinWorkDouble value = diagonal[iColumn]; CoinBigIndex j; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; if (jColumn > iColumn) { work[jColumn] = -quadraticElement[j]; } else if (iColumn == jColumn) { value += quadraticElement[j]; } } largest = CoinMax(largest, CoinAbs(value)); diagonal_[iColumn] = -value; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (j = start; j < end; j++) { work[row[j] + numberTotal] = element[j]; largest = CoinMax(largest, CoinAbs(element[j])); } for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } else { value = 1.0e100; diagonal_[iColumn] = -value; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; } } } } // slacks for (iColumn = numberColumns; iColumn < numberTotal; iColumn++) { longDouble * put = sparseFactor_ + choleskyStart_[iColumn]; int * which = choleskyRow_ + indexStart_[iColumn]; CoinWorkDouble value = diagonal[iColumn]; if (CoinAbs(value) > 1.0e-100) { value = 1.0 / value; largest = CoinMax(largest, CoinAbs(value)); } else { value = 1.0e100; } diagonal_[iColumn] = -value; work[iColumn-numberColumns+numberTotal] = -1.0; CoinBigIndex j; int number = choleskyStart_[iColumn+1] - choleskyStart_[iColumn]; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } // Finish diagonal CoinWorkDouble delta2 = model_->delta(); // add delta*delta to bottom delta2 *= delta2; for (iRow = 0; iRow < numberRowsModel; iRow++) { longDouble * put = sparseFactor_ + choleskyStart_[iRow+numberTotal]; diagonal_[iRow+numberTotal] = delta2; CoinBigIndex j; int number = choleskyStart_[iRow+numberTotal+1] - choleskyStart_[iRow+numberTotal]; for (j = 0; j < number; j++) { put[j] = 0.0; } } } //check sizes largest *= 1.0e-20; largest = CoinMin(largest, CHOL_SMALL_VALUE); doubleParameters_[10] = CoinMax(1.0e-20, largest); integerParameters_[20] = 0; doubleParameters_[3] = 0.0; doubleParameters_[4] = COIN_DBL_MAX; // Set up LDL cutoff integerParameters_[34] = numberTotal; // KKT int * rowsDropped2 = new int[numberRows_]; CoinZeroN(rowsDropped2, numberRows_); factorizePart2(rowsDropped2); newDropped = integerParameters_[20]; largest = doubleParameters_[3]; smallest = doubleParameters_[4]; if (model_->messageHandler()->logLevel() > 1) std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl; choleskyCondition_ = largest / smallest; // Should save adjustments in ..R_ int n1 = 0, n2 = 0; CoinWorkDouble * primalR = model_->primalR(); CoinWorkDouble * dualR = model_->dualR(); for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped2[iRow]) { n1++; //printf("row region1 %d dropped\n",iRow); //rowsDropped_[iRow]=1; rowsDropped_[iRow] = 0; primalR[iRow] = doubleParameters_[20]; } else { rowsDropped_[iRow] = 0; primalR[iRow] = 0.0; } } for (; iRow < numberRows_; iRow++) { if (rowsDropped2[iRow]) { n2++; //printf("row region2 %d dropped\n",iRow); //rowsDropped_[iRow]=1; rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = doubleParameters_[34]; } else { rowsDropped_[iRow] = 0; dualR[iRow-numberTotal] = 0.0; } } delete [] rowsDropped2; } status_ = 0; return newDropped; } /* Factorize - filling in rowsDropped and returning number dropped in integerParam. */ void ClpCholeskyBase::factorizePart2(int * rowsDropped) { CoinWorkDouble largest = doubleParameters_[3]; CoinWorkDouble smallest = doubleParameters_[4]; // probably done before largest = 0.0; smallest = COIN_DBL_MAX; double dropValue = doubleParameters_[10]; int firstPositive = integerParameters_[34]; longDouble * d = ClpCopyOfArray(diagonal_, numberRows_); int iRow; // minimum size before clique done //#define MINCLIQUE INT_MAX #define MINCLIQUE 3 longDouble * work = workDouble_; CoinBigIndex * first = workInteger_; for (iRow = 0; iRow < numberRows_; iRow++) { link_[iRow] = -1; work[iRow] = 0.0; first[iRow] = choleskyStart_[iRow]; } int lastClique = -1; bool inClique = false; bool newClique = false; bool endClique = false; int lastRow = 0; int nextRow2 = -1; for (iRow = 0; iRow < firstDense_ + 1; iRow++) { if (iRow < firstDense_) { endClique = false; if (clique_[iRow] > 0) { // this is in a clique inClique = true; if (clique_[iRow] > lastClique) { // new Clique newClique = true; // If we have clique going then signal to do old one endClique = (lastClique > 0); } else { // Still in clique newClique = false; } } else { // not in clique inClique = false; newClique = false; // If we have clique going then signal to do old one endClique = (lastClique > 0); } lastClique = clique_[iRow]; } else if (inClique) { // Finish off endClique = true; } else { break; } if (endClique) { // We have just finished updating a clique - do block pivot and clean up int jRow; for ( jRow = lastRow; jRow < iRow; jRow++) { int jCount = jRow - lastRow; CoinWorkDouble diagonalValue = diagonal_[jRow]; CoinBigIndex start = choleskyStart_[jRow]; CoinBigIndex end = choleskyStart_[jRow+1]; for (int kRow = lastRow; kRow < jRow; kRow++) { jCount--; CoinBigIndex get = choleskyStart_[kRow] + jCount; CoinWorkDouble a_jk = sparseFactor_[get]; CoinWorkDouble value1 = d[kRow] * a_jk; diagonalValue -= a_jk * value1; for (CoinBigIndex j = start; j < end; j++) sparseFactor_[j] -= value1 * sparseFactor_[++get]; } // check int originalRow = permute_[jRow]; if (originalRow < firstPositive) { // must be negative if (diagonalValue <= -dropValue) { smallest = CoinMin(smallest, -diagonalValue); largest = CoinMax(largest, -diagonalValue); d[jRow] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { rowsDropped[originalRow] = 2; d[jRow] = -1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } else { // must be positive if (diagonalValue >= dropValue) { smallest = CoinMin(smallest, diagonalValue); largest = CoinMax(largest, diagonalValue); d[jRow] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { rowsDropped[originalRow] = 2; d[jRow] = 1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } diagonal_[jRow] = diagonalValue; for (CoinBigIndex j = start; j < end; j++) { sparseFactor_[j] *= diagonalValue; } } if (nextRow2 >= 0) { for ( jRow = lastRow; jRow < iRow - 1; jRow++) { link_[jRow] = jRow + 1; } link_[iRow-1] = link_[nextRow2]; link_[nextRow2] = lastRow; } } if (iRow == firstDense_) break; // we were just cleaning up if (newClique) { // initialize new clique lastRow = iRow; } // for each column L[*,kRow] that affects L[*,iRow] CoinWorkDouble diagonalValue = diagonal_[iRow]; int nextRow = link_[iRow]; int kRow = 0; while (1) { kRow = nextRow; if (kRow < 0) break; // out of loop nextRow = link_[kRow]; // Modify by outer product of L[*,irow] by L[*,krow] from first CoinBigIndex k = first[kRow]; CoinBigIndex end = choleskyStart_[kRow+1]; assert(k < end); CoinWorkDouble a_ik = sparseFactor_[k++]; CoinWorkDouble value1 = d[kRow] * a_ik; // update first first[kRow] = k; diagonalValue -= value1 * a_ik; CoinBigIndex offset = indexStart_[kRow] - choleskyStart_[kRow]; if (k < end) { int jRow = choleskyRow_[k+offset]; if (clique_[kRow] < MINCLIQUE) { link_[kRow] = link_[jRow]; link_[jRow] = kRow; for (; k < end; k++) { int jRow = choleskyRow_[k+offset]; work[jRow] += sparseFactor_[k] * value1; } } else { // Clique CoinBigIndex currentIndex = k + offset; int linkSave = link_[jRow]; link_[jRow] = kRow; work[kRow] = value1; // ? or a_jk int last = kRow + clique_[kRow]; for (int kkRow = kRow + 1; kkRow < last; kkRow++) { CoinBigIndex j = first[kkRow]; //int iiRow = choleskyRow_[j+indexStart_[kkRow]-choleskyStart_[kkRow]]; CoinWorkDouble a = sparseFactor_[j]; CoinWorkDouble dValue = d[kkRow] * a; diagonalValue -= a * dValue; work[kkRow] = dValue; first[kkRow]++; link_[kkRow-1] = kkRow; } nextRow = link_[last-1]; link_[last-1] = linkSave; int length = end - k; for (int i = 0; i < length; i++) { int lRow = choleskyRow_[currentIndex++]; CoinWorkDouble t0 = work[lRow]; for (int kkRow = kRow; kkRow < last; kkRow++) { CoinBigIndex j = first[kkRow] + i; t0 += work[kkRow] * sparseFactor_[j]; } work[lRow] = t0; } } } } // Now apply if (inClique) { // in clique diagonal_[iRow] = diagonalValue; CoinBigIndex start = choleskyStart_[iRow]; CoinBigIndex end = choleskyStart_[iRow+1]; CoinBigIndex currentIndex = indexStart_[iRow]; nextRow2 = -1; CoinBigIndex get = start + clique_[iRow] - 1; if (get < end) { nextRow2 = choleskyRow_[currentIndex+get-start]; first[iRow] = get; } for (CoinBigIndex j = start; j < end; j++) { int kRow = choleskyRow_[currentIndex++]; sparseFactor_[j] -= work[kRow]; // times? work[kRow] = 0.0; } } else { // not in clique int originalRow = permute_[iRow]; if (originalRow < firstPositive) { // must be negative if (diagonalValue <= -dropValue) { smallest = CoinMin(smallest, -diagonalValue); largest = CoinMax(largest, -diagonalValue); d[iRow] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { rowsDropped[originalRow] = 2; d[iRow] = -1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } else { // must be positive if (diagonalValue >= dropValue) { smallest = CoinMin(smallest, diagonalValue); largest = CoinMax(largest, diagonalValue); d[iRow] = diagonalValue; diagonalValue = 1.0 / diagonalValue; } else { rowsDropped[originalRow] = 2; d[iRow] = 1.0e100; diagonalValue = 0.0; integerParameters_[20]++; } } diagonal_[iRow] = diagonalValue; CoinBigIndex offset = indexStart_[iRow] - choleskyStart_[iRow]; CoinBigIndex start = choleskyStart_[iRow]; CoinBigIndex end = choleskyStart_[iRow+1]; assert (first[iRow] == start); if (start < end) { int nextRow = choleskyRow_[start+offset]; link_[iRow] = link_[nextRow]; link_[nextRow] = iRow; for (CoinBigIndex j = start; j < end; j++) { int jRow = choleskyRow_[j+offset]; CoinWorkDouble value = sparseFactor_[j] - work[jRow]; work[jRow] = 0.0; sparseFactor_[j] = diagonalValue * value; } } } } if (firstDense_ < numberRows_) { // do dense // update dense part updateDense(d,/*work,*/first); ClpCholeskyDense dense; // just borrow space int nDense = numberRows_ - firstDense_; if (doKKT_) { for (iRow = firstDense_; iRow < numberRows_; iRow++) { int originalRow = permute_[iRow]; if (originalRow >= firstPositive) { firstPositive = iRow - firstDense_; break; } } } dense.reserveSpace(this, nDense); int * dropped = new int[nDense]; memset(dropped, 0, nDense * sizeof(int)); dense.setDoubleParameter(3, largest); dense.setDoubleParameter(4, smallest); dense.setDoubleParameter(10, dropValue); dense.setIntegerParameter(20, 0); dense.setIntegerParameter(34, firstPositive); dense.setModel(model_); dense.factorizePart2(dropped); largest = dense.getDoubleParameter(3); smallest = dense.getDoubleParameter(4); integerParameters_[20] += dense.getIntegerParameter(20); for (iRow = firstDense_; iRow < numberRows_; iRow++) { int originalRow = permute_[iRow]; rowsDropped[originalRow] = dropped[iRow-firstDense_]; } delete [] dropped; } delete [] d; doubleParameters_[3] = largest; doubleParameters_[4] = smallest; return; } // Updates dense part (broken out for profiling) void ClpCholeskyBase::updateDense(longDouble * d, /*longDouble * work,*/ int * first) { for (int iRow = 0; iRow < firstDense_; iRow++) { CoinBigIndex start = first[iRow]; CoinBigIndex end = choleskyStart_[iRow+1]; if (start < end) { CoinBigIndex offset = indexStart_[iRow] - choleskyStart_[iRow]; if (clique_[iRow] < 2) { CoinWorkDouble dValue = d[iRow]; for (CoinBigIndex k = start; k < end; k++) { int kRow = choleskyRow_[k+offset]; assert(kRow >= firstDense_); CoinWorkDouble a_ik = sparseFactor_[k]; CoinWorkDouble value1 = dValue * a_ik; diagonal_[kRow] -= value1 * a_ik; CoinBigIndex base = choleskyStart_[kRow] - kRow - 1; for (CoinBigIndex j = k + 1; j < end; j++) { int jRow = choleskyRow_[j+offset]; CoinWorkDouble a_jk = sparseFactor_[j]; sparseFactor_[base+jRow] -= a_jk * value1; } } } else if (clique_[iRow] < 3) { // do as pair CoinWorkDouble dValue0 = d[iRow]; CoinWorkDouble dValue1 = d[iRow+1]; int offset1 = first[iRow+1] - start; // skip row iRow++; for (CoinBigIndex k = start; k < end; k++) { int kRow = choleskyRow_[k+offset]; assert(kRow >= firstDense_); CoinWorkDouble a_ik0 = sparseFactor_[k]; CoinWorkDouble value0 = dValue0 * a_ik0; CoinWorkDouble a_ik1 = sparseFactor_[k+offset1]; CoinWorkDouble value1 = dValue1 * a_ik1; diagonal_[kRow] -= value0 * a_ik0 + value1 * a_ik1; CoinBigIndex base = choleskyStart_[kRow] - kRow - 1; for (CoinBigIndex j = k + 1; j < end; j++) { int jRow = choleskyRow_[j+offset]; CoinWorkDouble a_jk0 = sparseFactor_[j]; CoinWorkDouble a_jk1 = sparseFactor_[j+offset1]; sparseFactor_[base+jRow] -= a_jk0 * value0 + a_jk1 * value1; } } #define MANY_REGISTERS #ifdef MANY_REGISTERS } else if (clique_[iRow] == 3) { #else } else { #endif // do as clique // maybe later get fancy on big cliques and do transpose copy // seems only worth going to 3 on Intel CoinWorkDouble dValue0 = d[iRow]; CoinWorkDouble dValue1 = d[iRow+1]; CoinWorkDouble dValue2 = d[iRow+2]; // get offsets and skip rows int offset1 = first[++iRow] - start; int offset2 = first[++iRow] - start; for (CoinBigIndex k = start; k < end; k++) { int kRow = choleskyRow_[k+offset]; assert(kRow >= firstDense_); CoinWorkDouble diagonalValue = diagonal_[kRow]; CoinWorkDouble a_ik0 = sparseFactor_[k]; CoinWorkDouble value0 = dValue0 * a_ik0; CoinWorkDouble a_ik1 = sparseFactor_[k+offset1]; CoinWorkDouble value1 = dValue1 * a_ik1; CoinWorkDouble a_ik2 = sparseFactor_[k+offset2]; CoinWorkDouble value2 = dValue2 * a_ik2; CoinBigIndex base = choleskyStart_[kRow] - kRow - 1; diagonal_[kRow] = diagonalValue - value0 * a_ik0 - value1 * a_ik1 - value2 * a_ik2; for (CoinBigIndex j = k + 1; j < end; j++) { int jRow = choleskyRow_[j+offset]; CoinWorkDouble a_jk0 = sparseFactor_[j]; CoinWorkDouble a_jk1 = sparseFactor_[j+offset1]; CoinWorkDouble a_jk2 = sparseFactor_[j+offset2]; sparseFactor_[base+jRow] -= a_jk0 * value0 + a_jk1 * value1 + a_jk2 * value2; } } #ifdef MANY_REGISTERS } else { // do as clique // maybe later get fancy on big cliques and do transpose copy // maybe only worth going to 3 on Intel (but may have hidden registers) CoinWorkDouble dValue0 = d[iRow]; CoinWorkDouble dValue1 = d[iRow+1]; CoinWorkDouble dValue2 = d[iRow+2]; CoinWorkDouble dValue3 = d[iRow+3]; // get offsets and skip rows int offset1 = first[++iRow] - start; int offset2 = first[++iRow] - start; int offset3 = first[++iRow] - start; for (CoinBigIndex k = start; k < end; k++) { int kRow = choleskyRow_[k+offset]; assert(kRow >= firstDense_); CoinWorkDouble diagonalValue = diagonal_[kRow]; CoinWorkDouble a_ik0 = sparseFactor_[k]; CoinWorkDouble value0 = dValue0 * a_ik0; CoinWorkDouble a_ik1 = sparseFactor_[k+offset1]; CoinWorkDouble value1 = dValue1 * a_ik1; CoinWorkDouble a_ik2 = sparseFactor_[k+offset2]; CoinWorkDouble value2 = dValue2 * a_ik2; CoinWorkDouble a_ik3 = sparseFactor_[k+offset3]; CoinWorkDouble value3 = dValue3 * a_ik3; CoinBigIndex base = choleskyStart_[kRow] - kRow - 1; diagonal_[kRow] = diagonalValue - (value0 * a_ik0 + value1 * a_ik1 + value2 * a_ik2 + value3 * a_ik3); for (CoinBigIndex j = k + 1; j < end; j++) { int jRow = choleskyRow_[j+offset]; CoinWorkDouble a_jk0 = sparseFactor_[j]; CoinWorkDouble a_jk1 = sparseFactor_[j+offset1]; CoinWorkDouble a_jk2 = sparseFactor_[j+offset2]; CoinWorkDouble a_jk3 = sparseFactor_[j+offset3]; sparseFactor_[base+jRow] -= a_jk0 * value0 + a_jk1 * value1 + a_jk2 * value2 + a_jk3 * value3; } } #endif } } } } /* Uses factorization to solve. */ void ClpCholeskyBase::solve (CoinWorkDouble * region) { if (!whichDense_) { solve(region, 3); } else { // dense columns int i; solve(region, 1); // do change; int numberDense = dense_->numberRows(); CoinWorkDouble * change = new CoinWorkDouble[numberDense]; for (i = 0; i < numberDense; i++) { const longDouble * a = denseColumn_ + i * numberRows_; CoinWorkDouble value = 0.0; for (int iRow = 0; iRow < numberRows_; iRow++) value += a[iRow] * region[iRow]; change[i] = value; } // solve dense_->solve(change); for (i = 0; i < numberDense; i++) { const longDouble * a = denseColumn_ + i * numberRows_; CoinWorkDouble value = change[i]; for (int iRow = 0; iRow < numberRows_; iRow++) region[iRow] -= value * a[iRow]; } delete [] change; // and finish off solve(region, 2); } } /* solve - 1 just first half, 2 just second half - 3 both. If 1 and 2 then diagonal has sqrt of inverse otherwise inverse */ void ClpCholeskyBase::solve(CoinWorkDouble * region, int type) { #ifdef CLP_DEBUG double * regionX = NULL; if (sizeof(CoinWorkDouble) != sizeof(double) && type == 3) { regionX = ClpCopyOfArray(region, numberRows_); } #endif CoinWorkDouble * work = reinterpret_cast (workDouble_); int i; CoinBigIndex j; for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; work[i] = region[iRow]; } switch (type) { case 1: for (i = 0; i < numberRows_; i++) { CoinWorkDouble value = work[i]; CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; work[iRow] -= sparseFactor_[j] * value; } } for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; region[iRow] = work[i] * diagonal_[i]; } break; case 2: for (i = numberRows_ - 1; i >= 0; i--) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i] * diagonal_[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; value -= sparseFactor_[j] * work[iRow]; } work[i] = value; int iRow = permute_[i]; region[iRow] = value; } break; case 3: for (i = 0; i < firstDense_; i++) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; work[iRow] -= sparseFactor_[j] * value; } } if (firstDense_ < numberRows_) { // do dense ClpCholeskyDense dense; // just borrow space int nDense = numberRows_ - firstDense_; dense.reserveSpace(this, nDense); dense.solve(work + firstDense_); for (i = numberRows_ - 1; i >= firstDense_; i--) { CoinWorkDouble value = work[i]; int iRow = permute_[i]; region[iRow] = value; } } for (i = firstDense_ - 1; i >= 0; i--) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i] * diagonal_[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; value -= sparseFactor_[j] * work[iRow]; } work[i] = value; int iRow = permute_[i]; region[iRow] = value; } break; } #ifdef CLP_DEBUG if (regionX) { longDouble * work = workDouble_; int i; CoinBigIndex j; double largestO = 0.0; for (i = 0; i < numberRows_; i++) { largestO = CoinMax(largestO, CoinAbs(regionX[i])); } for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; work[i] = regionX[iRow]; } for (i = 0; i < firstDense_; i++) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; work[iRow] -= sparseFactor_[j] * value; } } if (firstDense_ < numberRows_) { // do dense ClpCholeskyDense dense; // just borrow space int nDense = numberRows_ - firstDense_; dense.reserveSpace(this, nDense); dense.solve(work + firstDense_); for (i = numberRows_ - 1; i >= firstDense_; i--) { CoinWorkDouble value = work[i]; int iRow = permute_[i]; regionX[iRow] = value; } } for (i = firstDense_ - 1; i >= 0; i--) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i] * diagonal_[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; value -= sparseFactor_[j] * work[iRow]; } work[i] = value; int iRow = permute_[i]; regionX[iRow] = value; } double largest = 0.0; double largestV = 0.0; for (i = 0; i < numberRows_; i++) { largest = CoinMax(largest, CoinAbs(region[i] - regionX[i])); largestV = CoinMax(largestV, CoinAbs(region[i])); } printf("largest difference %g, largest %g, largest original %g\n", largest, largestV, largestO); delete [] regionX; } #endif } #if 0 //CLP_LONG_CHOLESKY /* Uses factorization to solve. */ void ClpCholeskyBase::solve (CoinWorkDouble * region) { assert (!whichDense_) ; CoinWorkDouble * work = reinterpret_cast (workDouble_); int i; CoinBigIndex j; for (i = 0; i < numberRows_; i++) { int iRow = permute_[i]; work[i] = region[iRow]; } for (i = 0; i < firstDense_; i++) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; work[iRow] -= sparseFactor_[j] * value; } } if (firstDense_ < numberRows_) { // do dense ClpCholeskyDense dense; // just borrow space int nDense = numberRows_ - firstDense_; dense.reserveSpace(this, nDense); dense.solve(work + firstDense_); for (i = numberRows_ - 1; i >= firstDense_; i--) { CoinWorkDouble value = work[i]; int iRow = permute_[i]; region[iRow] = value; } } for (i = firstDense_ - 1; i >= 0; i--) { CoinBigIndex offset = indexStart_[i] - choleskyStart_[i]; CoinWorkDouble value = work[i] * diagonal_[i]; for (j = choleskyStart_[i]; j < choleskyStart_[i+1]; j++) { int iRow = choleskyRow_[j+offset]; value -= sparseFactor_[j] * work[iRow]; } work[i] = value; int iRow = permute_[i]; region[iRow] = value; } } #endif Clp-1.15.10/src/ClpCholeskyTaucs.cpp0000644000076600007660000003772311510657452015610 0ustar coincoin/* $Id: ClpCholeskyTaucs.cpp 1665 2011-01-04 17:55:54Z lou $ */ #ifdef TAUCS_BARRIER // 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 "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpCholeskyTaucs.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyTaucs::ClpCholeskyTaucs () : ClpCholeskyBase(), matrix_(NULL), factorization_(NULL), sparseFactorT_(NULL), choleskyStartT_(NULL), choleskyRowT_(NULL), sizeFactorT_(0), rowCopyT_(NULL) { type_ = 13; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyTaucs::ClpCholeskyTaucs (const ClpCholeskyTaucs & rhs) : ClpCholeskyBase(rhs) { type_ = rhs.type_; // For Taucs stuff is done by malloc matrix_ = rhs.matrix_; sizeFactorT_ = rhs.sizeFactorT_; if (matrix_) { choleskyStartT_ = (int *) malloc((numberRows_ + 1) * sizeof(int)); CoinMemcpyN(rhs.choleskyStartT_, (numberRows_ + 1), choleskyStartT_); choleskyRowT_ = (int *) malloc(sizeFactorT_ * sizeof(int)); CoinMemcpyN(rhs.choleskyRowT_, sizeFactorT_, choleskyRowT_); sparseFactorT_ = (double *) malloc(sizeFactorT_ * sizeof(double)); CoinMemcpyN(rhs.sparseFactorT_, sizeFactorT_, sparseFactorT_); matrix_->colptr = choleskyStartT_; matrix_->rowind = choleskyRowT_; matrix_->values.d = sparseFactorT_; } else { sparseFactorT_ = NULL; choleskyStartT_ = NULL; choleskyRowT_ = NULL; } factorization_ = NULL, rowCopyT_ = rhs.rowCopyT_->clone(); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyTaucs::~ClpCholeskyTaucs () { taucs_ccs_free(matrix_); if (factorization_) taucs_supernodal_factor_free(factorization_); delete rowCopyT_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyTaucs & ClpCholeskyTaucs::operator=(const ClpCholeskyTaucs& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); taucs_ccs_free(matrix_); if (factorization_) taucs_supernodal_factor_free(factorization_); factorization_ = NULL; sizeFactorT_ = rhs.sizeFactorT_; matrix_ = rhs.matrix_; if (matrix_) { choleskyStartT_ = (int *) malloc((numberRows_ + 1) * sizeof(int)); CoinMemcpyN(rhs.choleskyStartT_, (numberRows_ + 1), choleskyStartT_); choleskyRowT_ = (int *) malloc(sizeFactorT_ * sizeof(int)); CoinMemcpyN(rhs.choleskyRowT_, sizeFactorT_, choleskyRowT_); sparseFactorT_ = (double *) malloc(sizeFactorT_ * sizeof(double)); CoinMemcpyN(rhs.sparseFactorT_, sizeFactorT_, sparseFactorT_); matrix_->colptr = choleskyStartT_; matrix_->rowind = choleskyRowT_; matrix_->values.d = sparseFactorT_; } else { sparseFactorT_ = NULL; choleskyStartT_ = NULL; choleskyRowT_ = NULL; } delete rowCopyT_; rowCopyT_ = rhs.rowCopyT_->clone(); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyTaucs::clone() const { return new ClpCholeskyTaucs(*this); } /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyTaucs::order(ClpInterior * model) { numberRows_ = model->numberRows(); rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopyT_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopyT_->getVectorStarts(); const int * rowLength = rowCopyT_->getVectorLengths(); const int * column = rowCopyT_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_]; CoinZeroN(used, numberRows_); int iRow; sizeFactorT_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in matrix_ = taucs_ccs_create(numberRows_, numberRows_, sizeFactorT_, TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER); if (!matrix_) return 1; // Space for starts choleskyStartT_ = matrix_->colptr; choleskyRowT_ = matrix_->rowind; sparseFactorT_ = matrix_->values.d; sizeFactorT_ = 0; which = choleskyRowT_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStartT_[iRow] = sizeFactorT_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStartT_[numberRows_] = sizeFactorT_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; int * perm, *invp; // There seem to be bugs in ordering if model too small if (numberRows_ > 10) taucs_ccs_order(matrix_, &perm, &invp, (const char *) "genmmd"); else taucs_ccs_order(matrix_, &perm, &invp, (const char *) "identity"); CoinMemcpyN(perm, numberRows_, permuteInverse_); free(perm); CoinMemcpyN(invp, numberRows_, permute_); free(invp); // need to permute taucs_ccs_matrix * permuted = taucs_ccs_permute_symmetrically(matrix_, permuteInverse_, permute_); // symbolic factorization_ = taucs_ccs_factor_llt_symbolic(permuted); taucs_ccs_free(permuted); return factorization_ ? 0 : 1; } /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyTaucs::symbolic() { return 0; } /* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyTaucs::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopyT_->getVectorStarts(); const int * rowLength = rowCopyT_->getVectorLengths(); const int * column = rowCopyT_->getIndices(); const double * elementByRow = rowCopyT_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = perturbation * perturbation; if (perturbation > 1.0) { //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; perturbation = sqrt(perturbation);; perturbation = 1.0; } for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactorT_ + choleskyStartT_[iRow]; int * which = choleskyRowT_ + choleskyStartT_[iRow]; int number = choleskyStartT_[iRow+1] - choleskyStartT_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } int j; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactorT_, sizeFactorT_); largest2 *= 1.0e-19; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStartT_[iRow]; double diagonal = sparseFactorT_[start]; if (diagonal > largest2) { sparseFactorT_[start] = diagonal + perturbation; } else { sparseFactorT_[start] = diagonal + perturbation; rowsDropped[iRow] = 2; numberDroppedBefore++; } } } taucs_supernodal_factor_free_numeric(factorization_); // need to permute taucs_ccs_matrix * permuted = taucs_ccs_permute_symmetrically(matrix_, permuteInverse_, permute_); int rCode = taucs_ccs_factor_llt_numeric(permuted, factorization_); taucs_ccs_free(permuted); if (rCode) printf("return code of %d from factor\n", rCode); delete [] work; choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 200) cleanCholesky = true; else cleanCholesky = false; /* How do I find out where 1.0e100's are in cholesky? */ if (cleanCholesky) { //drop fresh makes some formADAT easier int oldDropped = numberRowsDropped_; if (newDropped || numberRowsDropped_) { std::cout << "Rank " << numberRows_ - newDropped << " ( " << newDropped << " dropped)"; if (newDropped > oldDropped) std::cout << " ( " << newDropped - oldDropped << " dropped this time)"; std::cout << std::endl; newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = rowsDropped[i]; rowsDropped_[i] = dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(1 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = rowsDropped[i]; int oldDropped = rowsDropped_[i];; rowsDropped_[i] = dropped; if (dropped == 2) { assert (!oldDropped); //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } status_ = 0; return newDropped; } /* Uses factorization to solve. */ void ClpCholeskyTaucs::solve (double * region) { double * in = new double[numberRows_]; double * out = new double[numberRows_]; taucs_vec_permute(numberRows_, TAUCS_DOUBLE, region, in, permuteInverse_); int rCode = taucs_supernodal_solve_llt(factorization_, out, in); if (rCode) printf("return code of %d from solve\n", rCode); taucs_vec_permute(numberRows_, TAUCS_DOUBLE, out, region, permute_); delete [] out; delete [] in; } #endif Clp-1.15.10/src/ClpLinearObjective.cpp0000644000076600007660000002276611510657452016075 0ustar coincoin/* $Id: ClpLinearObjective.cpp 1665 2011-01-04 17:55:54Z lou $ */ // 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). #include "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpLinearObjective.hpp" #include "CoinHelperFunctions.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpLinearObjective::ClpLinearObjective () : ClpObjective() { type_ = 1; objective_ = NULL; numberColumns_ = 0; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpLinearObjective::ClpLinearObjective (const double * objective , int numberColumns) : ClpObjective() { type_ = 1; numberColumns_ = numberColumns; objective_ = CoinCopyOfArray(objective, numberColumns_, 0.0); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective & rhs) : ClpObjective(rhs) { numberColumns_ = rhs.numberColumns_; objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_); } /* Subset constructor. Duplicates are allowed and order is as given. */ ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective &rhs, int numberColumns, const int * whichColumn) : ClpObjective(rhs) { objective_ = NULL; numberColumns_ = 0; if (numberColumns > 0) { // check valid lists int numberBad = 0; int i; for (i = 0; i < numberColumns; i++) if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_) numberBad++; if (numberBad) throw CoinError("bad column list", "subset constructor", "ClpLinearObjective"); numberColumns_ = numberColumns; objective_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) objective_[i] = rhs.objective_[whichColumn[i]]; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpLinearObjective::~ClpLinearObjective () { delete [] objective_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpLinearObjective & ClpLinearObjective::operator=(const ClpLinearObjective& rhs) { if (this != &rhs) { ClpObjective::operator=(rhs); numberColumns_ = rhs.numberColumns_; delete [] objective_; objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_); } return *this; } // Returns gradient double * ClpLinearObjective::gradient(const ClpSimplex * /*model*/, const double * /*solution*/, double & offset, bool /*refresh*/, int /*includeLinear*/) { // not sure what to do about scaling //assert (!model); //assert (includeLinear==2); //otherwise need to return all zeros offset = 0.0; return objective_; } /* Returns reduced gradient.Returns an offset (to be added to current one). */ double ClpLinearObjective::reducedGradient(ClpSimplex * model, double * region, bool /*useFeasibleCosts*/) { int numberRows = model->numberRows(); //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 * cost = model->costRegion(); //assert (!useFeasibleCosts); const int * pivotVariable = model->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = cost[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector.setNumElements(number); int numberColumns = model->numberColumns(); // Btran basic costs double * work = workSpace->denseVector(); model->factorization()->updateColumnTranspose(workSpace, &arrayVector); ClpFillN(work, numberRows, 0.0); // now look at dual solution double * rowReducedCost = region + numberColumns; double * dual = rowReducedCost; double * rowCost = model->costRegion(0); for (iRow = 0; iRow < numberRows; iRow++) { dual[iRow] = array[iRow]; } double * dj = region; ClpDisjointCopyN(model->costRegion(1), 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 0.0; } /* Returns step length which gives minimum of objective for solution + theta * change vector up to maximum theta. arrays are numberColumns+numberRows */ double ClpLinearObjective::stepLength(ClpSimplex * model, const double * solution, const double * change, double maximumTheta, double & currentObj, double & predictedObj, double & thetaObj) { const double * cost = model->costRegion(); double delta = 0.0; int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); currentObj = 0.0; thetaObj = 0.0; for (int iColumn = 0; iColumn < numberColumns + numberRows; iColumn++) { delta += cost[iColumn] * change[iColumn]; currentObj += cost[iColumn] * solution[iColumn]; } thetaObj = currentObj + delta * maximumTheta; predictedObj = currentObj + delta * maximumTheta; if (delta < 0.0) { return maximumTheta; } else { printf("odd linear direction %g\n", delta); return 0.0; } } // Return objective value (without any ClpModel offset) (model may be NULL) double ClpLinearObjective::objectiveValue(const ClpSimplex * model, const double * solution) const { const double * cost = objective_; if (model && model->costRegion()) cost = model->costRegion(); double currentObj = 0.0; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { currentObj += cost[iColumn] * solution[iColumn]; } return currentObj; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpObjective * ClpLinearObjective::clone() const { return new ClpLinearObjective(*this); } /* Subset clone. Duplicates are allowed and order is as given. */ ClpObjective * ClpLinearObjective::subsetClone (int numberColumns, const int * whichColumns) const { return new ClpLinearObjective(*this, numberColumns, whichColumns); } // Resize objective void ClpLinearObjective::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { int i; double * newArray = new double[newNumberColumns]; if (objective_) CoinMemcpyN(objective_, CoinMin(newNumberColumns, numberColumns_), newArray); delete [] objective_; objective_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) objective_[i] = 0.0; numberColumns_ = newNumberColumns; } } // Delete columns in objective void ClpLinearObjective::deleteSome(int numberToDelete, const int * which) { if (objective_) { int i ; char * deleted = new char[numberColumns_]; int numberDeleted = 0; CoinZeroN(deleted, numberColumns_); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { numberDeleted++; deleted[j] = 1; } } int newNumberColumns = numberColumns_ - numberDeleted; double * newArray = new double[newNumberColumns]; int put = 0; for (i = 0; i < numberColumns_; i++) { if (!deleted[i]) { newArray[put++] = objective_[i]; } } delete [] objective_; objective_ = newArray; delete [] deleted; numberColumns_ = newNumberColumns; } } // Scale objective void ClpLinearObjective::reallyScale(const double * columnScale) { for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { objective_[iColumn] *= columnScale[iColumn]; } } Clp-1.15.10/src/AbcSimplex.hpp0000644000076600007660000013045412101105055014377 0ustar coincoin/* $Id: AbcSimplex.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef AbcSimplex_H #define AbcSimplex_H #include #include #include "ClpModel.hpp" #include "ClpMatrixBase.hpp" #include "CoinIndexedVector.hpp" #include "AbcCommon.hpp" class AbcSimplex; #include "ClpSolve.hpp" #include "CoinAbcCommon.hpp" class ClpSimplex; class AbcDualRowPivot; class AbcPrimalColumnPivot; class AbcSimplexFactorization; class AbcNonLinearCost; class OsiAbcSolverInterface; class CoinWarmStartBasis; class ClpDisasterHandler; class AbcSimplexProgress; class AbcMatrix; class AbcTolerancesEtc; /** This solves LPs using the simplex method It inherits from ClpModel and all its arrays are created at algorithm time. Originally I tried to work with model arrays but for simplicity of coding I changed to single arrays with structural variables then row variables. Some coding is still based on old style and needs cleaning up. For a description of algorithms: for dual see AbcSimplexDual.hpp and at top of AbcSimplexDual.cpp for primal see AbcSimplexPrimal.hpp and at top of AbcSimplexPrimal.cpp There is an algorithm data member. + for primal variations and - for dual variations */ #define PAN #if ABC_NORMAL_DEBUG>0 #define PRINT_PAN 1 #endif #define TRY_ABC_GUS #define HEAVY_PERTURBATION 57 #if ABC_PARALLEL==1 // Use pthreads #include #endif typedef struct { double result; //const CoinIndexedVector * constVector; // can get rid of //CoinIndexedVector * vectors[2]; // can get rid of int status; int stuff[4]; } CoinAbcThreadInfo; #include "ClpSimplex.hpp" class AbcSimplex : public ClpSimplex { friend void AbcSimplexUnitTest(const std::string & mpsDir); public: /** enums for status of various sorts. ClpModel order (and warmstart) is isFree = 0x00, basic = 0x01, atUpperBound = 0x02, atLowerBound = 0x03, isFixed means fixed at lower bound and out of basis */ enum Status { atLowerBound = 0x00, // so we can use bottom two bits to sort and swap signs atUpperBound = 0x01, isFree = 0x04, superBasic = 0x05, basic = 0x06, isFixed = 0x07 }; // For Dual enum FakeBound { noFake = 0x00, lowerFake = 0x01, upperFake = 0x02, bothFake = 0x03 }; /**@name Constructors and destructor and copy */ //@{ /// Default constructor AbcSimplex (bool emptyMessages = false ); /** Copy constructor. */ AbcSimplex(const AbcSimplex & rhs); /** Copy constructor from model. */ AbcSimplex(const ClpSimplex & rhs); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped Can optionally modify rhs to take into account variables NOT in list in this case duplicates are not allowed (also see getbackSolution) */ AbcSimplex (const ClpSimplex * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true, bool fixOthers = false); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped Can optionally modify rhs to take into account variables NOT in list in this case duplicates are not allowed (also see getbackSolution) */ AbcSimplex (const AbcSimplex * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true, bool fixOthers = false); /** This constructor modifies original AbcSimplex and stores original stuff in created AbcSimplex. It is only to be used in conjunction with originalModel */ AbcSimplex (AbcSimplex * wholeModel, int numberColumns, const int * whichColumns); /** This copies back stuff from miniModel and then deletes miniModel. Only to be used with mini constructor */ void originalModel(AbcSimplex * miniModel); /** This constructor copies from ClpSimplex */ AbcSimplex (const ClpSimplex * clpSimplex); /// Put back solution into ClpSimplex void putBackSolution(ClpSimplex * simplex); /** Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ //void setPersistenceFlag(int value); /// Save a copy of model with certain state - normally without cuts void makeBaseModel(); /// Switch off base model void deleteBaseModel(); /// See if we have base model inline AbcSimplex * baseModel() const { return abcBaseModel_; } /** Reset to base model (just size and arrays needed) If model NULL use internal copy */ void setToBaseModel(AbcSimplex * model = NULL); /// Assignment operator. This copies the data AbcSimplex & operator=(const AbcSimplex & rhs); /// Destructor ~AbcSimplex ( ); //@} /**@name Functions most useful to user */ //@{ /** Dual algorithm - see AbcSimplexDual.hpp for method. */ int dual(); int doAbcDual(); /** Primal algorithm - see AbcSimplexPrimal.hpp for method. */ int primal(int ifValuesPass); int doAbcPrimal(int ifValuesPass); /// Returns a basis (to be deleted by user) CoinWarmStartBasis * getBasis() const; /// Passes in factorization void setFactorization( AbcSimplexFactorization & factorization); /// Swaps factorization AbcSimplexFactorization * swapFactorization( AbcSimplexFactorization * factorization); /// Gets clean and emptyish factorization AbcSimplexFactorization * getEmptyFactorization(); /** Tightens primal bounds to make dual faster. Unless fixed or doTight>10, bounds are slightly looser than they could be. This is to make dual go faster and is probably not needed with a presolve. Returns non-zero if problem infeasible. Fudge for branch and bound - put bounds on columns of factor * largest value (at continuous) - should improve stability in branch and bound on infeasible branches (0.0 is off) */ int tightenPrimalBounds(); /// Sets row pivot choice algorithm in dual void setDualRowPivotAlgorithm(AbcDualRowPivot & choice); /// Sets column pivot choice algorithm in primal void setPrimalColumnPivotAlgorithm(AbcPrimalColumnPivot & choice); //@} /// If user left factorization frequency then compute void defaultFactorizationFrequency(); //@} /**@name most useful gets and sets */ //@{ /// factorization inline AbcSimplexFactorization * factorization() const { return reinterpret_cast(abcFactorization_); } #ifdef EARLY_FACTORIZE /// Early factorization inline AbcSimplexFactorization * earlyFactorization() const { return reinterpret_cast(abcEarlyFactorization_); } #endif /// Factorization frequency int factorizationFrequency() const; void setFactorizationFrequency(int value); /// Maximum rows inline int maximumAbcNumberRows() const { return maximumAbcNumberRows_;} /// Maximum Total inline int maximumNumberTotal() const { return maximumNumberTotal_;} inline int maximumTotal() const { return maximumNumberTotal_;} /// Return true if the objective limit test can be relied upon bool isObjectiveLimitTestValid() const ; /// Number of variables (includes spare rows) inline int numberTotal() const { return numberTotal_;} /// Number of variables without fixed to zero (includes spare rows) inline int numberTotalWithoutFixed() const { return numberTotalWithoutFixed_;} /// Useful arrays (0,1,2,3,4,5,6,7) inline CoinPartitionedVector * usefulArray(int index) { return & usefulArray_[index]; } inline CoinPartitionedVector * usefulArray(int index) const { return const_cast(&usefulArray_[index]); } //@} /******************** End of most useful part **************/ /**@name Functions less likely to be useful to casual user */ //@{ /** Given an existing factorization computes and checks primal and dual solutions. Uses current problem arrays for bounds. Returns feasibility states */ int getSolution (); /// Sets objectiveValue_ from rawObjectiveValue_ void setClpSimplexObjectiveValue(); /** Sets dual values pass djs using unscaled duals type 1 - values pass type 2 - just use as infeasibility weights type 3 - as 2 but crash */ void setupDualValuesPass(const double * fakeDuals, const double * fakePrimals, int type); /// Gets objective value with all offsets but as for minimization inline double minimizationObjectiveValue() const { return objectiveValue_-dblParam_[ClpObjOffset];} /// Current dualTolerance (will end up as dualTolerance_) inline double currentDualTolerance() const { return currentDualTolerance_;} inline void setCurrentDualTolerance(double value) { currentDualTolerance_ = value; } /// Return pointer to details of costs inline AbcNonLinearCost * abcNonLinearCost() const { return abcNonLinearCost_; } /// Perturbation (fixed) - is just scaled random numbers double * perturbationSaved() const { return perturbationSaved_;} /// Acceptable pivot for this iteration inline double acceptablePivot() const { return acceptablePivot_;} /// Set to 1 if no free or super basic inline int ordinaryVariables() const { return ordinaryVariables_;} /// Number of ordinary (lo/up) in tableau row inline int numberOrdinary() const { return numberOrdinary_;} /// Set number of ordinary (lo/up) in tableau row inline void setNumberOrdinary(int number) { numberOrdinary_=number;} /// Current dualBound (will end up as dualBound_) inline double currentDualBound() const { return currentDualBound_;} /// dual row pivot choice inline AbcDualRowPivot * dualRowPivot() const { return abcDualRowPivot_; } /// primal column pivot choice inline AbcPrimalColumnPivot * primalColumnPivot() const { return abcPrimalColumnPivot_; } /// Abc Matrix inline AbcMatrix * abcMatrix() const { return abcMatrix_; } /** Factorizes using current basis. solveType - 1 iterating, 0 initial, -1 external If 10 added then in primal values pass Return codes are as from AbcSimplexFactorization unless initial factorization when total number of singularities is returned. Special case is numberRows_+1 -> all slack basis. if initial should be before permute in pivotVariable may be same as toExternal */ int internalFactorize(int solveType); /** Permutes in from ClpModel data - assumes scale factors done and AbcMatrix exists but is in original order (including slacks) For now just add basicArray at end == But could partition into normal (i.e. reasonable lower/upper) abnormal - free, odd bounds fixed == sets a valid pivotVariable Slacks always shifted by offset Fixed variables always shifted by offset Recode to allow row objective so can use pi from idiot etc */ void permuteIn(); /// deals with new basis and puts in abcPivotVariable_ void permuteBasis(); /// Permutes out - bit settings same as stateOfProblem void permuteOut(int whatsWanted); /// Save data ClpDataSave saveData() ; /// Restore data void restoreData(ClpDataSave saved); /// Clean up status void cleanStatus(); /** Computes duals from scratch. If givenDjs then allows for nonzero basic djs. Returns number of refinements */ int computeDuals(double * givenDjs, CoinIndexedVector * array1, CoinIndexedVector * array2); /// Computes primals from scratch. Returns number of refinements int computePrimals (CoinIndexedVector * array1, CoinIndexedVector * array2); /// Computes nonbasic cost and total cost void computeObjective (); /// set multiple sequence in void setMultipleSequenceIn(int sequenceIn[4]); /** Unpacks one column of the matrix into indexed array Uses sequenceIn_ */ inline void unpack(CoinIndexedVector & rowArray) const {unpack(rowArray,sequenceIn_);} /** Unpacks one column of the matrix into indexed array */ void unpack(CoinIndexedVector & rowArray, int sequence) const; /** This does basis housekeeping and does values for in/out variables. Can also decide to re-factorize */ int housekeeping(/*double objectiveChange*/); /** This sets largest infeasibility and most infeasible and sum and number of infeasibilities (Primal) */ void checkPrimalSolution(bool justBasic); /** This sets largest infeasibility and most infeasible and sum and number of infeasibilities (Dual) */ void checkDualSolution(); /** This sets largest infeasibility and most infeasible and sum and number of infeasibilities AND sumFakeInfeasibilites_ (Dual) */ void checkDualSolutionPlusFake(); /** This sets sum and number of infeasibilities (Dual and Primal) */ void checkBothSolutions(); /// Computes solutions - 1 do duals, 2 do primals, 3 both (returns number of refinements) int gutsOfSolution(int type); /// Computes solutions - 1 do duals, 2 do primals, 3 both (returns number of refinements) int gutsOfPrimalSolution(int type); /// Saves good status etc void saveGoodStatus(); /// Restores previous good status and says trouble void restoreGoodStatus(int type); #define rowUseScale_ scaleFromExternal_ #define inverseRowUseScale_ scaleToExternal_ /// After modifying first copy refreshes second copy and marks as updated void refreshCosts(); void refreshLower(unsigned int type=~(ROW_LOWER_SAME|COLUMN_UPPER_SAME)); void refreshUpper(unsigned int type=~(ROW_LOWER_SAME|COLUMN_LOWER_SAME)); /// Sets up all extra pointers void setupPointers(int maxRows,int maxColumns); /// Copies all saved versions to working versions and may do something for perturbation void copyFromSaved(int type=31); /// fills in perturbationSaved_ from start with 0.5+random void fillPerturbation(int start, int number); /// For debug - prints summary of arrays which are out of kilter void checkArrays(int ignoreEmpty=0) const; /// For debug - summarizes dj situation (1 recomputes duals first, 2 checks duals as well) void checkDjs(int type=1) const; /// For debug - checks solutionBasic void checkSolutionBasic() const; /// For debug - moves solution back to external and computes stuff (always checks djs) void checkMoveBack(bool checkDuals); public: /** For advanced use. When doing iterative solves things can get nasty so on values pass if incoming solution has largest infeasibility < incomingInfeasibility throw out variables from basis until largest infeasibility < allowedInfeasibility or incoming largest infeasibility. If allowedInfeasibility>= incomingInfeasibility this is always possible altough you may end up with an all slack basis. Defaults are 1.0,10.0 */ void setValuesPassAction(double incomingInfeasibility, double allowedInfeasibility); /** Get a clean factorization - i.e. throw out singularities may do more later */ int cleanFactorization(int ifValuesPass); /// Move status and solution to ClpSimplex void moveStatusToClp(ClpSimplex * clpModel); /// Move status and solution from ClpSimplex void moveStatusFromClp(ClpSimplex * clpModel); //@} /**@name most useful gets and sets */ //@{ public: /// Objective value inline double clpObjectiveValue() const { return (objectiveValue_+objectiveOffset_-bestPossibleImprovement_)*optimizationDirection_ - dblParam_[ClpObjOffset]; } /** Basic variables pivoting on which rows may be same as toExternal but may be as at invert */ inline int * pivotVariable() const { return abcPivotVariable_; } /// State of problem inline int stateOfProblem() const { return stateOfProblem_;} /// State of problem inline void setStateOfProblem(int value) { stateOfProblem_=value;} /// Points from external to internal //inline int * fromExternal() const //{ return fromExternal_;} /// Points from internal to external //inline int * toExternal() const //{return toExternal_;} /** Scale from primal external to internal (in external order) Or other way for dual */ inline double * scaleFromExternal() const {return scaleFromExternal_;} /** Scale from primal internal to external (in external order) Or other way for dual */ inline double * scaleToExternal() const {return scaleToExternal_;} /// corresponds to rowScale etc inline double * rowScale2() const {return rowUseScale_;} inline double * inverseRowScale2() const {return inverseRowUseScale_;} inline double * inverseColumnScale2() const {return inverseColumnUseScale_;} inline double * columnScale2() const {return columnUseScale_;} inline int arrayForDualColumn() const {return arrayForDualColumn_;} /// upper theta from dual column inline double upperTheta() const {return upperTheta_;} inline int arrayForReplaceColumn() const { return arrayForReplaceColumn_;} inline int arrayForFlipBounds() const { return arrayForFlipBounds_;} inline int arrayForFlipRhs() const { return arrayForFlipRhs_;} inline int arrayForBtran() const { return arrayForBtran_;} inline int arrayForFtran() const { return arrayForFtran_;} inline int arrayForTableauRow() const { return arrayForTableauRow_;} /// value of incoming variable (in Dual) double valueIncomingDual() const; /// Get pointer to array[getNumCols()] of primal solution vector const double * getColSolution() const; /// Get pointer to array[getNumRows()] of dual prices const double * getRowPrice() const; /// Get a pointer to array[getNumCols()] of reduced costs const double * getReducedCost() const; /** Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector */ const double * getRowActivity() const; //@} /**@name protected methods */ //@{ /** May change basis and then returns number changed. Computation of solutions may be overriden by given pi and solution */ int gutsOfSolution ( double * givenDuals, const double * givenPrimals, bool valuesPass = false); /// Does most of deletion for arrays etc(0 just null arrays, 1 delete first) void gutsOfDelete(int type); /// Does most of copying void gutsOfCopy(const AbcSimplex & rhs); /// Initializes arrays void gutsOfInitialize(int numberRows,int numberColumns,bool doMore); /// resizes arrays void gutsOfResize(int numberRows,int numberColumns); /** Translates ClpModel to AbcSimplex See DO_ bits in stateOfProblem_ for type e.g. DO_BASIS_AND_ORDER */ void translate(int type); /// Moves basic stuff to basic area void moveToBasic(int which=15); //@} public: /**@name public methods */ //@{ /// Return region inline double * solutionRegion() const { return abcSolution_; } inline double * djRegion() const { return abcDj_; } inline double * lowerRegion() const { return abcLower_; } inline double * upperRegion() const { return abcUpper_; } inline double * costRegion() const { return abcCost_; } /// Return region inline double * solutionRegion(int which) const { return abcSolution_+which*maximumAbcNumberRows_; } inline double * djRegion(int which) const { return abcDj_+which*maximumAbcNumberRows_; } inline double * lowerRegion(int which) const { return abcLower_+which*maximumAbcNumberRows_; } inline double * upperRegion(int which) const { return abcUpper_+which*maximumAbcNumberRows_; } inline double * costRegion(int which) const { return abcCost_+which*maximumAbcNumberRows_; } /// Return region inline double * solutionBasic() const { return solutionBasic_; } inline double * djBasic() const { return djBasic_; } inline double * lowerBasic() const { return lowerBasic_; } inline double * upperBasic() const { return upperBasic_; } inline double * costBasic() const { return costBasic_; } /// Perturbation inline double * abcPerturbation() const { return abcPerturbation_;} /// Fake djs inline double * fakeDjs() const { return djSaved_;} inline unsigned char * internalStatus() const { return internalStatus_;} inline AbcSimplex::Status getInternalStatus(int sequence) const { return static_cast (internalStatus_[sequence] & 7); } inline AbcSimplex::Status getInternalColumnStatus(int sequence) const { return static_cast (internalStatus_[sequence+maximumAbcNumberRows_] & 7); } inline void setInternalStatus(int sequence, AbcSimplex::Status newstatus) { unsigned char & st_byte = internalStatus_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | newstatus); } inline void setInternalColumnStatus(int sequence, AbcSimplex::Status newstatus) { unsigned char & st_byte = internalStatus_[sequence+maximumAbcNumberRows_]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | newstatus); } /** Normally the first factorization does sparse coding because the factorization could be singular. This allows initial dense factorization when it is known to be safe */ void setInitialDenseFactorization(bool onOff); bool initialDenseFactorization() const; /** Return sequence In or Out */ inline int sequenceIn() const { return sequenceIn_; } inline int sequenceOut() const { return sequenceOut_; } /** Set sequenceIn or Out */ inline void setSequenceIn(int sequence) { sequenceIn_ = sequence; } inline void setSequenceOut(int sequence) { sequenceOut_ = sequence; } #if 0 /** Return sequenceInternal In or Out */ inline int sequenceInternalIn() const { return sequenceInternalIn_; } inline int sequenceInternalOut() const { return sequenceInternalOut_; } /** Set sequenceInternalIn or Out */ inline void setSequenceInternalIn(int sequence) { sequenceInternalIn_ = sequence; } inline void setSequenceInternalOut(int sequence) { sequenceInternalOut_ = sequence; } #endif /// Returns 1 if sequence indicates column inline int isColumn(int sequence) const { return sequence >= maximumAbcNumberRows_ ? 1 : 0; } /// Returns sequence number within section inline int sequenceWithin(int sequence) const { return sequence < maximumAbcNumberRows_ ? sequence : sequence - maximumAbcNumberRows_; } /// Current/last pivot row (set after END of choosing pivot row in dual) inline int lastPivotRow() const { return lastPivotRow_;} /// First Free_ inline int firstFree() const { return firstFree_;} /// Last firstFree_ inline int lastFirstFree() const { return lastFirstFree_;} /// Free chosen vector inline int freeSequenceIn() const { return freeSequenceIn_;} /// Acceptable pivot for this iteration inline double currentAcceptablePivot() const { return currentAcceptablePivot_;} #ifdef PAN /** Returns 1 if fake superbasic 0 if free or true superbasic -1 if was fake but has cleaned itself up (sets status) -2 if wasn't fake */ inline int fakeSuperBasic(int iSequence) { if ((internalStatus_[iSequence]&7)==4) return 0; // free if ((internalStatus_[iSequence]&7)!=5) return -2; double value=abcSolution_[iSequence]; if (value=-currentDualTolerance_) { setInternalStatus(iSequence,atLowerBound); #if PRINT_PAN>1 printf("Pansetting %d to lb\n",iSequence); #endif return -1; } else { return 1; } } else if (value>abcUpper_[iSequence]-primalTolerance_) { if (abcDj_[iSequence]<=currentDualTolerance_) { setInternalStatus(iSequence,atUpperBound); #if PRINT_PAN>1 printf("Pansetting %d to ub\n",iSequence); #endif return -1; } else { return 1; } } else { return 0; } } #endif /// Return row or column values inline double solution(int sequence) { return abcSolution_[sequence]; } /// Return address of row or column values inline double & solutionAddress(int sequence) { return abcSolution_[sequence]; } inline double reducedCost(int sequence) { return abcDj_[sequence]; } inline double & reducedCostAddress(int sequence) { return abcDj_[sequence]; } inline double lower(int sequence) { return abcLower_[sequence]; } /// Return address of row or column lower bound inline double & lowerAddress(int sequence) { return abcLower_[sequence]; } inline double upper(int sequence) { return abcUpper_[sequence]; } /// Return address of row or column upper bound inline double & upperAddress(int sequence) { return abcUpper_[sequence]; } inline double cost(int sequence) { return abcCost_[sequence]; } /// Return address of row or column cost inline double & costAddress(int sequence) { return abcCost_[sequence]; } /// Return original lower bound inline double originalLower(int iSequence) const { if (iSequence < numberColumns_) return columnLower_[iSequence]; else return rowLower_[iSequence-numberColumns_]; } /// Return original lower bound inline double originalUpper(int iSequence) const { if (iSequence < numberColumns_) return columnUpper_[iSequence]; else return rowUpper_[iSequence-numberColumns_]; } /// For dealing with all issues of cycling etc inline AbcSimplexProgress * abcProgress() { return &abcProgress_;} public: /** Clears an array and says available (-1 does all) when no possibility of going parallel */ inline void clearArraysPublic(int which) { clearArrays(which);} /** Returns first available empty array (and sets flag) when no possibility of going parallel */ inline int getAvailableArrayPublic() const { return getAvailableArray();} #if ABC_PARALLEL /// get parallel mode inline int parallelMode() const { return parallelMode_;} /// set parallel mode inline void setParallelMode(int value) { parallelMode_=value;} /// Number of cpus inline int numberCpus() const { return parallelMode_+1;} #if ABC_PARALLEL==1 /// set stop start inline void setStopStart(int value) { stopStart_=value;} #endif #endif //protected: /// Clears an array and says available (-1 does all) void clearArrays(int which); /// Clears an array and says available void clearArrays(CoinPartitionedVector * which); /// Returns first available empty array (and sets flag) int getAvailableArray() const; /// Say array going to be used inline void setUsedArray(int which) const {int check=1<(st_byte & ~24); st_byte = static_cast(st_byte | (fakeBound << 3)); } inline FakeBound getFakeBound(int sequence) const { return static_cast ((internalStatus_[sequence] >> 3) & 3); } bool atFakeBound(int sequence) const; inline void setPivoted( int sequence) { internalStatus_[sequence] = static_cast(internalStatus_[sequence] | 32); } inline void clearPivoted( int sequence) { internalStatus_[sequence] = static_cast(internalStatus_[sequence] & ~32); } inline bool pivoted(int sequence) const { return (((internalStatus_[sequence] >> 5) & 1) != 0); } public: /// Swaps two variables void swap(int pivotRow,int nonBasicPosition); /// To flag a variable void setFlagged( int sequence); inline void clearFlagged( int sequence) { internalStatus_[sequence] = static_cast(internalStatus_[sequence] & ~64); } inline bool flagged(int sequence) const { return ((internalStatus_[sequence] & 64) != 0); } protected: /// To say row active in primal pivot row choice inline void setActive( int iRow) { internalStatus_[iRow] = static_cast(internalStatus_[iRow] | 128); } inline void clearActive( int iRow) { internalStatus_[iRow] = static_cast(internalStatus_[iRow] & ~128); } inline bool active(int iRow) const { return ((internalStatus_[iRow] & 128) != 0); } public: /** Set up status array (can be used by OsiAbc). Also can be used to set up all slack basis */ void createStatus() ; /// Does sort of crash void crash(int type); /** Puts more stuff in basis 1 bit set - do even if basis exists 2 bit set - don't bother staying triangular */ void putStuffInBasis(int type); /** Sets up all slack basis and resets solution to as it was after initial load or readMps */ void allSlackBasis(); /// For debug - check pivotVariable consistent void checkConsistentPivots() const; /// Print stuff void printStuff() const; /// Common bits of coding for dual and primal int startup(int ifValuesPass); /// Raw objective value (so always minimize in primal) inline double rawObjectiveValue() const { return objectiveValue_; } /// Compute objective value from solution and put in objectiveValue_ void computeObjectiveValue(bool useWorkingSolution = false); /// Compute minimization objective value from internal solution without perturbation double computeInternalObjectiveValue(); /// Move status and solution across void moveInfo(const AbcSimplex & rhs, bool justStatus = false); #define NUMBER_THREADS 3 #if ABC_PARALLEL==1 // For waking up thread inline pthread_mutex_t * mutexPointer(int which,int thread=0) { return mutex_+which+3*thread;} inline pthread_barrier_t * barrierPointer() { return &barrier_;} inline int whichLocked(int thread=0) const { return locked_[thread];} inline CoinAbcThreadInfo * threadInfoPointer(int thread=0) { return threadInfo_+thread;} void startParallelStuff(int type); int stopParallelStuff(int type); /// so thread can find out which one it is int whichThread() const; #elif ABC_PARALLEL==2 //inline CoinAbcThreadInfo * threadInfoPointer(int thread=0) //{ return threadInfo_+thread;} #endif //@} //------------------------------------------------------------------------- /**@name Changing bounds on variables and constraints */ //@{ /** Set an objective function coefficient */ void setObjectiveCoefficient( int elementIndex, double elementValue ); /** Set an objective function coefficient */ inline void setObjCoeff( int elementIndex, double elementValue ) { setObjectiveCoefficient( elementIndex, elementValue); } /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ void setColumnLower( int elementIndex, double elementValue ); /** Set a single column upper bound
Use DBL_MAX for infinity. */ void setColumnUpper( int elementIndex, double elementValue ); /** Set a single column lower and upper bound */ void setColumnBounds( 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 */ void setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ inline void setColLower( int elementIndex, double elementValue ) { setColumnLower(elementIndex, elementValue); } /** Set a single column upper bound
Use DBL_MAX for infinity. */ inline void setColUpper( int elementIndex, double elementValue ) { setColumnUpper(elementIndex, elementValue); } /** Set a single column lower and upper bound */ inline void setColBounds( int elementIndex, double newlower, double newupper ) { setColumnBounds(elementIndex, newlower, newupper); } /** Set the bounds on a number of columns simultaneously
@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 */ inline void setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { setColumnSetBounds(indexFirst, indexLast, boundList); } /** Set a single row lower bound
Use -DBL_MAX for -infinity. */ void setRowLower( int elementIndex, double elementValue ); /** Set a single row upper bound
Use DBL_MAX for infinity. */ void setRowUpper( int elementIndex, double elementValue ) ; /** Set a single row lower and upper bound */ void setRowBounds( int elementIndex, double lower, double upper ) ; /** Set the bounds on a number of rows simultaneously
@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 */ void setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /// Resizes rim part of model void resize (int newNumberRows, int newNumberColumns); //@} ////////////////// data ////////////////// protected: /**@name data. Many arrays have a row part and a column part. There is a single array with both - columns then rows and then normally two arrays pointing to rows and columns. The single array is the owner of memory */ //@{ /// Sum of nonbasic costs double sumNonBasicCosts_; /// Sum of costs (raw objective value) double rawObjectiveValue_; /// Objective offset (from offset_) double objectiveOffset_; /** Perturbation factor If <0.0 then virtual if 0.0 none if >0.0 use this as factor */ double perturbationFactor_; /// Current dualTolerance (will end up as dualTolerance_) double currentDualTolerance_; /// Current dualBound (will end up as dualBound_) double currentDualBound_; /// Largest gap double largestGap_; /// Last dual bound double lastDualBound_; /// Sum of infeasibilities when using fake perturbation tolerance double sumFakeInfeasibilities_; /// Last primal error double lastPrimalError_; /// Last dual error double lastDualError_; /// Acceptable pivot for this iteration double currentAcceptablePivot_; /// Movement of variable double movement_; /// Objective change double objectiveChange_; /// Btran alpha double btranAlpha_; /// FT alpha #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha_; /// Minimum theta movement double minimumThetaMovement_; /// Initial sum of infeasibilities double initialSumInfeasibilities_; public: /// Where we are in iteration int stateOfIteration_; protected: /// Last firstFree_ int lastFirstFree_; /// Free chosen vector int freeSequenceIn_; /// Maximum number rows int maximumAbcNumberRows_; /// Maximum number columns int maximumAbcNumberColumns_; /// Maximum numberTotal int maximumNumberTotal_; /// Current number of variables flagged int numberFlagged_; /// Iteration at which to do relaxed dualColumn int normalDualColumnIteration_; /** State of dual waffle -2 - in initial large tolerance phase -1 - in medium tolerance phase n - in correct tolerance phase and thought optimal n times */ int stateDualColumn_; /* May want to put some arrays into struct Two arrays point to/from external Order is basic,unused basic, at lower, at upper, superbasic, free, fixed with starts */ /// Number of variables (includes spare rows) int numberTotal_; /// Number of variables without fixed to zero (includes spare rows) int numberTotalWithoutFixed_; /// Start of variables at lower bound with no upper #define startAtLowerNoOther_ maximumAbcNumberRows_ /// Start of variables at lower bound with upper int startAtLowerOther_; /// Start of variables at upper bound with no lower int startAtUpperNoOther_; /// Start of variables at upper bound with lower int startAtUpperOther_; /// Start of superBasic, free or awkward bounds variables int startOther_; /// Start of fixed variables int startFixed_; #ifdef EARLY_FACTORIZE /// Number of iterations to try factorizing early int numberEarly_; #endif /** State of problem State of external arrays 2048 - status OK 4096 - row primal solution OK 8192 - row dual solution OK 16384 - column primal solution OK 32768 - column dual solution OK 65536 - Everything not going smoothly (when smooth we forget about tiny bad djs) 131072 - when increasing rows add a bit 262144 - scale matrix and create new one 524288 - do basis and order 1048576 - just status (and check if order needed) 2097152 - just solution 4194304 - just redo bounds (and offset) Bottom bits say if usefulArray in use */ #define ALL_STATUS_OK 2048 #define ROW_PRIMAL_OK 4096 #define ROW_DUAL_OK 8192 #define COLUMN_PRIMAL_OK 16384 #define COLUMN_DUAL_OK 32768 #define PESSIMISTIC 65536 #define ADD_A_BIT 131072 #define DO_SCALE_AND_MATRIX 262144 #define DO_BASIS_AND_ORDER 524288 #define DO_STATUS 1048576 #define DO_SOLUTION 2097152 #define DO_JUST_BOUNDS 0x400000 #define NEED_BASIS_SORT 0x800000 #define FAKE_SUPERBASIC 0x1000000 #define VALUES_PASS 0x2000000 #define VALUES_PASS2 0x4000000 mutable int stateOfProblem_; #if ABC_PARALLEL public: /// parallel mode int parallelMode_; protected: #endif /// Number of ordinary (lo/up) in tableau row int numberOrdinary_; /// Set to 1 if no free or super basic int ordinaryVariables_; /// Number of free nonbasic variables int numberFreeNonBasic_; /// Last time cleaned up int lastCleaned_; /// Current/last pivot row (set after END of choosing pivot row in dual) int lastPivotRow_; /// Nonzero (probably 10) if swapped algorithms int swappedAlgorithm_; /// Initial number of infeasibilities int initialNumberInfeasibilities_; /// Points from external to internal //int * fromExternal_; /// Points from internal to external //int * toExternal_; /** Scale from primal external to internal (in external order) Or other way for dual */ double * scaleFromExternal_; /** Scale from primal internal to external (in external order) Or other way for dual */ double * scaleToExternal_; /// use this instead of columnScale double * columnUseScale_; /// use this instead of inverseColumnScale double * inverseColumnUseScale_; /** Primal offset (in external order) So internal value is (external-offset)*scaleFromExternal */ double * offset_; /// Offset for accumulated offsets*matrix double * offsetRhs_; /// Useful array of numberTotal length double * tempArray_; /** Working status ? may be signed ? link pi_ to an indexed array? may have saved from last factorization at end */ unsigned char * internalStatus_; /// Saved status unsigned char * internalStatusSaved_; /** Perturbation (fixed) - is just scaled random numbers If perturbationFactor_<0 then virtual perturbation */ double * abcPerturbation_; /// saved perturbation double * perturbationSaved_; /// basic perturbation double * perturbationBasic_; /// Working matrix AbcMatrix * abcMatrix_; /** Working scaled copy of lower bounds has original scaled copy at end */ double * abcLower_; /** Working scaled copy of upper bounds has original scaled copy at end */ double * abcUpper_; /** Working scaled copy of objective ? where perturbed copy or can we always work with perturbed copy (in B&B) if we adjust increments/cutoffs ? should we save a fixed perturbation offset array has original scaled copy at end */ double * abcCost_; /** Working scaled primal solution may have saved from last factorization at end */ double * abcSolution_; /** Working scaled dual solution may have saved from last factorization at end */ double * abcDj_; /// Saved scaled copy of lower bounds double * lowerSaved_; /// Saved scaled copy of upper bounds double * upperSaved_; /// Saved scaled copy of objective double * costSaved_; /// Saved scaled primal solution double * solutionSaved_; /// Saved scaled dual solution double * djSaved_; /// Working scaled copy of basic lower bounds double * lowerBasic_; /// Working scaled copy of basic upper bounds double * upperBasic_; /// Working scaled copy of basic objective double * costBasic_; /// Working scaled basic primal solution double * solutionBasic_; /// Working scaled basic dual solution (want it to be zero) double * djBasic_; /// dual row pivot choice AbcDualRowPivot * abcDualRowPivot_; /// primal column pivot choice AbcPrimalColumnPivot * abcPrimalColumnPivot_; /** Basic variables pivoting on which rows followed by atLo/atUp then free/superbasic then fixed */ int * abcPivotVariable_; /// Reverse abcPivotVariable_ for moving around int * reversePivotVariable_; /// factorization AbcSimplexFactorization * abcFactorization_; #ifdef EARLY_FACTORIZE /// Alternative factorization AbcSimplexFactorization * abcEarlyFactorization_; #endif #ifdef TEMPORARY_FACTORIZATION /// Alternative factorization AbcSimplexFactorization * abcOtherFactorization_; #endif /// Saved version of solution //double * savedSolution_; /// A copy of model with certain state - normally without cuts AbcSimplex * abcBaseModel_; /// A copy of model as ClpSimplex with certain state ClpSimplex * clpModel_; /** Very wasteful way of dealing with infeasibilities in primal. However it will allow non-linearities and use of dual analysis. If it doesn't work it can easily be replaced. */ AbcNonLinearCost * abcNonLinearCost_; /// Useful arrays (all of row+column+2 length) /* has secondary offset and counts so row goes first then column Probably back to CoinPartitionedVector as AbcMatrix has slacks also says if in use - so we can just get next available one */ #define ABC_NUMBER_USEFUL 8 mutable CoinPartitionedVector usefulArray_[ABC_NUMBER_USEFUL]; /// For dealing with all issues of cycling etc AbcSimplexProgress abcProgress_; /// For saving stuff at beginning ClpDataSave saveData_; /// upper theta from dual column double upperTheta_; /// Multiple sequence in int multipleSequenceIn_[4]; public: int arrayForDualColumn_; int arrayForReplaceColumn_; int arrayForFlipBounds_; //2 int arrayForFlipRhs_; // if sequential can re-use int arrayForBtran_; // 0 int arrayForFtran_; // 1 int arrayForTableauRow_; //3 protected: int numberFlipped_; int numberDisasters_; //int nextCleanNonBasicIteration_; #if ABC_PARALLEL==1 // For waking up thread pthread_mutex_t mutex_[3*NUMBER_THREADS]; pthread_barrier_t barrier_; CoinAbcThreadInfo threadInfo_[NUMBER_THREADS]; pthread_t abcThread_[NUMBER_THREADS]; int locked_[NUMBER_THREADS]; int stopStart_; #elif ABC_PARALLEL==2 //CoinAbcThreadInfo threadInfo_[NUMBER_THREADS]; #endif //@} }; //############################################################################# /** A function that tests the methods in the AbcSimplex class. The only reason for it not to be a member method is that this way it doesn't have to be compiled into the library. And that's a gain, because the library should be compiled with optimization on, but this method should be compiled with debugging. It also does some testing of AbcSimplexFactorization class */ void AbcSimplexUnitTest(const std::string & mpsDir); #endif Clp-1.15.10/src/ClpQuadraticObjective.hpp0000644000076600007660000001267211510657452016600 0ustar coincoin/* $Id: ClpQuadraticObjective.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpQuadraticObjective_H #define ClpQuadraticObjective_H #include "ClpObjective.hpp" #include "CoinPackedMatrix.hpp" //############################################################################# /** Quadratic Objective Class */ class ClpQuadraticObjective : public ClpObjective { public: ///@name Stuff //@{ /** Returns gradient. If Quadratic 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); //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpQuadraticObjective(); /// Constructor from objective ClpQuadraticObjective(const double * linearObjective, int numberColumns, const CoinBigIndex * start, const int * column, const double * element, int numberExtendedColumns_ = -1); /** Copy constructor . If type is -1 then make sure half symmetric, if +1 then make sure full */ ClpQuadraticObjective(const ClpQuadraticObjective & rhs, int type = 0); /** Subset constructor. Duplicates are allowed and order is as given. */ ClpQuadraticObjective (const ClpQuadraticObjective &rhs, int numberColumns, const int * whichColumns) ; /// Assignment operator ClpQuadraticObjective & operator=(const ClpQuadraticObjective& rhs); /// Destructor virtual ~ClpQuadraticObjective (); /// Clone virtual ClpObjective * clone() const; /** Subset clone. Duplicates are allowed and order is as given. */ virtual ClpObjective * subsetClone (int numberColumns, const int * whichColumns) const; /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ void loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start, const int * column, const double * element, int numberExtendedColumns = -1); void loadQuadraticObjective ( const CoinPackedMatrix& matrix); /// Get rid of quadratic objective void deleteQuadraticObjective(); //@} ///@name Gets and sets //@{ /// Quadratic objective inline CoinPackedMatrix * quadraticObjective() const { return quadraticObjective_; } /// Linear objective inline double * linearObjective() const { return objective_; } /// Length of linear objective which could be bigger inline int numberExtendedColumns() const { return numberExtendedColumns_; } /// Number of columns in quadratic objective inline int numberColumns() const { return numberColumns_; } /// If a full or half matrix inline bool fullMatrix() const { return fullMatrix_; } //@} //--------------------------------------------------------------------------- private: ///@name Private member data /// Quadratic objective CoinPackedMatrix * quadraticObjective_; /// Objective double * objective_; /// Gradient double * gradient_; /// Useful to have number of columns about int numberColumns_; /// Also length of linear objective which could be bigger int numberExtendedColumns_; /// True if full symmetric matrix, false if half bool fullMatrix_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyUfl.hpp0000644000076600007660000000436711534466607015270 0ustar coincoin/* $Id: ClpCholeskyUfl.hpp 1691 2011-03-05 17:06: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). #ifndef ClpCholeskyUfl_H #define ClpCholeskyUfl_H #include "ClpCholeskyBase.hpp" class ClpMatrixBase; class ClpCholeskyDense; typedef struct cholmod_factor_struct cholmod_factor; typedef struct cholmod_common_struct cholmod_common; /** Ufl class for Clp Cholesky factorization If you wish to use AMD code from University of Florida see http://www.cise.ufl.edu/research/sparse/amd for terms of use If you wish to use CHOLMOD code from University of Florida see http://www.cise.ufl.edu/research/sparse/cholmod for terms of use */ class ClpCholeskyUfl : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ //@{ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /** Does Symbolic factorization given permutation using CHOLMOD (if available). This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory. */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped using CHOLMOD (if available). If return code negative then out of memory */ virtual int factorize(const double * diagonal, int * rowsDropped) ; /** Uses factorization to solve. Uses CHOLMOD (if available). */ virtual void solve (double * region) ; //@} /**@name Constructors, destructor */ //@{ /** Constructor which has dense columns activated. Default is off. */ ClpCholeskyUfl(int denseThreshold = -1); /** Destructor */ virtual ~ClpCholeskyUfl(); /// Clone virtual ClpCholeskyBase * clone() const ; //@} private: cholmod_factor * L_ ; cholmod_common * c_ ; // Copy ClpCholeskyUfl(const ClpCholeskyUfl&); // Assignment ClpCholeskyUfl& operator=(const ClpCholeskyUfl&); }; #endif Clp-1.15.10/src/ClpPrimalColumnSteepest.cpp0000644000076600007660000050356512144406577017154 0ustar coincoin/* $Id: ClpPrimalColumnSteepest.cpp 1955 2013-05-14 10:10:07Z 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). #include "CoinPragma.hpp" #include "ClpSimplex.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "CoinIndexedVector.hpp" #include "ClpFactorization.hpp" #include "ClpNonLinearCost.hpp" #include "ClpMessage.hpp" #include "CoinHelperFunctions.hpp" #include //#define CLP_DEBUG //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpPrimalColumnSteepest::ClpPrimalColumnSteepest (int mode) : ClpPrimalColumnPivot(), devex_(0.0), weights_(NULL), infeasible_(NULL), alternateWeights_(NULL), savedWeights_(NULL), reference_(NULL), state_(-1), mode_(mode), persistence_(normal), numberSwitched_(0), pivotSequence_(-1), savedPivotSequence_(-1), savedSequenceOut_(-1), sizeFactorization_(0) { type_ = 2 + 64 * mode; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpPrimalColumnSteepest::ClpPrimalColumnSteepest (const ClpPrimalColumnSteepest & rhs) : ClpPrimalColumnPivot(rhs) { state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; numberSwitched_ = rhs.numberSwitched_; model_ = rhs.model_; pivotSequence_ = rhs.pivotSequence_; savedPivotSequence_ = rhs.savedPivotSequence_; savedSequenceOut_ = rhs.savedSequenceOut_; sizeFactorization_ = rhs.sizeFactorization_; devex_ = rhs.devex_; if ((model_ && model_->whatsChanged() & 1) != 0) { if (rhs.infeasible_) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } reference_ = NULL; if (rhs.weights_) { assert(model_); int number = model_->numberRows() + model_->numberColumns(); assert (number == rhs.model_->numberRows() + rhs.model_->numberColumns()); weights_ = new double[number]; CoinMemcpyN(rhs.weights_, number, weights_); savedWeights_ = new double[number]; CoinMemcpyN(rhs.savedWeights_, number, savedWeights_); if (mode_ != 1) { reference_ = CoinCopyOfArray(rhs.reference_, (number + 31) >> 5); } } else { weights_ = NULL; savedWeights_ = NULL; } if (rhs.alternateWeights_) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } } else { infeasible_ = NULL; reference_ = NULL; weights_ = NULL; savedWeights_ = NULL; alternateWeights_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpPrimalColumnSteepest::~ClpPrimalColumnSteepest () { delete [] weights_; delete infeasible_; delete alternateWeights_; delete [] savedWeights_; delete [] reference_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpPrimalColumnSteepest & ClpPrimalColumnSteepest::operator=(const ClpPrimalColumnSteepest& rhs) { if (this != &rhs) { ClpPrimalColumnPivot::operator=(rhs); state_ = rhs.state_; mode_ = rhs.mode_; persistence_ = rhs.persistence_; numberSwitched_ = rhs.numberSwitched_; model_ = rhs.model_; pivotSequence_ = rhs.pivotSequence_; savedPivotSequence_ = rhs.savedPivotSequence_; savedSequenceOut_ = rhs.savedSequenceOut_; sizeFactorization_ = rhs.sizeFactorization_; devex_ = rhs.devex_; delete [] weights_; delete [] reference_; reference_ = NULL; delete infeasible_; delete alternateWeights_; delete [] savedWeights_; savedWeights_ = NULL; if (rhs.infeasible_ != NULL) { infeasible_ = new CoinIndexedVector(rhs.infeasible_); } else { infeasible_ = NULL; } if (rhs.weights_ != NULL) { assert(model_); int number = model_->numberRows() + model_->numberColumns(); assert (number == rhs.model_->numberRows() + rhs.model_->numberColumns()); weights_ = new double[number]; CoinMemcpyN(rhs.weights_, number, weights_); savedWeights_ = new double[number]; CoinMemcpyN(rhs.savedWeights_, number, savedWeights_); if (mode_ != 1) { reference_ = CoinCopyOfArray(rhs.reference_, (number + 31) >> 5); } } else { weights_ = NULL; } if (rhs.alternateWeights_ != NULL) { alternateWeights_ = new CoinIndexedVector(rhs.alternateWeights_); } else { alternateWeights_ = NULL; } } return *this; } // These have to match ClpPackedMatrix version #define TRY_NORM 1.0e-4 #define ADD_ONE 1.0 // Returns pivot column, -1 if none /* The Packed CoinIndexedVector updates has cost updates - for normal LP that is just +-weight where a feasibility changed. It also has reduced cost from last iteration in pivot row*/ int ClpPrimalColumnSteepest::pivotColumn(CoinIndexedVector * updates, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { assert(model_); if (model_->nonLinearCost()->lookBothWays() || model_->algorithm() == 2) { // Do old way updates->expand(); return pivotColumnOldMethod(updates, spareRow1, spareRow2, spareColumn1, spareColumn2); } int number = 0; int * index; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); int anyUpdates; double * infeas = infeasible_->denseVector(); // Local copy of mode so can decide what to do int switchType; if (mode_ == 4) switchType = 5 - numberSwitched_; else if (mode_ >= 10) switchType = 3; else switchType = mode_; /* switchType - 0 - all exact devex 1 - all steepest 2 - some exact devex 3 - auto some exact devex 4 - devex 5 - dantzig 10 - can go to mini-sprint */ // Look at gub #if 1 model_->clpMatrix()->dualExpanded(model_, updates, NULL, 4); #else updates->clear(); model_->computeDuals(NULL); #endif if (updates->getNumElements() > 1) { // would have to have two goes for devex, three for steepest anyUpdates = 2; } else if (updates->getNumElements()) { if (updates->getIndices()[0] == pivotRow && fabs(updates->denseVector()[0]) > 1.0e-6) { // reasonable size anyUpdates = 1; //if (fabs(model_->dualIn())<1.0e-4||fabs(fabs(model_->dualIn())-fabs(updates->denseVector()[0]))>1.0e-5) //printf("dualin %g pivot %g\n",model_->dualIn(),updates->denseVector()[0]); } else { // too small anyUpdates = 2; } } else if (pivotSequence_ >= 0) { // just after re-factorization anyUpdates = -1; } else { // sub flip - nothing to do anyUpdates = 0; } int sequenceOut = model_->sequenceOut(); if (switchType == 5) { // If known matrix then we will do partial pricing if (model_->clpMatrix()->canDoPartialPricing()) { pivotSequence_ = -1; pivotRow = -1; // See if to switch int numberRows = model_->numberRows(); int numberWanted = 10; int numberColumns = model_->numberColumns(); int numberHiddenRows = model_->clpMatrix()->hiddenRows(); double ratio = static_cast (sizeFactorization_ + numberHiddenRows) / static_cast (numberRows + 2 * numberHiddenRows); // Number of dual infeasibilities at last invert int numberDual = model_->numberDualInfeasibilities(); int numberLook = CoinMin(numberDual, numberColumns / 10); if (ratio < 1.0) { numberWanted = 100; numberLook /= 20; numberWanted = CoinMax(numberWanted, numberLook); } else if (ratio < 3.0) { numberWanted = 500; numberLook /= 15; numberWanted = CoinMax(numberWanted, numberLook); } else if (ratio < 4.0 || mode_ == 5) { numberWanted = 1000; numberLook /= 10; numberWanted = CoinMax(numberWanted, numberLook); } else if (mode_ != 5) { switchType = 4; // initialize numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; model_->computeDuals(NULL); saveWeights(model_, 4); anyUpdates = 0; COIN_DETAIL_PRINT(printf("switching to devex %d nel ratio %g\n", sizeFactorization_, ratio)); } if (switchType == 5) { numberLook *= 5; // needs tuning for gub if (model_->numberIterations() % 1000 == 0 && model_->logLevel() > 1) { COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d look %d\n", sizeFactorization_, ratio, numberWanted, numberLook)); } // Update duals and row djs // Do partial pricing return partialPricing(updates, spareRow2, numberWanted, numberLook); } } } if (switchType == 5) { if (anyUpdates > 0) { justDjs(updates, spareRow2, spareColumn1, spareColumn2); } } else if (anyUpdates == 1) { if (switchType < 4) { // exact etc when can use dj djsAndSteepest(updates, spareRow2, spareColumn1, spareColumn2); } else { // devex etc when can use dj djsAndDevex(updates, spareRow2, spareColumn1, spareColumn2); } } else if (anyUpdates == -1) { if (switchType < 4) { // exact etc when djs okay justSteepest(updates, spareRow2, spareColumn1, spareColumn2); } else { // devex etc when djs okay justDevex(updates, spareRow2, spareColumn1, spareColumn2); } } else if (anyUpdates == 2) { if (switchType < 4) { // exact etc when have to use pivot djsAndSteepest2(updates, spareRow2, spareColumn1, spareColumn2); } else { // devex etc when have to use pivot djsAndDevex2(updates, spareRow2, spareColumn1, spareColumn2); } } #ifdef CLP_DEBUG alternateWeights_->checkClear(); #endif // make sure outgoing from last iteration okay if (sequenceOut >= 0) { ClpSimplex::Status status = model_->getStatus(sequenceOut); double value = model_->reducedCost(sequenceOut); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } } } // update of duals finished - now do pricing // See what sort of pricing int numberWanted = 10; number = infeasible_->getNumElements(); int numberColumns = model_->numberColumns(); if (switchType == 5) { pivotSequence_ = -1; pivotRow = -1; // See if to switch int numberRows = model_->numberRows(); // ratio is done on number of columns here //double ratio = static_cast sizeFactorization_/static_cast numberColumns; double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); //double ratio = static_cast sizeFactorization_/static_cast model_->clpMatrix()->getNumElements(); if (ratio < 1.0) { numberWanted = CoinMax(100, number / 200); } else if (ratio < 2.0 - 1.0) { numberWanted = CoinMax(500, number / 40); } else if (ratio < 4.0 - 3.0 || mode_ == 5) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 30); } else if (mode_ != 5) { switchType = 4; // initialize numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to devex %d nel ratio %g\n", sizeFactorization_, ratio)); } //if (model_->numberIterations()%1000==0) //printf("numels %d ratio %g wanted %d\n",sizeFactorization_,ratio,numberWanted); } int numberRows = model_->numberRows(); // ratio is done on number of rows here double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); if(switchType == 4) { // Still in devex mode // Go to steepest if lot of iterations? if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else if (ratio < 7.0) { numberWanted = CoinMax(2000, number / 5); numberWanted = CoinMax(numberWanted, numberColumns / 10); } else { // we can zero out updates->clear(); spareColumn1->clear(); switchType = 3; // initialize pivotSequence_ = -1; pivotRow = -1; numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to exact %d nel ratio %g\n", sizeFactorization_, ratio)); updates->clear(); } if (model_->numberIterations() % 1000 == 0) COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d type x\n", sizeFactorization_, ratio, numberWanted)); } if (switchType < 4) { if (switchType < 2 ) { numberWanted = number + 1; } else if (switchType == 2) { numberWanted = CoinMax(2000, number / 8); } else { if (ratio < 1.0) { numberWanted = CoinMax(2000, number / 20); } else if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 40); } else if (ratio < 10.0) { numberWanted = CoinMax(2000, number / 8); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else { ratio = number * (ratio / 80.0); if (ratio > number) { numberWanted = number + 1; } else { numberWanted = CoinMax(2000, static_cast (ratio)); numberWanted = CoinMax(numberWanted, numberColumns / 10); } } } //if (model_->numberIterations()%1000==0) //printf("numels %d ratio %g wanted %d type %d\n",sizeFactorization_,ratio,numberWanted, //switchType); } double bestDj = 1.0e-30; int bestSequence = -1; int i, iSequence; index = infeasible_->getIndices(); number = infeasible_->getNumElements(); // Re-sort infeasible every 100 pivots // Not a good idea if (0 && model_->factorization()->pivots() > 0 && (model_->factorization()->pivots() % 100) == 0) { int nLook = model_->numberRows() + numberColumns; number = 0; for (i = 0; i < nLook; i++) { if (infeas[i]) { if (fabs(infeas[i]) > COIN_INDEXED_TINY_ELEMENT) index[number++] = i; else infeas[i] = 0.0; } } infeasible_->setNumElements(number); } if(model_->numberIterations() < model_->lastBadIteration() + 200 && model_->factorization()->pivots() > 10) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } #ifdef CLP_DEBUG if (model_->numberDualInfeasibilities() == 1) printf("** %g %g %g %x %x %d\n", tolerance, model_->dualTolerance(), model_->largestDualError(), model_, model_->messageHandler(), number); #endif // stop last one coming immediately double saveOutInfeasibility = 0.0; if (sequenceOut >= 0) { saveOutInfeasibility = infeas[sequenceOut]; infeas[sequenceOut] = 0.0; } if (model_->factorization()->pivots() && model_->numberPrimalInfeasibilities()) tolerance = CoinMax(tolerance, 1.0e-10 * model_->infeasibilityCost()); tolerance *= tolerance; // as we are using squares int iPass; // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; //double largestWeight=0.0; //double smallestWeight=1.0e100; for (iPass = 0; iPass < 2; iPass++) { int end = start[2*iPass+1]; if (switchType < 5) { for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; double weight = weights_[iSequence]; if (value > tolerance) { //weight=1.0; if (value > bestDj * weight) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value / weight; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } numberWanted--; } if (!numberWanted) break; } } else { // Dantzig for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; if (value > tolerance) { if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } numberWanted--; } if (!numberWanted) break; } } if (!numberWanted) break; } model_->clpMatrix()->setSavedBestSequence(bestSequence); if (bestSequence >= 0) model_->clpMatrix()->setSavedBestDj(model_->djRegion()[bestSequence]); if (sequenceOut >= 0) { infeas[sequenceOut] = saveOutInfeasibility; } /*if (model_->numberIterations()%100==0) printf("%d best %g\n",bestSequence,bestDj);*/ #ifndef NDEBUG if (bestSequence >= 0) { if (model_->getStatus(bestSequence) == ClpSimplex::atLowerBound) assert(model_->reducedCost(bestSequence) < 0.0); if (model_->getStatus(bestSequence) == ClpSimplex::atUpperBound) { assert(model_->reducedCost(bestSequence) > 0.0); } } #endif #if 0 for (int i=0;icurrentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray (packed mode) model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); // normal for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); int addSequence; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER double slack_multiplier; #endif if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = model_->numberColumns(); #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = CLP_PRIMAL_SLACK_MULTIPLIER; #endif } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = 0; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = 1.0; #endif } for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[j]; updateBy[j] = 0.0; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: iSequence += addSequence; if (value > tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: iSequence += addSequence; if (value < -tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } } updates->setNumElements(0); spareColumn1->setNumElements(0); if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); } } // Update djs, weights for Devex void ClpPrimalColumnSteepest::djsAndDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int j; int number = 0; int * index; double * updateBy; double * reducedCost; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // for weights update we use pivotSequence // unset in case sub flip assert (pivotSequence_ >= 0); assert (model_->pivotVariable()[pivotSequence_] == model_->sequenceIn()); pivotSequence_ = -1; double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, updates); // and we can see if reference //double referenceIn = 0.0; int sequenceIn = model_->sequenceIn(); //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; double scaleFactor = 1.0 / updates->denseVector()[0]; // as formula is with 1.0 // put row of tableau in rowArray and columnArray (packed mode) model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); // update weights double * weight; int numberColumns = model_->numberColumns(); // rows reducedCost = model_->djRegion(0); int addSequence = model_->numberColumns();; number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; // Devex for (j = 0; j < number; j++) { double thisWeight; double pivot; double value3; int iSequence = index[j]; double value = reducedCost[iSequence]; double value2 = updateBy[j]; updateBy[j] = 0.0; value -= value2; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); iSequence += addSequence; if (value > tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence , value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); iSequence += addSequence; if (value < -tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence , value); } else { infeasible_->zero(iSequence); } } } // columns weight = weights_; scaleFactor = -scaleFactor; reducedCost = model_->djRegion(1); number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); // Devex for (j = 0; j < number; j++) { double thisWeight; double pivot; double value3; int iSequence = index[j]; double value = reducedCost[iSequence]; double value2 = updateBy[j]; value -= value2; updateBy[j] = 0.0; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atUpperBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value > tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; value3 = pivot * pivot * devex_; if (reference(iSequence)) value3 += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value3); if (value < -tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } } } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; // make sure infeasibility on incoming is 0.0 infeasible_->zero(sequenceIn); spareRow2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Update djs, weights for Steepest void ClpPrimalColumnSteepest::djsAndSteepest(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int j; int number = 0; int * index; double * updateBy; double * reducedCost; double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; // for weights update we use pivotSequence // unset in case sub flip assert (pivotSequence_ >= 0); assert (model_->pivotVariable()[pivotSequence_] == model_->sequenceIn()); double * infeas = infeasible_->denseVector(); double scaleFactor = 1.0 / updates->denseVector()[0]; // as formula is with 1.0 assert (updates->getIndices()[0] == pivotSequence_); pivotSequence_ = -1; //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, updates); //alternateWeights_->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, alternateWeights_); // and we can see if reference int sequenceIn = model_->sequenceIn(); double referenceIn; if (mode_ != 1) { if(reference(sequenceIn)) referenceIn = 1.0; else referenceIn = 0.0; } else { referenceIn = -1.0; } // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // update row weights here so we can scale alternateWeights_ // update weights double * weight; double * other = alternateWeights_->denseVector(); int numberColumns = model_->numberColumns(); // rows reducedCost = model_->djRegion(0); int addSequence = model_->numberColumns();; number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; for (j = 0; j < number; j++) { double thisWeight; double pivot; double modification; double pivotSquared; int iSequence = index[j]; double value2 = updateBy[j]; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); double value; switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); reducedCost[iSequence] = 0.0; case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = reducedCost[iSequence] - value2; modification = other[iSequence]; thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; reducedCost[iSequence] = value; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: value = reducedCost[iSequence] - value2; modification = other[iSequence]; thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; reducedCost[iSequence] = value; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; iSequence += addSequence; if (value > tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence , value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: value = reducedCost[iSequence] - value2; modification = other[iSequence]; thisWeight = weight[iSequence]; // row has -1 pivot = value2 * scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; reducedCost[iSequence] = value; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; iSequence += addSequence; if (value < -tolerance) { // store square in list #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*CLP_PRIMAL_SLACK_MULTIPLIER; #else value *= value; #endif if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } // put row of tableau in rowArray and columnArray (packed) // get subset which have nonzero tableau elements transposeTimes2(updates, spareColumn1, alternateWeights_, spareColumn2, spareRow2, -scaleFactor); // zero updateBy CoinZeroN(updateBy, number); alternateWeights_->clear(); // columns assert (scaleFactor); reducedCost = model_->djRegion(1); number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; double value2 = updateBy[j]; updateBy[j] = 0.0; value -= value2; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[iSequence]) infeas[iSequence] = value * value; // already there else infeasible_->quickAdd(iSequence, value * value); } else { infeasible_->zero(iSequence); } } } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; // make sure infeasibility on incoming is 0.0 infeasible_->zero(sequenceIn); spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Update djs, weights for Devex void ClpPrimalColumnSteepest::djsAndDevex2(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int iSection, j; int number = 0; int * index; double * updateBy; double * reducedCost; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); // normal for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); int addSequence; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER double slack_multiplier; #endif if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = model_->numberColumns(); #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = CLP_PRIMAL_SLACK_MULTIPLIER; #endif } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = 0; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = 1.0; #endif } for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[j]; updateBy[j] = 0.0; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: iSequence += addSequence; if (value > tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: iSequence += addSequence; if (value < -tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } } // They are empty updates->setNumElements(0); spareColumn1->setNumElements(0); // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); // for weights update we use pivotSequence if (pivotSequence_ >= 0) { pivotRow = pivotSequence_; // unset in case sub flip pivotSequence_ = -1; // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference //double referenceIn = 0.0; //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // update weights updates->setNumElements(0); spareColumn1->setNumElements(0); // might as well set dj to 1 dj = 1.0; updates->insert(pivotRow, -dj); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); double * weight; int numberColumns = model_->numberColumns(); // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = - updateBy[iSequence]; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // columns weight = weights_; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[iSequence]; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } } // Update djs, weights for Steepest void ClpPrimalColumnSteepest::djsAndSteepest2(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int iSection, j; int number = 0; int * index; double * updateBy; double * reducedCost; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); double * infeas = infeasible_->denseVector(); //updates->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); // normal for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); int addSequence; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER double slack_multiplier; #endif if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = model_->numberColumns(); #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = CLP_PRIMAL_SLACK_MULTIPLIER; #endif } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = 0; #ifdef CLP_PRIMAL_SLACK_MULTIPLIER slack_multiplier = 1.0; #endif } for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[j]; updateBy[j] = 0.0; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: iSequence += addSequence; if (value > tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } break; case ClpSimplex::atLowerBound: iSequence += addSequence; if (value < -tolerance) { #ifdef CLP_PRIMAL_SLACK_MULTIPLIER value *= value*slack_multiplier; #else value *= value; #endif // store square in list if (infeas[iSequence]) infeas[iSequence] = value; // already there else infeasible_->quickAdd(iSequence, value); } else { infeasible_->zero(iSequence); } } } } // we can zero out as will have to get pivot row // ***** move updates->setNumElements(0); spareColumn1->setNumElements(0); if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); } // for weights update we use pivotSequence pivotRow = pivotSequence_; // unset in case sub flip pivotSequence_ = -1; if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); int sequenceIn = pivotVariable[pivotRow]; assert (sequenceIn == model_->sequenceIn()); infeasible_->zero(sequenceIn); // and we can see if reference double referenceIn; if (mode_ != 1) { if(reference(sequenceIn)) referenceIn = 1.0; else referenceIn = 0.0; } else { referenceIn = -1.0; } // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // update weights updates->setNumElements(0); spareColumn1->setNumElements(0); // might as well set dj to 1 dj = -1.0; updates->createPacked(1, &pivotRow, &dj); model_->factorization()->updateColumnTranspose(spareRow2, updates); bool needSubset = (mode_ < 4 || numberSwitched_ > 1 || mode_ >= 10); double * weight; double * other = alternateWeights_->denseVector(); int numberColumns = model_->numberColumns(); // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; if (needSubset) { // now update weight update array model_->factorization()->updateColumnTranspose(spareRow2, alternateWeights_); // do alternateWeights_ here so can scale for (j = 0; j < number; j++) { int iSequence = index[j]; assert (iSequence >= 0 && iSequence < model_->numberRows()); double thisWeight = weight[iSequence]; // row has -1 double pivot = - updateBy[j]; double modification = other[iSequence]; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } transposeTimes2(updates, spareColumn1, alternateWeights_, spareColumn2, spareRow2, 0.0); } else { // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); } if (needSubset) { CoinZeroN(updateBy, number); } else if (mode_ == 4) { // Devex assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = -updateBy[j]; updateBy[j] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } } // columns weight = weights_; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); if (needSubset) { // Exact - already done } else if (mode_ == 4) { // Devex for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[j]; updateBy[j] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; alternateWeights_->clear(); spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif } updates->setNumElements(0); spareColumn1->setNumElements(0); } // Updates two arrays for steepest void ClpPrimalColumnSteepest::transposeTimes2(const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, CoinIndexedVector * spare, double scaleFactor) { // see if reference int sequenceIn = model_->sequenceIn(); double referenceIn; if (mode_ != 1) { if(reference(sequenceIn)) referenceIn = 1.0; else referenceIn = 0.0; } else { referenceIn = -1.0; } if (model_->clpMatrix()->canCombine(model_, pi1)) { // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes2(model_, pi1, dj1, pi2, spare, referenceIn, devex_, reference_, weights_, scaleFactor); } else { // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, pi1, dj2, dj1); // get subset which have nonzero tableau elements model_->clpMatrix()->subsetTransposeTimes(model_, pi2, dj1, dj2); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; // columns double * weight = weights_; int number = dj1->getNumElements(); const int * index = dj1->getIndices(); double * updateBy = dj1->denseVector(); double * updateBy2 = dj2->denseVector(); for (int j = 0; j < number; j++) { double thisWeight; double pivot; double pivotSquared; int iSequence = index[j]; double value2 = updateBy[j]; if (killDjs) updateBy[j] = 0.0; double modification = updateBy2[j]; updateBy2[j] = 0.0; ClpSimplex::Status status = model_->getStatus(iSequence); if (status != ClpSimplex::basic && status != ClpSimplex::isFixed) { thisWeight = weight[iSequence]; pivot = value2 * scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } } } dj2->setNumElements(0); } // Update weights for Devex void ClpPrimalColumnSteepest::justDevex(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int j; int number = 0; int * index; double * updateBy; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); // for weights update we use pivotSequence pivotRow = pivotSequence_; assert (pivotRow >= 0); // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); int sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference //double referenceIn = 0.0; //if (mode_ != 1 && reference(sequenceIn)) // referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; assert (!updates->getNumElements()); assert (!spareColumn1->getNumElements()); // unset in case sub flip pivotSequence_ = -1; // might as well set dj to 1 dj = -1.0; updates->createPacked(1, &pivotRow, &dj); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); double * weight; int numberColumns = model_->numberColumns(); // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; // Devex assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = - updateBy[j]; updateBy[j] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // columns weight = weights_; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); // Devex for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[j]; updateBy[j] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Update weights for Steepest void ClpPrimalColumnSteepest::justSteepest(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { int j; int number = 0; int * index; double * updateBy; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); // for weights update we use pivotSequence pivotRow = pivotSequence_; // unset in case sub flip pivotSequence_ = -1; assert (pivotRow >= 0); // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); int sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference double referenceIn = 0.0; if (mode_ != 1 && reference(sequenceIn)) referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; assert (!updates->getNumElements()); assert (!spareColumn1->getNumElements()); // update weights //updates->setNumElements(0); //spareColumn1->setNumElements(0); // might as well set dj to 1 dj = -1.0; updates->createPacked(1, &pivotRow, &dj); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); double * weight; double * other = alternateWeights_->denseVector(); int numberColumns = model_->numberColumns(); // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; // Exact // now update weight update array //alternateWeights_->scanAndPack(); model_->factorization()->updateColumnTranspose(spareRow2, alternateWeights_); // get subset which have nonzero tableau elements model_->clpMatrix()->subsetTransposeTimes(model_, alternateWeights_, spareColumn1, spareColumn2); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = -updateBy[j]; updateBy[j] = 0.0; double modification = other[iSequence]; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } // columns weight = weights_; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); // Exact double * updateBy2 = spareColumn2->denseVector(); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; double pivot = updateBy[j]; updateBy[j] = 0.0; double modification = updateBy2[j]; updateBy2[j] = 0.0; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (mode_ == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; alternateWeights_->clear(); spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // Returns pivot column, -1 if none int ClpPrimalColumnSteepest::pivotColumnOldMethod(CoinIndexedVector * updates, CoinIndexedVector * , CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2) { assert(model_); int iSection, j; int number = 0; int * index; double * updateBy; double * reducedCost; // dj could be very small (or even zero - take care) double dj = model_->dualIn(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; int pivotRow = model_->pivotRow(); int anyUpdates; double * infeas = infeasible_->denseVector(); // Local copy of mode so can decide what to do int switchType; if (mode_ == 4) switchType = 5 - numberSwitched_; else if (mode_ >= 10) switchType = 3; else switchType = mode_; /* switchType - 0 - all exact devex 1 - all steepest 2 - some exact devex 3 - auto some exact devex 4 - devex 5 - dantzig */ if (updates->getNumElements()) { // would have to have two goes for devex, three for steepest anyUpdates = 2; // add in pivot contribution if (pivotRow >= 0) updates->add(pivotRow, -dj); } else if (pivotRow >= 0) { if (fabs(dj) > 1.0e-15) { // some dj updates->insert(pivotRow, -dj); if (fabs(dj) > 1.0e-6) { // reasonable size anyUpdates = 1; } else { // too small anyUpdates = 2; } } else { // zero dj anyUpdates = -1; } } else if (pivotSequence_ >= 0) { // just after re-factorization anyUpdates = -1; } else { // sub flip - nothing to do anyUpdates = 0; } if (anyUpdates > 0) { model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); // normal for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); int addSequence; if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); addSequence = model_->numberColumns(); } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); addSequence = 0; } if (!model_->nonLinearCost()->lookBothWays()) { for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[iSequence]; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } } } } else { ClpNonLinearCost * nonLinear = model_->nonLinearCost(); // We can go up OR down for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= updateBy[iSequence]; reducedCost[iSequence] = value; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { // look other way - change up should be negative value -= nonLinear->changeUpInCost(iSequence + addSequence); if (value > -tolerance) { infeasible_->zero(iSequence + addSequence); } else { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { // look other way - change down should be positive value -= nonLinear->changeDownInCost(iSequence + addSequence); if (value < tolerance) { infeasible_->zero(iSequence + addSequence); } else { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } } } } } } if (anyUpdates == 2) { // we can zero out as will have to get pivot row updates->clear(); spareColumn1->clear(); } if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); infeasible_->zero(sequenceIn); } } // make sure outgoing from last iteration okay int sequenceOut = model_->sequenceOut(); if (sequenceOut >= 0) { ClpSimplex::Status status = model_->getStatus(sequenceOut); double value = model_->reducedCost(sequenceOut); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[sequenceOut]) infeas[sequenceOut] = value * value; // already there else infeasible_->quickAdd(sequenceOut, value * value); } else { infeasible_->zero(sequenceOut); } } } // If in quadratic re-compute all if (model_->algorithm() == 2) { for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); int addSequence; int iSequence; if (!iSection) { number = model_->numberRows(); addSequence = model_->numberColumns(); } else { number = model_->numberColumns(); addSequence = 0; } if (!model_->nonLinearCost()->lookBothWays()) { for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } } } } else { // we can go both ways ClpNonLinearCost * nonLinear = model_->nonLinearCost(); for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence + addSequence); switch(status) { case ClpSimplex::basic: infeasible_->zero(iSequence + addSequence); case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { infeasible_->zero(iSequence + addSequence); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { // look other way - change up should be negative value -= nonLinear->changeUpInCost(iSequence + addSequence); if (value > -tolerance) { infeasible_->zero(iSequence + addSequence); } else { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } else { // look other way - change down should be positive value -= nonLinear->changeDownInCost(iSequence + addSequence); if (value < tolerance) { infeasible_->zero(iSequence + addSequence); } else { // store square in list if (infeas[iSequence+addSequence]) infeas[iSequence+addSequence] = value * value; // already there else infeasible_->quickAdd(iSequence + addSequence, value * value); } } } } } } } // See what sort of pricing int numberWanted = 10; number = infeasible_->getNumElements(); int numberColumns = model_->numberColumns(); if (switchType == 5) { // we can zero out updates->clear(); spareColumn1->clear(); pivotSequence_ = -1; pivotRow = -1; // See if to switch int numberRows = model_->numberRows(); // ratio is done on number of columns here //double ratio = static_cast sizeFactorization_/static_cast numberColumns; double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); //double ratio = static_cast sizeFactorization_/static_cast model_->clpMatrix()->getNumElements(); if (ratio < 0.1) { numberWanted = CoinMax(100, number / 200); } else if (ratio < 0.3) { numberWanted = CoinMax(500, number / 40); } else if (ratio < 0.5 || mode_ == 5) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 30); } else if (mode_ != 5) { switchType = 4; // initialize numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to devex %d nel ratio %g\n", sizeFactorization_, ratio)); updates->clear(); } if (model_->numberIterations() % 1000 == 0) COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d\n", sizeFactorization_, ratio, numberWanted)); } if(switchType == 4) { // Still in devex mode int numberRows = model_->numberRows(); // ratio is done on number of rows here double ratio = static_cast (sizeFactorization_) / static_cast (numberRows); // Go to steepest if lot of iterations? if (ratio < 1.0) { numberWanted = CoinMax(2000, number / 20); } else if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else { // we can zero out updates->clear(); spareColumn1->clear(); switchType = 3; // initialize pivotSequence_ = -1; pivotRow = -1; numberSwitched_++; // Make sure will re-do delete [] weights_; weights_ = NULL; saveWeights(model_, 4); COIN_DETAIL_PRINT(printf("switching to exact %d nel ratio %g\n", sizeFactorization_, ratio)); updates->clear(); } if (model_->numberIterations() % 1000 == 0) COIN_DETAIL_PRINT(printf("numels %d ratio %g wanted %d\n", sizeFactorization_, ratio, numberWanted)); } if (switchType < 4) { if (switchType < 2 ) { numberWanted = number + 1; } else if (switchType == 2) { numberWanted = CoinMax(2000, number / 8); } else { double ratio = static_cast (sizeFactorization_) / static_cast (model_->numberRows()); if (ratio < 1.0) { numberWanted = CoinMax(2000, number / 20); } else if (ratio < 5.0) { numberWanted = CoinMax(2000, number / 10); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else if (ratio < 10.0) { numberWanted = CoinMax(2000, number / 8); numberWanted = CoinMax(numberWanted, numberColumns / 20); } else { ratio = number * (ratio / 80.0); if (ratio > number) { numberWanted = number + 1; } else { numberWanted = CoinMax(2000, static_cast (ratio)); numberWanted = CoinMax(numberWanted, numberColumns / 10); } } } } // for weights update we use pivotSequence pivotRow = pivotSequence_; // unset in case sub flip pivotSequence_ = -1; if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 const int * pivotVariable = model_->pivotVariable(); int sequenceIn = pivotVariable[pivotRow]; infeasible_->zero(sequenceIn); // and we can see if reference double referenceIn = 0.0; if (switchType != 1 && reference(sequenceIn)) referenceIn = 1.0; // save outgoing weight round update double outgoingWeight = 0.0; if (sequenceOut >= 0) outgoingWeight = weights_[sequenceOut]; // update weights if (anyUpdates != 1) { updates->setNumElements(0); spareColumn1->setNumElements(0); // might as well set dj to 1 dj = 1.0; updates->insert(pivotRow, -dj); model_->factorization()->updateColumnTranspose(spareRow2, updates); // put row of tableau in rowArray and columnArray model_->clpMatrix()->transposeTimes(model_, -1.0, updates, spareColumn2, spareColumn1); } double * weight; double * other = alternateWeights_->denseVector(); int numberColumns = model_->numberColumns(); double scaleFactor = -1.0 / dj; // as formula is with 1.0 // rows number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); weight = weights_ + numberColumns; if (switchType < 4) { // Exact // now update weight update array model_->factorization()->updateColumnTranspose(spareRow2, alternateWeights_); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[iSequence] * scaleFactor; updateBy[iSequence] = 0.0; double modification = other[iSequence]; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (switchType == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence + numberColumns)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } } else if (switchType == 4) { // Devex assert (devex_ > 0.0); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[iSequence] * scaleFactor; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence + numberColumns)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } } // columns weight = weights_; scaleFactor = -scaleFactor; number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); if (switchType < 4) { // Exact // get subset which have nonzero tableau elements model_->clpMatrix()->subsetTransposeTimes(model_, alternateWeights_, spareColumn1, spareColumn2); double * updateBy2 = spareColumn2->denseVector(); for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; double pivot = updateBy[iSequence] * scaleFactor; updateBy[iSequence] = 0.0; double modification = updateBy2[j]; updateBy2[j] = 0.0; double pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex_ + pivot * modification; if (thisWeight < TRY_NORM) { if (switchType == 1) { // steepest thisWeight = CoinMax(TRY_NORM, ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, TRY_NORM); } } weight[iSequence] = thisWeight; } } else if (switchType == 4) { // Devex for (j = 0; j < number; j++) { int iSequence = index[j]; double thisWeight = weight[iSequence]; // row has -1 double pivot = updateBy[iSequence] * scaleFactor; updateBy[iSequence] = 0.0; double value = pivot * pivot * devex_; if (reference(iSequence)) value += 1.0; weight[iSequence] = CoinMax(0.99 * thisWeight, value); } } // restore outgoing weight if (sequenceOut >= 0) weights_[sequenceOut] = outgoingWeight; alternateWeights_->clear(); spareColumn2->setNumElements(0); //#define SOME_DEBUG_1 #ifdef SOME_DEBUG_1 // check for accuracy int iCheck = 892; //printf("weight for iCheck is %g\n",weights_[iCheck]); int numberRows = model_->numberRows(); //int numberColumns = model_->numberColumns(); for (iCheck = 0; iCheck < numberRows + numberColumns; iCheck++) { if (model_->getStatus(iCheck) != ClpSimplex::basic && !model_->getStatus(iCheck) != ClpSimplex::isFixed) checkAccuracy(iCheck, 1.0e-1, updates, spareRow2); } #endif updates->setNumElements(0); spareColumn1->setNumElements(0); } // update of duals finished - now do pricing double bestDj = 1.0e-30; int bestSequence = -1; int i, iSequence; index = infeasible_->getIndices(); number = infeasible_->getNumElements(); if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (!model_->factorization()->pivots()) checkTolerance = 1.0e-6; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } #ifdef CLP_DEBUG if (model_->numberDualInfeasibilities() == 1) printf("** %g %g %g %x %x %d\n", tolerance, model_->dualTolerance(), model_->largestDualError(), model_, model_->messageHandler(), number); #endif // stop last one coming immediately double saveOutInfeasibility = 0.0; if (sequenceOut >= 0) { saveOutInfeasibility = infeas[sequenceOut]; infeas[sequenceOut] = 0.0; } tolerance *= tolerance; // as we are using squares int iPass; // Setup two passes int start[4]; start[1] = number; start[2] = 0; double dstart = static_cast (number) * model_->randomNumberGenerator()->randomDouble(); start[0] = static_cast (dstart); start[3] = start[0]; //double largestWeight=0.0; //double smallestWeight=1.0e100; for (iPass = 0; iPass < 2; iPass++) { int end = start[2*iPass+1]; if (switchType < 5) { for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; if (value > tolerance) { double weight = weights_[iSequence]; //weight=1.0; if (value > bestDj * weight) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value / weight; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } numberWanted--; if (!numberWanted) break; } } else { // Dantzig for (i = start[2*iPass]; i < end; i++) { iSequence = index[i]; double value = infeas[iSequence]; if (value > tolerance) { if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } numberWanted--; if (!numberWanted) break; } } if (!numberWanted) break; } if (sequenceOut >= 0) { infeas[sequenceOut] = saveOutInfeasibility; } /*if (model_->numberIterations()%100==0) printf("%d best %g\n",bestSequence,bestDj);*/ reducedCost = model_->djRegion(); model_->clpMatrix()->setSavedBestSequence(bestSequence); if (bestSequence >= 0) model_->clpMatrix()->setSavedBestDj(reducedCost[bestSequence]); #ifdef CLP_DEBUG if (bestSequence >= 0) { if (model_->getStatus(bestSequence) == ClpSimplex::atLowerBound) assert(model_->reducedCost(bestSequence) < 0.0); if (model_->getStatus(bestSequence) == ClpSimplex::atUpperBound) assert(model_->reducedCost(bestSequence) > 0.0); } #endif return bestSequence; } // Called when maximum pivots changes void ClpPrimalColumnSteepest::maximumPivotsChanged() { if (alternateWeights_ && alternateWeights_->capacity() != model_->numberRows() + model_->factorization()->maximumPivots()) { delete alternateWeights_; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization alternateWeights_->reserve(model_->numberRows() + model_->factorization()->maximumPivots()); } } /* 1) before factorization 2) after factorization 3) just redo infeasibilities 4) restore weights 5) at end of values pass (so need initialization) */ void ClpPrimalColumnSteepest::saveWeights(ClpSimplex * model, int mode) { model_ = model; if (mode_ == 4 || mode_ == 5) { if (mode == 1 && !weights_) numberSwitched_ = 0; // Reset } // alternateWeights_ is defined as indexed but is treated oddly // at times int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); const int * pivotVariable = model_->pivotVariable(); bool doInfeasibilities = true; if (mode == 1) { if(weights_) { // Check if size has changed if (infeasible_->capacity() == numberRows + numberColumns && alternateWeights_->capacity() == numberRows + model_->factorization()->maximumPivots()) { //alternateWeights_->clear(); if (pivotSequence_ >= 0 && pivotSequence_ < numberRows) { // save pivot order CoinMemcpyN(pivotVariable, numberRows, alternateWeights_->getIndices()); // change from pivot row number to sequence number pivotSequence_ = pivotVariable[pivotSequence_]; } else { pivotSequence_ = -1; } state_ = 1; } else { // size has changed - clear everything delete [] weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete [] savedWeights_; savedWeights_ = NULL; delete [] reference_; reference_ = NULL; state_ = -1; pivotSequence_ = -1; } } } else if (mode == 2 || mode == 4 || mode == 5) { // restore if (!weights_ || state_ == -1 || mode == 5) { // Partial is only allowed with certain types of matrix if ((mode_ != 4 && mode_ != 5) || numberSwitched_ || !model_->clpMatrix()->canDoPartialPricing()) { // initialize weights delete [] weights_; delete alternateWeights_; weights_ = new double[numberRows+numberColumns]; alternateWeights_ = new CoinIndexedVector(); // enough space so can use it for factorization alternateWeights_->reserve(numberRows + model_->factorization()->maximumPivots()); initializeWeights(); // create saved weights delete [] savedWeights_; savedWeights_ = CoinCopyOfArray(weights_, numberRows + numberColumns); // just do initialization mode = 3; } else { // Partial pricing // use region as somewhere to save non-fixed slacks // set up infeasibilities if (!infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberColumns + numberRows); } infeasible_->clear(); int number = model_->numberRows() + model_->numberColumns(); int iSequence; int numberLook = 0; int * which = infeasible_->getIndices(); for (iSequence = model_->numberColumns(); iSequence < number; iSequence++) { ClpSimplex::Status status = model_->getStatus(iSequence); if (status != ClpSimplex::isFixed) which[numberLook++] = iSequence; } infeasible_->setNumElements(numberLook); doInfeasibilities = false; } savedPivotSequence_ = -2; savedSequenceOut_ = -2; } else { if (mode != 4) { // save CoinMemcpyN(weights_, (numberRows + numberColumns), savedWeights_); savedPivotSequence_ = pivotSequence_; savedSequenceOut_ = model_->sequenceOut(); } else { // restore CoinMemcpyN(savedWeights_, (numberRows + numberColumns), weights_); // was - but I think should not be //pivotSequence_= savedPivotSequence_; //model_->setSequenceOut(savedSequenceOut_); pivotSequence_ = -1; model_->setSequenceOut(-1); // indices are wrong so clear by hand //alternateWeights_->clear(); CoinZeroN(alternateWeights_->denseVector(), alternateWeights_->capacity()); alternateWeights_->setNumElements(0); } } state_ = 0; // set up infeasibilities if (!infeasible_) { infeasible_ = new CoinIndexedVector(); infeasible_->reserve(numberColumns + numberRows); } } if (mode >= 2 && mode != 5) { if (mode != 3) { if (pivotSequence_ >= 0) { // restore pivot row int iRow; // permute alternateWeights double * temp = model_->rowArray(3)->denseVector();; double * work = alternateWeights_->denseVector(); int * savePivotOrder = model_->rowArray(3)->getIndices(); int * oldPivotOrder = alternateWeights_->getIndices(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = oldPivotOrder[iRow]; temp[iPivot] = work[iRow]; savePivotOrder[iRow] = iPivot; } int number = 0; int found = -1; int * which = oldPivotOrder; // find pivot row and re-create alternateWeights for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; if (iPivot == pivotSequence_) found = iRow; work[iRow] = temp[iPivot]; if (work[iRow]) which[number++] = iRow; } alternateWeights_->setNumElements(number); #ifdef CLP_DEBUG // Can happen but I should clean up assert(found >= 0); #endif pivotSequence_ = found; for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = savePivotOrder[iRow]; temp[iPivot] = 0.0; } } else { // Just clean up if (alternateWeights_) alternateWeights_->clear(); } } // Save size of factorization if (!model->factorization()->pivots()) sizeFactorization_ = model_->factorization()->numberElements(); if(!doInfeasibilities) return; // don't disturb infeasibilities infeasible_->clear(); double tolerance = model_->currentDualTolerance(); int number = model_->numberRows() + model_->numberColumns(); int iSequence; double * reducedCost = model_->djRegion(); const double * lower = model_->lowerRegion(); const double * upper = model_->upperRegion(); const double * solution = model_->solutionRegion(); double primalTolerance = model_->currentPrimalTolerance(); if (!model_->nonLinearCost()->lookBothWays()) { #ifndef CLP_PRIMAL_SLACK_MULTIPLIER for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } } } #else // Columns int numberColumns = model_->numberColumns(); for (iSequence = 0; iSequence < numberColumns; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // check hasn't slipped through if (solution[iSequence]setStatus(iSequence,ClpSimplex::atLowerBound); if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } } else if (solution[iSequence]>upper[iSequence]-primalTolerance) { model_->setStatus(iSequence,ClpSimplex::atUpperBound); if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } } else { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } } break; case ClpSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } } } // Rows for ( ; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value * CLP_PRIMAL_SLACK_MULTIPLIER); } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value * CLP_PRIMAL_SLACK_MULTIPLIER); } } } #endif } else { ClpNonLinearCost * nonLinear = model_->nonLinearCost(); // can go both ways for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) { // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; // store square in list infeasible_->quickAdd(iSequence, value * value); } break; case ClpSimplex::atUpperBound: if (value > tolerance) { infeasible_->quickAdd(iSequence, value * value); } else { // look other way - change up should be negative value -= nonLinear->changeUpInCost(iSequence); if (value < -tolerance) { // store square in list infeasible_->quickAdd(iSequence, value * value); } } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { infeasible_->quickAdd(iSequence, value * value); } else { // look other way - change down should be positive value -= nonLinear->changeDownInCost(iSequence); if (value > tolerance) { // store square in list infeasible_->quickAdd(iSequence, value * value); } } } } } } } // Gets rid of last update void ClpPrimalColumnSteepest::unrollWeights() { if ((mode_ == 4 || mode_ == 5) && !numberSwitched_) return; double * saved = alternateWeights_->denseVector(); int number = alternateWeights_->getNumElements(); int * which = alternateWeights_->getIndices(); int i; for (i = 0; i < number; i++) { int iRow = which[i]; weights_[iRow] = saved[iRow]; saved[iRow] = 0.0; } alternateWeights_->setNumElements(0); } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpPrimalColumnPivot * ClpPrimalColumnSteepest::clone(bool CopyData) const { if (CopyData) { return new ClpPrimalColumnSteepest(*this); } else { return new ClpPrimalColumnSteepest(); } } void ClpPrimalColumnSteepest::updateWeights(CoinIndexedVector * input) { // Local copy of mode so can decide what to do int switchType = mode_; if (mode_ == 4 && numberSwitched_) switchType = 3; else if (mode_ == 4 || mode_ == 5) return; int number = input->getNumElements(); int * which = input->getIndices(); double * work = input->denseVector(); int newNumber = 0; int * newWhich = alternateWeights_->getIndices(); double * newWork = alternateWeights_->denseVector(); int i; int sequenceIn = model_->sequenceIn(); int sequenceOut = model_->sequenceOut(); const int * pivotVariable = model_->pivotVariable(); int pivotRow = model_->pivotRow(); pivotSequence_ = pivotRow; devex_ = 0.0; // Can't create alternateWeights_ as packed as needed unpacked if (!input->packedMode()) { if (pivotRow >= 0) { if (switchType == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex_ += work[iRow] * work[iRow]; newWork[iRow] = -2.0 * work[iRow]; } newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); devex_ += ADD_ONE; weights_[sequenceOut] = 1.0 + ADD_ONE; CoinMemcpyN(which, number, newWhich); alternateWeights_->setNumElements(number); } else { if ((mode_ != 4 && mode_ != 5) || numberSwitched_ > 1) { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[iRow] * work[iRow]; newWork[iRow] = -2.0 * work[iRow]; newWhich[newNumber++] = iRow; } } if (!newWork[pivotRow] && devex_ > 0.0) newWhich[newNumber++] = pivotRow; // add if not already in newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) devex_ += work[iRow] * work[iRow]; } } if (reference(sequenceIn)) { devex_ += 1.0; } else { } if (reference(sequenceOut)) { weights_[sequenceOut] = 1.0 + 1.0; } else { weights_[sequenceOut] = 1.0; } alternateWeights_->setNumElements(newNumber); } } else { if (switchType == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex_ += work[iRow] * work[iRow]; } devex_ += ADD_ONE; } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[iRow] * work[iRow]; } } if (reference(sequenceIn)) devex_ += 1.0; } } } else { // packed input if (pivotRow >= 0) { if (switchType == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex_ += work[i] * work[i]; newWork[iRow] = -2.0 * work[i]; } newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); devex_ += ADD_ONE; weights_[sequenceOut] = 1.0 + ADD_ONE; CoinMemcpyN(which, number, newWhich); alternateWeights_->setNumElements(number); } else { if ((mode_ != 4 && mode_ != 5) || numberSwitched_ > 1) { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[i] * work[i]; newWork[iRow] = -2.0 * work[i]; newWhich[newNumber++] = iRow; } } if (!newWork[pivotRow] && devex_ > 0.0) newWhich[newNumber++] = pivotRow; // add if not already in newWork[pivotRow] = -2.0 * CoinMax(devex_, 0.0); } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) devex_ += work[i] * work[i]; } } if (reference(sequenceIn)) { devex_ += 1.0; } else { } if (reference(sequenceOut)) { weights_[sequenceOut] = 1.0 + 1.0; } else { weights_[sequenceOut] = 1.0; } alternateWeights_->setNumElements(newNumber); } } else { if (switchType == 1) { for (i = 0; i < number; i++) { devex_ += work[i] * work[i]; } devex_ += ADD_ONE; } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex_ += work[i] * work[i]; } } if (reference(sequenceIn)) devex_ += 1.0; } } } double oldDevex = weights_[sequenceIn]; #ifdef CLP_DEBUG if ((model_->messageHandler()->logLevel() & 32)) printf("old weight %g, new %g\n", oldDevex, devex_); #endif double check = CoinMax(devex_, oldDevex) + 0.1; weights_[sequenceIn] = devex_; double testValue = 0.1; if (mode_ == 4 && numberSwitched_ == 1) testValue = 0.5; if ( fabs ( devex_ - oldDevex ) > testValue * check ) { #ifdef CLP_DEBUG if ((model_->messageHandler()->logLevel() & 48) == 16) printf("old weight %g, new %g\n", oldDevex, devex_); #endif //printf("old weight %g, new %g\n",oldDevex,devex_); testValue = 0.99; if (mode_ == 1) testValue = 1.01e1; // make unlikely to do if steepest else if (mode_ == 4 && numberSwitched_ == 1) testValue = 0.9; double difference = fabs(devex_ - oldDevex); if ( difference > testValue * check ) { // need to redo model_->messageHandler()->message(CLP_INITIALIZE_STEEP, *model_->messagesPointer()) << oldDevex << devex_ << CoinMessageEol; initializeWeights(); } } if (pivotRow >= 0) { // set outgoing weight here weights_[model_->sequenceOut()] = devex_ / (model_->alpha() * model_->alpha()); } } // Checks accuracy - just for debug void ClpPrimalColumnSteepest::checkAccuracy(int sequence, double relativeTolerance, CoinIndexedVector * rowArray1, CoinIndexedVector * rowArray2) { if ((mode_ == 4 || mode_ == 5) && !numberSwitched_) return; model_->unpack(rowArray1, sequence); model_->factorization()->updateColumn(rowArray2, rowArray1); int number = rowArray1->getNumElements(); int * which = rowArray1->getIndices(); double * work = rowArray1->denseVector(); const int * pivotVariable = model_->pivotVariable(); double devex = 0.0; int i; if (mode_ == 1) { for (i = 0; i < number; i++) { int iRow = which[i]; devex += work[iRow] * work[iRow]; work[iRow] = 0.0; } devex += ADD_ONE; } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iPivot = pivotVariable[iRow]; if (reference(iPivot)) { devex += work[iRow] * work[iRow]; } work[iRow] = 0.0; } if (reference(sequence)) devex += 1.0; } double oldDevex = weights_[sequence]; double check = CoinMax(devex, oldDevex);; if ( fabs ( devex - oldDevex ) > relativeTolerance * check ) { COIN_DETAIL_PRINT(printf("check %d old weight %g, new %g\n", sequence, oldDevex, devex)); // update so won't print again weights_[sequence] = devex; } rowArray1->setNumElements(0); } // Initialize weights void ClpPrimalColumnSteepest::initializeWeights() { int numberRows = model_->numberRows(); int numberColumns = model_->numberColumns(); int number = numberRows + numberColumns; int iSequence; if (mode_ != 1) { // initialize to 1.0 // and set reference framework if (!reference_) { int nWords = (number + 31) >> 5; reference_ = new unsigned int[nWords]; CoinZeroN(reference_, nWords); } for (iSequence = 0; iSequence < number; iSequence++) { weights_[iSequence] = 1.0; if (model_->getStatus(iSequence) == ClpSimplex::basic) { setReference(iSequence, false); } else { setReference(iSequence, true); } } } else { CoinIndexedVector * temp = new CoinIndexedVector(); temp->reserve(numberRows + model_->factorization()->maximumPivots()); double * array = alternateWeights_->denseVector(); int * which = alternateWeights_->getIndices(); for (iSequence = 0; iSequence < number; iSequence++) { weights_[iSequence] = 1.0 + ADD_ONE; if (model_->getStatus(iSequence) != ClpSimplex::basic && model_->getStatus(iSequence) != ClpSimplex::isFixed) { model_->unpack(alternateWeights_, iSequence); double value = ADD_ONE; model_->factorization()->updateColumn(temp, alternateWeights_); int number = alternateWeights_->getNumElements(); int j; for (j = 0; j < number; j++) { int iRow = which[j]; value += array[iRow] * array[iRow]; array[iRow] = 0.0; } alternateWeights_->setNumElements(0); weights_[iSequence] = value; } } delete temp; } } // Gets rid of all arrays void ClpPrimalColumnSteepest::clearArrays() { if (persistence_ == normal) { delete [] weights_; weights_ = NULL; delete infeasible_; infeasible_ = NULL; delete alternateWeights_; alternateWeights_ = NULL; delete [] savedWeights_; savedWeights_ = NULL; delete [] reference_; reference_ = NULL; } pivotSequence_ = -1; state_ = -1; savedPivotSequence_ = -1; savedSequenceOut_ = -1; devex_ = 0.0; } // Returns true if would not find any column bool ClpPrimalColumnSteepest::looksOptimal() const { if (looksOptimal_) return true; // user overrode //**** THIS MUST MATCH the action coding above double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (!model_->factorization()->pivots()) checkTolerance = 1.0e-6; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } int number = model_->numberRows() + model_->numberColumns(); int iSequence; double * reducedCost = model_->djRegion(); int numberInfeasible = 0; if (!model_->nonLinearCost()->lookBothWays()) { for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) numberInfeasible++; break; case ClpSimplex::atUpperBound: if (value > tolerance) numberInfeasible++; break; case ClpSimplex::atLowerBound: if (value < -tolerance) numberInfeasible++; } } } else { ClpNonLinearCost * nonLinear = model_->nonLinearCost(); // can go both ways for (iSequence = 0; iSequence < number; iSequence++) { double value = reducedCost[iSequence]; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: if (fabs(value) > FREE_ACCEPT * tolerance) numberInfeasible++; break; case ClpSimplex::atUpperBound: if (value > tolerance) { numberInfeasible++; } else { // look other way - change up should be negative value -= nonLinear->changeUpInCost(iSequence); if (value < -tolerance) numberInfeasible++; } break; case ClpSimplex::atLowerBound: if (value < -tolerance) { numberInfeasible++; } else { // look other way - change down should be positive value -= nonLinear->changeDownInCost(iSequence); if (value > tolerance) numberInfeasible++; } } } } return numberInfeasible == 0; } /* Returns number of extra columns for sprint algorithm - 0 means off. Also number of iterations before recompute */ int ClpPrimalColumnSteepest::numberSprintColumns(int & numberIterations) const { numberIterations = 0; int numberAdd = 0; if (!numberSwitched_ && mode_ >= 10) { numberIterations = CoinMin(2000, model_->numberRows() / 5); numberIterations = CoinMax(numberIterations, model_->factorizationFrequency()); numberIterations = CoinMax(numberIterations, 500); if (mode_ == 10) { numberAdd = CoinMax(300, model_->numberColumns() / 10); numberAdd = CoinMax(numberAdd, model_->numberRows() / 5); // fake all //numberAdd=1000000; numberAdd = CoinMin(numberAdd, model_->numberColumns()); } else { abort(); } } return numberAdd; } // Switch off sprint idea void ClpPrimalColumnSteepest::switchOffSprint() { numberSwitched_ = 10; } // Update djs doing partial pricing (dantzig) int ClpPrimalColumnSteepest::partialPricing(CoinIndexedVector * updates, CoinIndexedVector * spareRow2, int numberWanted, int numberLook) { int number = 0; int * index; double * updateBy; double * reducedCost; double saveTolerance = model_->currentDualTolerance(); double tolerance = model_->currentDualTolerance(); // we can't really trust infeasibilities if there is dual error // this coding has to mimic coding in checkDualSolution double error = CoinMin(1.0e-2, model_->largestDualError()); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; if(model_->numberIterations() < model_->lastBadIteration() + 200) { // we can't really trust infeasibilities if there is dual error double checkTolerance = 1.0e-8; if (!model_->factorization()->pivots()) checkTolerance = 1.0e-6; if (model_->largestDualError() > checkTolerance) tolerance *= model_->largestDualError() / checkTolerance; // But cap tolerance = CoinMin(1000.0, tolerance); } if (model_->factorization()->pivots() && model_->numberPrimalInfeasibilities()) tolerance = CoinMax(tolerance, 1.0e-10 * model_->infeasibilityCost()); // So partial pricing can use model_->setCurrentDualTolerance(tolerance); model_->factorization()->updateColumnTranspose(spareRow2, updates); int numberColumns = model_->numberColumns(); // Rows reducedCost = model_->djRegion(0); number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); int j; double * duals = model_->dualRowSolution(); for (j = 0; j < number; j++) { int iSequence = index[j]; double value = duals[iSequence]; value -= updateBy[j]; updateBy[j] = 0.0; duals[iSequence] = value; } //#define CLP_DEBUG #ifdef CLP_DEBUG // check duals { int numberRows = model_->numberRows(); //work space CoinIndexedVector arrayVector; arrayVector.reserve(numberRows + 1000); CoinIndexedVector workSpace; workSpace.reserve(numberRows + 1000); int iRow; double * array = arrayVector.denseVector(); int * index = arrayVector.getIndices(); int number = 0; int * pivotVariable = model_->pivotVariable(); double * cost = model_->costRegion(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = cost[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector.setNumElements(number); // Extended duals before "updateTranspose" model_->clpMatrix()->dualExpanded(model_, &arrayVector, NULL, 0); // Btran basic costs model_->factorization()->updateColumnTranspose(&workSpace, &arrayVector); // now look at dual solution for (iRow = 0; iRow < numberRows; iRow++) { // slack double value = array[iRow]; if (fabs(duals[iRow] - value) > 1.0e-3) printf("bad row %d old dual %g new %g\n", iRow, duals[iRow], value); //duals[iRow]=value; } } #endif #undef CLP_DEBUG double bestDj = tolerance; int bestSequence = -1; const double * cost = model_->costRegion(1); model_->clpMatrix()->setOriginalWanted(numberWanted); model_->clpMatrix()->setCurrentWanted(numberWanted); int iPassR = 0, iPassC = 0; // Setup two passes // This biases towards picking row variables // This probably should be fixed int startR[4]; const int * which = infeasible_->getIndices(); int nSlacks = infeasible_->getNumElements(); startR[1] = nSlacks; startR[2] = 0; double randomR = model_->randomNumberGenerator()->randomDouble(); double dstart = static_cast (nSlacks) * randomR; startR[0] = static_cast (dstart); startR[3] = startR[0]; double startC[4]; startC[1] = 1.0; startC[2] = 0; double randomC = model_->randomNumberGenerator()->randomDouble(); startC[0] = randomC; startC[3] = randomC; reducedCost = model_->djRegion(1); int sequenceOut = model_->sequenceOut(); double * duals2 = duals - numberColumns; int chunk = CoinMin(1024, (numberColumns + nSlacks) / 32); #ifdef COIN_DETAIL if (model_->numberIterations() % 1000 == 0 && model_->logLevel() > 1) { printf("%d wanted, nSlacks %d, chunk %d\n", numberWanted, nSlacks, chunk); int i; for (i = 0; i < 4; i++) printf("start R %d C %g ", startR[i], startC[i]); printf("\n"); } #endif chunk = CoinMax(chunk, 256); bool finishedR = false, finishedC = false; bool doingR = randomR > randomC; //doingR=false; int saveNumberWanted = numberWanted; while (!finishedR || !finishedC) { if (finishedR) doingR = false; if (doingR) { int saveSequence = bestSequence; int start = startR[iPassR]; int end = CoinMin(startR[iPassR+1], start + chunk / 2); int jSequence; for (jSequence = start; jSequence < end; jSequence++) { int iSequence = which[jSequence]; if (iSequence != sequenceOut) { double value; ClpSimplex::Status status = model_->getStatus(iSequence); switch(status) { case ClpSimplex::basic: case ClpSimplex::isFixed: break; case ClpSimplex::isFree: case ClpSimplex::superBasic: value = fabs(cost[iSequence] + duals2[iSequence]); if (value > FREE_ACCEPT * tolerance) { numberWanted--; // we are going to bias towards free (but only if reasonable) value *= FREE_BIAS; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atUpperBound: value = cost[iSequence] + duals2[iSequence]; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; case ClpSimplex::atLowerBound: value = -(cost[iSequence] + duals2[iSequence]); if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!model_->flagged(iSequence)) { bestDj = value; bestSequence = iSequence; } else { // just to make sure we don't exit before got something numberWanted++; } } } break; } } if (!numberWanted) break; } numberLook -= (end - start); if (numberLook < 0 && (10 * (saveNumberWanted - numberWanted) > saveNumberWanted)) numberWanted = 0; // give up if (saveSequence != bestSequence) { // dj reducedCost[bestSequence] = cost[bestSequence] + duals[bestSequence-numberColumns]; bestDj = fabs(reducedCost[bestSequence]); model_->clpMatrix()->setSavedBestSequence(bestSequence); model_->clpMatrix()->setSavedBestDj(reducedCost[bestSequence]); } model_->clpMatrix()->setCurrentWanted(numberWanted); if (!numberWanted) break; doingR = false; // update start startR[iPassR] = jSequence; if (jSequence >= startR[iPassR+1]) { if (iPassR) finishedR = true; else iPassR = 2; } } if (finishedC) doingR = true; if (!doingR) { int saveSequence = bestSequence; // Columns double start = startC[iPassC]; // If we put this idea back then each function needs to update endFraction ** #if 0 double dchunk = (static_cast chunk) / (static_cast numberColumns); double end = CoinMin(startC[iPassC+1], start + dchunk);; #else double end = startC[iPassC+1]; // force end #endif model_->clpMatrix()->partialPricing(model_, start, end, bestSequence, numberWanted); numberWanted = model_->clpMatrix()->currentWanted(); numberLook -= static_cast ((end - start) * numberColumns); if (numberLook < 0 && (10 * (saveNumberWanted - numberWanted) > saveNumberWanted)) numberWanted = 0; // give up if (saveSequence != bestSequence) { // dj bestDj = fabs(model_->clpMatrix()->reducedCost(model_, bestSequence)); } if (!numberWanted) break; doingR = true; // update start startC[iPassC] = end; if (end >= startC[iPassC+1] - 1.0e-8) { if (iPassC) finishedC = true; else iPassC = 2; } } } updates->setNumElements(0); // Restore tolerance model_->setCurrentDualTolerance(saveTolerance); // Now create variable if column generation model_->clpMatrix()->createVariable(model_, bestSequence); #ifndef NDEBUG if (bestSequence >= 0) { if (model_->getStatus(bestSequence) == ClpSimplex::atLowerBound) assert(model_->reducedCost(bestSequence) < 0.0); if (model_->getStatus(bestSequence) == ClpSimplex::atUpperBound) assert(model_->reducedCost(bestSequence) > 0.0); } #endif return bestSequence; } Clp-1.15.10/src/ClpMatrixBase.cpp0000644000076600007660000005344511510657452015065 0ustar coincoin/* $Id: ClpMatrixBase.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpMatrixBase.hpp" #include "ClpSimplex.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpMatrixBase::ClpMatrixBase () : rhsOffset_(NULL), startFraction_(0.0), endFraction_(1.0), savedBestDj_(0.0), originalWanted_(0), currentWanted_(0), savedBestSequence_(-1), type_(-1), lastRefresh_(-1), refreshFrequency_(0), minimumObjectsScan_(-1), minimumGoodReducedCosts_(-1), trueSequenceIn_(-1), trueSequenceOut_(-1), skipDualCheck_(false) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpMatrixBase::ClpMatrixBase (const ClpMatrixBase & rhs) : type_(rhs.type_), skipDualCheck_(rhs.skipDualCheck_) { startFraction_ = rhs.startFraction_; endFraction_ = rhs.endFraction_; savedBestDj_ = rhs.savedBestDj_; originalWanted_ = rhs.originalWanted_; currentWanted_ = rhs.currentWanted_; savedBestSequence_ = rhs.savedBestSequence_; lastRefresh_ = rhs.lastRefresh_; refreshFrequency_ = rhs.refreshFrequency_; minimumObjectsScan_ = rhs.minimumObjectsScan_; minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_; trueSequenceIn_ = rhs.trueSequenceIn_; trueSequenceOut_ = rhs.trueSequenceOut_; skipDualCheck_ = rhs.skipDualCheck_; int numberRows = rhs.getNumRows(); if (rhs.rhsOffset_ && numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_, numberRows); } else { rhsOffset_ = NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpMatrixBase::~ClpMatrixBase () { delete [] rhsOffset_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpMatrixBase & ClpMatrixBase::operator=(const ClpMatrixBase& rhs) { if (this != &rhs) { type_ = rhs.type_; delete [] rhsOffset_; int numberRows = rhs.getNumRows(); if (rhs.rhsOffset_ && numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_, numberRows); } else { rhsOffset_ = NULL; } startFraction_ = rhs.startFraction_; endFraction_ = rhs.endFraction_; savedBestDj_ = rhs.savedBestDj_; originalWanted_ = rhs.originalWanted_; currentWanted_ = rhs.currentWanted_; savedBestSequence_ = rhs.savedBestSequence_; lastRefresh_ = rhs.lastRefresh_; refreshFrequency_ = rhs.refreshFrequency_; minimumObjectsScan_ = rhs.minimumObjectsScan_; minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_; trueSequenceIn_ = rhs.trueSequenceIn_; trueSequenceOut_ = rhs.trueSequenceOut_; skipDualCheck_ = rhs.skipDualCheck_; } return *this; } // And for scaling - default aborts for when scaling not supported void ClpMatrixBase::times(double scalar, const double * x, double * y, const double * rowScale, const double * /*columnScale*/) const { if (rowScale) { std::cerr << "Scaling not supported - ClpMatrixBase" << std::endl; abort(); } else { times(scalar, x, y); } } // And for scaling - default aborts for when scaling not supported void ClpMatrixBase::transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * /*columnScale*/, double * /*spare*/) const { if (rowScale) { std::cerr << "Scaling not supported - ClpMatrixBase" << std::endl; abort(); } else { transposeTimes(scalar, x, y); } } /* Subset clone (without gaps). Duplicates are allowed and order is as given. Derived classes need not provide this as it may not always make sense */ ClpMatrixBase * ClpMatrixBase::subsetClone ( int /*numberRows*/, const int * /*whichRows*/, int /*numberColumns*/, const int * /*whichColumns*/) const { std::cerr << "subsetClone not supported - ClpMatrixBase" << std::endl; abort(); return NULL; } /* Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector Default returns vector of ones */ CoinBigIndex * ClpMatrixBase::dubiousWeights(const ClpSimplex * model, int * /*inputWeights*/) const { int number = model->numberRows() + model->numberColumns(); CoinBigIndex * weights = new CoinBigIndex[number]; int i; for (i = 0; i < number; i++) weights[i] = 1; return weights; } #ifndef CLP_NO_VECTOR // Append Columns void ClpMatrixBase::appendCols(int /*number*/, const CoinPackedVectorBase * const * /*columns*/) { std::cerr << "appendCols not supported - ClpMatrixBase" << std::endl; abort(); } // Append Rows void ClpMatrixBase::appendRows(int /*number*/, const CoinPackedVectorBase * const * /*rows*/) { std::cerr << "appendRows not supported - ClpMatrixBase" << std::endl; abort(); } #endif /* Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ void ClpMatrixBase::rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive) { smallestNegative = 0.0; largestNegative = 0.0; smallestPositive = 0.0; largestPositive = 0.0; } /* The length of a major-dimension vector. */ int ClpMatrixBase::getVectorLength(int index) const { return getVectorLengths()[index]; } // Says whether it can do partial pricing bool ClpMatrixBase::canDoPartialPricing() const { return false; // default is no } /* Return x *A in z but just for number indices in y. Default cheats with fake CoinIndexedVector and then calls subsetTransposeTimes */ void ClpMatrixBase::listTransposeTimes(const ClpSimplex * model, double * x, int * y, int number, double * z) const { CoinIndexedVector pi; CoinIndexedVector list; CoinIndexedVector output; int * saveIndices = list.getIndices(); list.setNumElements(number); list.setIndexVector(y); double * savePi = pi.denseVector(); pi.setDenseVector(x); double * saveOutput = output.denseVector(); output.setDenseVector(z); output.setPacked(); subsetTransposeTimes(model, &pi, &list, &output); // restore settings list.setIndexVector(saveIndices); pi.setDenseVector(savePi); output.setDenseVector(saveOutput); } // Partial pricing void ClpMatrixBase::partialPricing(ClpSimplex * , double , double , int & , int & ) { std::cerr << "partialPricing not supported - ClpMatrixBase" << std::endl; abort(); } /* expands an updated column to allow for extra rows which the main solver does not know about and returns number added. If the arrays are NULL then returns number of extra entries needed. This will normally be a no-op - it is in for GUB! */ int ClpMatrixBase::extendUpdated(ClpSimplex * , CoinIndexedVector * , int ) { return 0; } /* utility primal function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpMatrixBase::primalExpanded(ClpSimplex * , int ) { } /* utility dual function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpMatrixBase::dualExpanded(ClpSimplex * , CoinIndexedVector * , double * , int ) { } /* general utility function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ int ClpMatrixBase::generalExpanded(ClpSimplex * model, int mode, int &number) { int returnCode = 0; switch (mode) { // Fill in pivotVariable but not for key variables case 0: { int i; int numberBasic = number; int numberColumns = model->numberColumns(); // Use different array so can build from true pivotVariable_ //int * pivotVariable = model->pivotVariable(); int * pivotVariable = model->rowArray(0)->getIndices(); for (i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) pivotVariable[numberBasic++] = i; } number = numberBasic; } break; // Do initial extra rows + maximum basic case 2: { number = model->numberRows(); } break; // To see if can dual or primal case 4: { returnCode = 3; } break; default: break; } return returnCode; } // Sets up an effective RHS void ClpMatrixBase::useEffectiveRhs(ClpSimplex * ) { std::cerr << "useEffectiveRhs not supported - ClpMatrixBase" << std::endl; abort(); } /* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpMatrixBase::rhsOffset(ClpSimplex * model, bool forceRefresh, bool #ifdef CLP_DEBUG check #endif ) { if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; double * rhs = new double[numberRows]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(), numberColumns, solution); int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic) rhs[iRow] = solutionSlack[iRow]; else rhs[iRow] = 0.0; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } times(-1.0, solution, rhs); delete [] solution; for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** bad effective %d - true %g old %g\n", iRow, rhs[iRow], rhsOffset_[iRow]); } } #endif if (forceRefresh || (refreshFrequency_ && model->numberIterations() >= lastRefresh_ + refreshFrequency_)) { // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(), numberColumns, solution); for (int iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic) rhsOffset_[iRow] = solutionSlack[iRow]; else rhsOffset_[iRow] = 0.0; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } times(-1.0, solution, rhsOffset_); delete [] solution; lastRefresh_ = model->numberIterations(); } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpMatrixBase::updatePivot(ClpSimplex * model, double oldInValue, double ) { if (rhsOffset_) { // update effective rhs int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); double * solution = model->solutionRegion(); int numberColumns = model->numberColumns(); if (sequenceIn == sequenceOut) { if (sequenceIn < numberColumns) add(model, rhsOffset_, sequenceIn, oldInValue - solution[sequenceIn]); } else { if (sequenceIn < numberColumns) add(model, rhsOffset_, sequenceIn, oldInValue); if (sequenceOut < numberColumns) add(model, rhsOffset_, sequenceOut, -solution[sequenceOut]); } } return 0; } int ClpMatrixBase::hiddenRows() const { return 0; } /* Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ void ClpMatrixBase::createVariable(ClpSimplex *, int &) { } // Returns reduced cost of a variable double ClpMatrixBase::reducedCost(ClpSimplex * model, int sequence) const { int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); if (sequence < numberRows + numberColumns) return model->djRegion()[sequence]; else return savedBestDj_; } /* Just for debug if odd type matrix. Returns number and sum of primal infeasibilities. */ int ClpMatrixBase::checkFeasible(ClpSimplex * model, double & sum) const { int numberRows = model->numberRows(); double * rhs = new double[numberRows]; int numberColumns = model->numberColumns(); int iRow; CoinZeroN(rhs, numberRows); times(1.0, model->solutionRegion(), rhs, model->rowScale(), model->columnScale()); int iColumn; int logLevel = model->messageHandler()->logLevel(); int numberInfeasible = 0; const double * rowLower = model->lowerRegion(0); const double * rowUpper = model->upperRegion(0); const double * solution; solution = model->solutionRegion(0); double tolerance = model->primalTolerance() * 1.01; sum = 0.0; for (iRow = 0; iRow < numberRows; iRow++) { double value = rhs[iRow]; double value2 = solution[iRow]; if (logLevel > 3) { if (fabs(value - value2) > 1.0e-8) printf("Row %d stored %g, computed %g\n", iRow, value2, value); } if (value < rowLower[iRow] - tolerance || value > rowUpper[iRow] + tolerance) { numberInfeasible++; sum += CoinMax(rowLower[iRow] - value, value - rowUpper[iRow]); } if (value2 > rowLower[iRow] + tolerance && value2 < rowUpper[iRow] - tolerance && model->getRowStatus(iRow) != ClpSimplex::basic) { assert (model->getRowStatus(iRow) == ClpSimplex::superBasic); } } const double * columnLower = model->lowerRegion(1); const double * columnUpper = model->upperRegion(1); solution = model->solutionRegion(1); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; if (value < columnLower[iColumn] - tolerance || value > columnUpper[iColumn] + tolerance) { numberInfeasible++; sum += CoinMax(columnLower[iColumn] - value, value - columnUpper[iColumn]); } if (value > columnLower[iColumn] + tolerance && value < columnUpper[iColumn] - tolerance && model->getColumnStatus(iColumn) != ClpSimplex::basic) { assert (model->getColumnStatus(iColumn) == ClpSimplex::superBasic); } } delete [] rhs; return numberInfeasible; } // These have to match ClpPrimalColumnSteepest version #define reference(i) (((reference[i>>5]>>(i&31))&1)!=0) // Updates second array for steepest and does devex weights (need not be coded) void ClpMatrixBase::subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { // get subset which have nonzero tableau elements subsetTransposeTimes(model, pi2, dj1, dj2); bool killDjs = (scaleFactor == 0.0); if (!scaleFactor) scaleFactor = 1.0; // columns int number = dj1->getNumElements(); const int * index = dj1->getIndices(); double * updateBy = dj1->denseVector(); double * updateBy2 = dj2->denseVector(); for (int j = 0; j < number; j++) { double thisWeight; double pivot; double pivotSquared; int iSequence = index[j]; double value2 = updateBy[j]; if (killDjs) updateBy[j] = 0.0; double modification = updateBy2[j]; updateBy2[j] = 0.0; ClpSimplex::Status status = model->getStatus(iSequence); if (status != ClpSimplex::basic && status != ClpSimplex::isFixed) { thisWeight = weights[iSequence]; pivot = value2 * scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeight < DEVEX_TRY_NORM) { if (referenceIn < 0.0) { // steepest thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); } else { // exact thisWeight = referenceIn * pivotSquared; if (reference(iSequence)) thisWeight += 1.0; thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); } } weights[iSequence] = thisWeight; } } dj2->setNumElements(0); } // Correct sequence in and out to give true value void ClpMatrixBase::correctSequence(const ClpSimplex * , int & , int & ) { } // Really scale matrix void ClpMatrixBase::reallyScale(const double * , const double * ) { std::cerr << "reallyScale not supported - ClpMatrixBase" << std::endl; abort(); } // Updates two arrays for steepest void ClpMatrixBase::transposeTimes2(const ClpSimplex * , const CoinIndexedVector * , CoinIndexedVector *, const CoinIndexedVector * , CoinIndexedVector * , double , double , // Array for exact devex to say what is in reference framework unsigned int * , double * , double ) { std::cerr << "transposeTimes2 not supported - ClpMatrixBase" << std::endl; abort(); } /* Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ void ClpMatrixBase::setDimensions(int , int ) { // If odd matrix assume user knows what they are doing } /* Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ int ClpMatrixBase::appendMatrix(int , int , const CoinBigIndex * , const int * , const double * , int ) { std::cerr << "appendMatrix not supported - ClpMatrixBase" << std::endl; abort(); return -1; } /* Modify one element of packed matrix. An element may be added. This works for either ordering If the new element is zero it will be deleted unless keepZero true */ void ClpMatrixBase::modifyCoefficient(int , int , double , bool ) { std::cerr << "modifyCoefficient not supported - ClpMatrixBase" << std::endl; abort(); } #if COIN_LONG_WORK // For long double versions (aborts if not supported) void ClpMatrixBase::times(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const { std::cerr << "long times not supported - ClpMatrixBase" << std::endl; abort(); } void ClpMatrixBase::transposeTimes(CoinWorkDouble scalar, const CoinWorkDouble * x, CoinWorkDouble * y) const { std::cerr << "long transposeTimes not supported - ClpMatrixBase" << std::endl; abort(); } #endif Clp-1.15.10/src/AbcSimplexFactorization.cpp0000644000076600007660000005064712101105055017134 0ustar coincoin/* $Id: AbcSimplexFactorization.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #define USE_DENSE_FAC -1 #define USE_SMALL_FAC 200 #define USE_LONG_FAC 10000 #include "CoinPragma.hpp" #include "AbcSimplexFactorization.hpp" #include "ClpFactorization.hpp" #include "ClpMessage.hpp" #include "CoinAbcCommon.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "AbcSimplex.hpp" #include "AbcSimplexDual.hpp" #include "AbcMatrix.hpp" #include "CoinAbcFactorization.hpp" //#include "CoinDenseFactorization.hpp" #ifdef ABC_JUST_ONE_FACTORIZATION #define CoinAbcFactorization CoinAbcBaseFactorization #define CoinAbcSmallFactorization CoinAbcBaseFactorization #define CoinAbcLongFactorization CoinAbcBaseFactorization #define CoinAbcOrderedFactorization CoinAbcBaseFactorization #endif #ifndef ABC_LONG_FACTORIZATION #undef CoinAbcLongFactorization #define CoinAbcLongFactorization CoinAbcOrderedFactorization #endif #ifdef ABC_TEMPORARY_FACTORIZATION #undef CoinAbcSmallFactorization #define CoinAbcSmallFactorization CoinAbcOrderedFactorization #endif //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcSimplexFactorization::AbcSimplexFactorization (int /*numberRows*/) { model_=NULL; coinAbcFactorization_ = new CoinAbcFactorization(); forceB_ = 0; goDenseThreshold_ = USE_DENSE_FAC; goSmallThreshold_ = USE_SMALL_FAC; goLongThreshold_ = USE_LONG_FAC; numberSlacks_=0; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcSimplexFactorization::AbcSimplexFactorization (const AbcSimplexFactorization & rhs, int denseIfSmaller) { forceB_ = rhs.forceB_; goDenseThreshold_ = rhs.goDenseThreshold_; goSmallThreshold_ = rhs.goSmallThreshold_; goLongThreshold_ = rhs.goLongThreshold_; numberSlacks_=rhs.numberSlacks_; int goDense = 0; model_=rhs.model_; if (denseIfSmaller > 0 && denseIfSmaller <= goDenseThreshold_) { CoinAbcDenseFactorization * denseR = dynamic_cast(rhs.coinAbcFactorization_); if (!denseR) goDense = 1; } if (denseIfSmaller > 0 && !rhs.coinAbcFactorization_) { if (denseIfSmaller <= goDenseThreshold_) goDense = 1; else if (denseIfSmaller <= goSmallThreshold_) goDense = 2; else if (denseIfSmaller >= goLongThreshold_) goDense = 3; } else if (denseIfSmaller < 0) { if (-denseIfSmaller <= goDenseThreshold_) goDense = 1; else if (-denseIfSmaller <= goSmallThreshold_) goDense = 2; else if (-denseIfSmaller >= goLongThreshold_) goDense = 3; } if (rhs.coinAbcFactorization_ && (denseIfSmaller >= 0 || !goDense)) coinAbcFactorization_ = rhs.coinAbcFactorization_->clone(); else coinAbcFactorization_ = NULL; if (goDense) { delete coinAbcFactorization_; if (goDense == 1) coinAbcFactorization_ = new CoinAbcDenseFactorization(); else if (goDense == 2) coinAbcFactorization_ = new CoinAbcSmallFactorization(); else if (goDense == 3) coinAbcFactorization_ = new CoinAbcLongFactorization(); else coinAbcFactorization_ = new CoinAbcFactorization(); assert (coinAbcFactorization_); coinAbcFactorization_->maximumPivots(rhs.coinAbcFactorization_->maximumPivots()); coinAbcFactorization_->pivotTolerance(rhs.coinAbcFactorization_->pivotTolerance()); coinAbcFactorization_->zeroTolerance(rhs.coinAbcFactorization_->zeroTolerance()); } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcSimplexFactorization::~AbcSimplexFactorization () { delete coinAbcFactorization_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcSimplexFactorization & AbcSimplexFactorization::operator=(const AbcSimplexFactorization& rhs) { if (this != &rhs) { forceB_ = rhs.forceB_; model_=rhs.model_; goDenseThreshold_ = rhs.goDenseThreshold_; goSmallThreshold_ = rhs.goSmallThreshold_; goLongThreshold_ = rhs.goLongThreshold_; numberSlacks_=rhs.numberSlacks_; if (rhs.coinAbcFactorization_) { delete coinAbcFactorization_; coinAbcFactorization_ = rhs.coinAbcFactorization_->clone(); } } return *this; } // Go over to dense code void AbcSimplexFactorization::goDenseOrSmall(int numberRows) { if (!forceB_) { delete coinAbcFactorization_; if (numberRows <= goDenseThreshold_) { coinAbcFactorization_ = new CoinAbcDenseFactorization(); } else if (numberRows <= goSmallThreshold_) { coinAbcFactorization_ = new CoinAbcSmallFactorization(); } else if (numberRows >= goLongThreshold_) { coinAbcFactorization_ = new CoinAbcLongFactorization(); } else { coinAbcFactorization_ = new CoinAbcFactorization(); } } } // If nonzero force use of 1,dense 2,small 3,long void AbcSimplexFactorization::forceOtherFactorization(int which) { delete coinAbcFactorization_; forceB_ = 0; coinAbcFactorization_ = NULL; if (which > 0 && which < 6) { forceB_ = which; switch (which) { case 1: coinAbcFactorization_ = new CoinAbcDenseFactorization(); goDenseThreshold_ = COIN_INT_MAX; break; case 2: case 4: coinAbcFactorization_ = new CoinAbcSmallFactorization(); goSmallThreshold_ = COIN_INT_MAX; break; case 3: case 5: coinAbcFactorization_ = new CoinAbcLongFactorization(); goLongThreshold_ = 0; break; } } else { coinAbcFactorization_ = new CoinAbcFactorization(); } } // Synchronize stuff void AbcSimplexFactorization::synchronize(const ClpFactorization * otherFactorization,const AbcSimplex * model) { goDenseThreshold_=otherFactorization->goDenseThreshold(); goSmallThreshold_=otherFactorization->goSmallThreshold(); goLongThreshold_=otherFactorization->goOslThreshold(); //forceOtherFactorization(otherFactorization->typeOfFactorization()); goDenseOrSmall(model->numberRows()); maximumPivots(static_cast(otherFactorization->maximumPivots()*1.2)); } int AbcSimplexFactorization::factorize ( AbcSimplex * model, int solveType, bool valuesPass) { model_= model; AbcMatrix * matrix = model->abcMatrix(); int numberRows = model->numberRows(); if (!numberRows) return 0; bool anyChanged = false; coinAbcFactorization_->setStatus(-99); const int * COIN_RESTRICT pivotVariable = model->pivotVariable(); //returns 0 -okay, -1 singular, -2 too many in basis */ // allow dense int solveMode = coinAbcFactorization_->solveMode()&1; if (model->numberIterations()>model->baseIteration()) solveMode += 8; else solveMode = 1; // try dense if (valuesPass) solveMode += 4; coinAbcFactorization_->setSolveMode(solveMode); while (status() < -98) { int i; int numberBasic = 0; // Move pivot variables across if they look good int * COIN_RESTRICT pivotTemp = model->usefulArray(0)->getIndices(); #ifndef NDEBUG model_->checkArrays(); #endif assert (!model->usefulArray(0)->getNumElements()); // Seems to prefer things in order so quickest // way is to go though like this for (i = 0; i < numberRows; i++) { if (pivotVariable[i]=numberRows) pivotTemp[numberBasic++] = pivotVariable[i]; } CoinBigIndex numberElements = numberSlacks_; // compute how much in basis int numberColumnBasic = numberBasic - numberSlacks_; numberElements += matrix->countBasis(pivotTemp + numberSlacks_, numberColumnBasic); //printf("Basis has %d slacks - size %d\n",numberSlacks_,numberElements); // Not needed for dense numberElements = 3 * numberBasic + 3 * numberElements + 20000; int numberIterations = model->numberIterations(); coinAbcFactorization_->setUsefulInformation(&numberIterations, 0); coinAbcFactorization_->getAreas ( numberRows, numberSlacks_ + numberColumnBasic, numberElements, 2 * numberElements ); #if 0 if (!model->numberIterations()) printf("do I need destructor etc in getAreas?\n"); #endif // Fill in counts so we can skip part of preProcess // This is NOT needed for dense but would be needed for later versions CoinFactorizationDouble * COIN_RESTRICT elementU; int * COIN_RESTRICT indexRowU; CoinBigIndex * COIN_RESTRICT startColumnU; int * COIN_RESTRICT numberInRow; int * COIN_RESTRICT numberInColumn; elementU = coinAbcFactorization_->elements(); indexRowU = coinAbcFactorization_->indices(); startColumnU = coinAbcFactorization_->starts(); #define slackValue 1.0 numberInRow = coinAbcFactorization_->numberInRow(); numberInColumn = coinAbcFactorization_->numberInColumn(); coinAbcFactorization_->setNumberSlacks(numberSlacks_); CoinZeroN ( numberInRow, numberRows ); CoinZeroN ( numberInColumn, numberRows ); for (i = 0; i < numberSlacks_; i++) { int iRow = pivotTemp[i]; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = slackValue; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberSlacks_] = numberSlacks_; // can change for gub so redo numberColumnBasic = numberRows - numberSlacks_; matrix->fillBasis(pivotTemp + numberSlacks_, numberColumnBasic, indexRowU, startColumnU + numberSlacks_, numberInRow, numberInColumn + numberSlacks_, elementU); numberElements = startColumnU[numberRows-1] + numberInColumn[numberRows-1]; coinAbcFactorization_->preProcess ( ); coinAbcFactorization_->factor (model); #if 0 if (model_->numberIterations()==23) { CoinAbcFactorization * factor = dynamic_cast(coinAbcFactorization_); if (factor) factor->show_self(); } #endif if (coinAbcFactorization_->status() == -1 && (coinAbcFactorization_->solveMode() & 1) != 0) { int solveMode = coinAbcFactorization_->solveMode(); solveMode --; // so bottom will be 0 coinAbcFactorization_->setSolveMode(solveMode); coinAbcFactorization_->setStatus(-99); } if (coinAbcFactorization_->status() == -99) continue; // If we get here status is 0 or -1 if (coinAbcFactorization_->status() == 0 && numberBasic == numberRows) { coinAbcFactorization_->postProcess(pivotTemp, model->pivotVariable()); model_->moveToBasic(); } else if (solveType == 0 || solveType == 2/*||solveType==1*/) { // Change pivotTemp to be correct list anyChanged = true; coinAbcFactorization_->makeNonSingular(pivotTemp); const double * COIN_RESTRICT lowerArray = model->lowerRegion(); const double * COIN_RESTRICT upperArray = model->upperRegion(); double * COIN_RESTRICT solution = model->solutionRegion(); //int * pivotVariable=model_->pivotVariable(); //int * fromExternal=model_->fromExternal(); int numberTotal=model_->numberTotal(); //can use external status_ unsigned char * COIN_RESTRICT statusArray = model_->statusArray(); CoinAbcMemset0(statusArray,numberTotal); for (int iRow=0;iRowlargeValue(); for (int iRow=0;iRow -largeValue || upper < largeValue) { if (lower!=upper) { if (fabs(value - lower) < fabs(value - upper)) { thisStatus=AbcSimplex::atLowerBound; solution[iPivot] = lower; } else { thisStatus= AbcSimplex::atUpperBound; solution[iPivot] = upper; } } else { thisStatus= AbcSimplex::isFixed; solution[iPivot] = upper; } } else { thisStatus=AbcSimplex::isFree; } } else { thisStatus=AbcSimplex::superBasic; } model_->setInternalStatus(iPivot,thisStatus); model_->setInternalStatus(jPivot,AbcSimplex::basic); // swap (solution will be wrong - but that doesn't matter as basic) model_->swap(iRow,jPivot); } } CoinAbcMemcpy(model_->pivotVariable(),pivotTemp,numberRows); #ifndef NDEBUG model_->checkConsistentPivots(); #endif // signal repeat coinAbcFactorization_->pivotTolerance(0.999); coinAbcFactorization_->setStatus(-99); } } //coinAbcFactorization_->setSolveMode(solveMode|1); if ( anyChanged && model->algorithm() < 0 && solveType > 0) { double dummyCost; static_cast (model)->changeBounds(3,dummyCost); } return coinAbcFactorization_->status(); } #if 0 /* Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots Fills in region for use later partial update already in U */ int AbcSimplexFactorization::checkReplace ( const AbcSimplex * model, CoinIndexedVector * regionSparse, int pivotRow, double &pivotCheck, double acceptablePivot) { if (pivots()==maximumPivots()) return 5; else return coinAbcFactorization_->checkReplace(model,regionSparse,pivotRow,pivotCheck,acceptablePivot); } /* Replaces one Column in basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If skipBtranU is false will do btran part partial update already in U */ int AbcSimplexFactorization::replaceColumn ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, double pivotCheck , bool skipBtranU, double acceptablePivot) { bool tab = coinAbcFactorization_->wantsTableauColumn(); int tempInfo[1]; tempInfo[0] = model->numberIterations(); coinAbcFactorization_->setUsefulInformation(tempInfo, 1); int returnCode = coinAbcFactorization_->replaceColumn(tab ? tableauColumn : regionSparse, pivotRow, pivotCheck, skipBtranU, acceptablePivot); return returnCode; } #endif /* Replaces one Column to basis, partial update already in U */ void AbcSimplexFactorization::replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ) { bool tab = coinAbcFactorization_->wantsTableauColumn(); int tempInfo[1]; tempInfo[0] = model->numberIterations(); coinAbcFactorization_->setUsefulInformation(tempInfo, 1); if (tab) coinAbcFactorization_->replaceColumnPart3(model,NULL,tableauColumn, pivotRow, tableauColumn->denseVector()[pivotRow]); else coinAbcFactorization_->replaceColumnPart3(model,regionSparse,NULL, pivotRow, alpha); } /* Replaces one Column to basis, partial update in vector */ void AbcSimplexFactorization::replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, CoinIndexedVector * partialUpdate, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ) { bool tab = coinAbcFactorization_->wantsTableauColumn(); int tempInfo[1]; tempInfo[0] = model->numberIterations(); coinAbcFactorization_->setUsefulInformation(tempInfo, 1); if (tab) coinAbcFactorization_->replaceColumnPart3(model,NULL,tableauColumn, pivotRow, tableauColumn->denseVector()[pivotRow]); else coinAbcFactorization_->replaceColumnPart3(model,regionSparse,NULL,partialUpdate, pivotRow, alpha); } #if 0 /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int AbcSimplexFactorization::updateColumnFT ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) { if (!numberRows()) return 0; int returnCode; returnCode = coinAbcFactorization_->updateColumnFT(regionSparse, regionSparse2); return returnCode; } /* Updates one column (FTRAN) from region2 number returned is negative if no room region1 starts as zero and is zero at end */ int AbcSimplexFactorization::updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const { if (!numberRows()) return 0; int returnCode; returnCode = coinAbcFactorization_->updateColumn(regionSparse, regionSparse2,true); return returnCode; } /* Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ int AbcSimplexFactorization::updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, CoinIndexedVector * regionSparse2, CoinIndexedVector * regionSparse3) { if (!numberRows()) return 0; int returnCode = 0; returnCode = coinAbcFactorization_->updateTwoColumnsFT( regionSparse1, regionSparse2, regionSparse3, true); return returnCode; } /* Updates one column (BTRAN) from region2 region1 starts as zero and is zero at end */ int AbcSimplexFactorization::updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const { if (!numberRows()) return 0; int returnCode; returnCode = coinAbcFactorization_->updateColumnTranspose(regionSparse, regionSparse2); return returnCode; } /* Updates one column for dual steepest edge weights (FTRAN) */ void AbcSimplexFactorization::updateWeights ( CoinIndexedVector & regionSparse) const { // NOTE either switch off sparse or pass in a sparseArray_ so can go parallel // may be best to use inner product approach static double fraction[2]={0.0,0.0}; static int times=0; times++; fraction[0] += static_cast(regionSparse.getNumElements())/ (static_cast(model_->numberRows())+1.0); updateColumn(regionSparse); fraction[1] += static_cast(regionSparse.getNumElements())/ (static_cast(model_->numberRows())+1.0); if ((times%1000)==0) printf("Average density %g before then %g\n", (100.0*fraction[0])/static_cast(times), (100.0*fraction[1])/static_cast(times)); } #endif /* makes a row copy of L for speed and to allow very sparse problems */ void AbcSimplexFactorization::goSparse() { abort(); coinAbcFactorization_->goSparse(); } // Set tolerances to safer of existing and given void AbcSimplexFactorization::saferTolerances ( double zeroValue, double pivotValue) { double newValue1; // better to have small tolerance even if slower if (zeroValue > 0.0) newValue1 = zeroValue; else newValue1 = -zeroTolerance() * zeroValue; newValue1 = CoinMin(zeroTolerance(),newValue1); if (newValue1>1.0e-15) zeroTolerance(newValue1); double newValue2; // better to have large tolerance even if slower if (pivotValue > 0.0) newValue2 = pivotValue; else newValue2 = -pivotTolerance() * pivotValue; newValue2 =CoinMin(CoinMax(pivotTolerance(), newValue2), 0.999); if (newValue2>pivotTolerance()) { pivotTolerance(newValue2); char line[100]; sprintf(line,"new zero tolerance %g new pivot tolerance %g", zeroTolerance(),pivotTolerance()); model_->messageHandler()->message(CLP_GENERAL2,*model_->messagesPointer()) << line << CoinMessageEol; } } // Sets factorization void AbcSimplexFactorization::setFactorization(AbcSimplexFactorization & rhs) { AbcSimplexFactorization::operator=(rhs); } Clp-1.15.10/src/CoinAbcBaseFactorization5.cpp0000644000076600007660000006554212101105055017263 0ustar coincoin/* $Id: CoinAbcBaseFactorization5.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #if ABC_NORMAL_DEBUG>0 // for conflicts extern int cilk_conflict; #endif #define UNROLL 1 #define INLINE_IT //#define INLINE_IT2 inline void scatterUpdateInline(CoinSimplexInt number, CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL==0 for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL==1 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL==2 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(static_cast(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const CoinSimplexInt * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { CoinFactorizationDouble pivotValue=0.0; for (CoinBigIndex j = 0; j < number; j ++ ) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; } #undef INLINE_IT // updateColumnR. Updates part of column (FTRANR) void CoinAbcTypeFactorization::updateColumnR ( CoinIndexedVector * regionSparse #if ABC_SMALL<2 , CoinAbcStatistics & statistics #endif #if ABC_PARALLEL ,int whichSparse #endif ) const { if ( numberR_ ) { CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector ( ); #if ABC_SMALL<3 CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinSimplexInt numberNonZero = regionSparse->getNumElements ( ); #endif const CoinBigIndex * COIN_RESTRICT startColumn = startColumnRAddress_-numberRows_; const CoinSimplexInt * COIN_RESTRICT indexRow = indexRowRAddress_; CoinSimplexInt * COIN_RESTRICT indexRowR2 = indexRowRAddress_+lengthAreaR_; if (gotRCopy()) indexRowR2 += lengthAreaR_; const CoinFactorizationDouble * COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt * COIN_RESTRICT permute = permuteAddress_; instrument_do("CoinAbcFactorizationUpdateR",sizeR); #if ABC_SMALL<2 // Size of R CoinSimplexDouble sizeR=startColumnRAddress_[numberR_]; // Work out very dubious idea of what would be fastest // Average CoinSimplexDouble averageR = sizeR/(static_cast (numberRowsExtra_)); // weights (relative to actual work) CoinSimplexDouble setMark = 0.1; // setting mark CoinSimplexDouble test1= 1.0; // starting ftran (without testPivot) CoinSimplexDouble testPivot = 2.0; // Seeing if zero etc CoinSimplexDouble startDot=2.0; // For starting dot product version // For final scan CoinSimplexDouble final = numberNonZero*1.0; CoinSimplexDouble methodTime0; // For first type methodTime0 = numberPivots_ * (testPivot + ((static_cast (numberNonZero))/(static_cast (numberRows_)) * averageR)); methodTime0 += numberNonZero *(test1 + averageR); methodTime0 += (numberNonZero+numberPivots_)*setMark; // third CoinSimplexDouble methodTime2 = sizeR + numberPivots_*startDot + numberNonZero*final; // switch off if necessary CoinSimplexInt method=0; if (!gotRCopy()||!gotSparse()||methodTime2(reinterpret_cast(mark)+whichSparse*sizeSparseArray_); } #endif // mark all rows which will be permuted for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++ ) { CoinSimplexInt iRow = permute[i]; mark[iRow]=1; } // we have another copy of R in R const CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_ + lengthAreaR_; const CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_ + lengthAreaR_; const CoinBigIndex * COIN_RESTRICT startR = startColumnRAddress_+maximumPivots_+1; // For current list order does not matter as // only affects end CoinSimplexInt newNumber=0; for (CoinSimplexInt i = 0; i < numberNonZero; i++ ) { CoinSimplexInt iRow = regionIndex[i]; CoinFactorizationDouble pivotValue = region[iRow]; assert (region[iRow]); if (!mark[iRow]) { regionIndex[newNumber++]=iRow; } CoinSimplexInt kRow=permute[iRow]; CoinSimplexInt number = numberInColumnPlus[kRow]; instrument_add(number); if (TEST_INT_NONZERO(number)) { CoinBigIndex start=startR[kRow]; #ifndef INLINE_IT CoinBigIndex end = start+number; for (CoinBigIndex j = start; j < end; j ++ ) { CoinFactorizationDouble value = elementR[j]; CoinSimplexInt jRow = indexRowR[j]; region[jRow] -= pivotValue*value; } #else CoinAbcScatterUpdate(number,pivotValue,elementR+start,indexRowR+start,region); #endif } } instrument_start("CoinAbcFactorizationUpdateRSparse2",numberRows_); numberNonZero = newNumber; for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++ ) { //move using permute_ (stored in inverse fashion) CoinSimplexInt iRow = permute[i]; CoinFactorizationDouble pivotValue = region[iRow]+region[i]; //zero out pre-permuted region[iRow] = 0.0; region[i]=0.0; if ( !TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue ) ) { int jRow=pivotRowBack[i]; assert (!region[jRow]); region[jRow]=pivotValue; CoinSimplexInt number = numberInColumnPlus[i]; instrument_add(number); if (TEST_INT_NONZERO(number)) { CoinBigIndex start=startR[i]; #ifndef INLINE_IT CoinBigIndex end = start+number; for (CoinBigIndex j = start; j < end; j ++ ) { CoinFactorizationDouble value = elementR[j]; CoinSimplexInt jRow = indexRowR[j]; region[jRow] -= pivotValue*value; } #else CoinAbcScatterUpdate(number,pivotValue,elementR+start,indexRowR+start,region); #endif } } } instrument_end(); for (CoinSimplexInt i = numberRows_; i < numberRowsExtra_; i++ ) { CoinSimplexInt iRow = permute[i]; assert (iRowsetNumElements ( numberNonZero ); #endif } #if ABC_SMALL<2 if (factorizationStatistics()) statistics.countAfterR_ += regionSparse->getNumElements(); #endif } #ifdef EARLY_FACTORIZE #include "AbcSimplex.hpp" #include "AbcMatrix.hpp" // Returns -2 if can't, -1 if singular, -99 memory, 0 OK int CoinAbcTypeFactorization::factorize (AbcSimplex * model, CoinIndexedVector & stuff) { AbcMatrix * matrix = model->abcMatrix(); setStatus(-99); int * COIN_RESTRICT pivotTemp = stuff.getIndices(); int numberColumnBasic = stuff.getNumElements(); // compute how much in basis int numberSlacks = numberRows_ - numberColumnBasic; CoinBigIndex numberElements = numberSlacks+matrix->countBasis(pivotTemp + numberSlacks, numberColumnBasic); // Not needed for dense numberElements = 3 * numberRows_ + 3 * numberElements + 20000; getAreas ( numberRows_, numberSlacks + numberColumnBasic, numberElements, 2 * numberElements ); numberSlacks_=numberSlacks; // Fill in counts so we can skip part of preProcess // This is NOT needed for dense but would be needed for later versions CoinFactorizationDouble * COIN_RESTRICT elementU; int * COIN_RESTRICT indexRowU; CoinBigIndex * COIN_RESTRICT startColumnU; int * COIN_RESTRICT numberInRow; int * COIN_RESTRICT numberInColumn; elementU = this->elements(); indexRowU = this->indices(); startColumnU = this->starts(); numberInRow = this->numberInRow(); numberInColumn = this->numberInColumn(); CoinZeroN ( numberInRow, numberRows_+1 ); CoinZeroN ( numberInColumn, numberRows_ ); for (int i = 0; i < numberSlacks_; i++) { int iRow = pivotTemp[i]; indexRowU[i] = iRow; startColumnU[i] = i; elementU[i] = 1.0; numberInRow[iRow] = 1; numberInColumn[i] = 1; } startColumnU[numberSlacks_] = numberSlacks_; matrix->fillBasis(pivotTemp + numberSlacks_, numberColumnBasic, indexRowU, startColumnU + numberSlacks_, numberInRow, numberInColumn + numberSlacks_, elementU); numberElements = startColumnU[numberRows_-1] + numberInColumn[numberRows_-1]; preProcess ( ); factor (model); if (status() == 0 ) { // Put sequence numbers in workArea int * savePivots = reinterpret_cast(workAreaAddress_); CoinAbcMemcpy(savePivots,pivotTemp,numberRows_); postProcess(pivotTemp, savePivots); return 0; } else { return -2; } } // 0 success, -1 can't +1 accuracy problems int CoinAbcTypeFactorization::replaceColumns ( const AbcSimplex * model, CoinIndexedVector & stuff, int firstPivot,int lastPivot, bool cleanUp) { // Could skip some if goes in and out (only if easy as then no alpha check) // Put sequence numbers in workArea int * savePivots = reinterpret_cast(workAreaAddress_); const int * pivotIndices = stuff.getIndices(); CoinSimplexDouble * pivotValues = stuff.denseVector(); int savePivot = stuff.capacity(); savePivot--; savePivot -= 2*firstPivot; int numberDo=lastPivot-firstPivot; // Say clear stuff.setNumElements(0); bool badUpdates=false; for (int iPivot=0;iPivotunpack(stuff,sequenceIn); updateColumnFTPart1(stuff); stuff.clear(); //checkReplacePart1a(&stuff,pivotRow); CoinSimplexDouble ftAlpha=checkReplacePart1(&stuff,pivotRow); // may need better check if (checkReplacePart2(pivotRow,btranAlpha,alpha,ftAlpha)>1) { badUpdates=true; printf("Inaccuracy ? btranAlpha %g ftranAlpha %g ftAlpha %g\n", btranAlpha,alpha,ftAlpha); break; } replaceColumnPart3(model,&stuff,NULL,pivotRow,ftAlpha); } int flag; if (!badUpdates) { flag=1; if (cleanUp) { CoinAbcMemcpy(model->pivotVariable(),savePivots,numberRows_); } } else { flag=-1; } stuff.setNumElements(flag); return flag >0 ? 0 : flag; } #endif #ifdef ABC_ORDERED_FACTORIZATION // Permute in for Ftran void CoinAbcTypeFactorization::permuteInForFtran(CoinIndexedVector & regionSparse, bool full) const { int numberNonZero=regionSparse.getNumElements(); const int * COIN_RESTRICT permuteIn = permuteAddress_+maximumRowsExtra_+1; double * COIN_RESTRICT region = regionSparse.denseVector(); double * COIN_RESTRICT tempRegion = region+numberRows_; int * COIN_RESTRICT index = regionSparse.getIndices(); if ((numberNonZero<<1)>numberRows_||full) { CoinAbcMemcpy(tempRegion,region,numberRows_); CoinAbcMemset0(region,numberRows_); numberNonZero=0; for (int i=0;i=0&&whichdenseVector ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = vector->getIndices ( ); CoinSimplexInt numberNonZero = vector->getNumElements ( ); long double * COIN_RESTRICT longRegion = longArray_[which].array(); assert (!vector->packedMode()); // could check all of longRegion for zero but this should trap most errors for (int i=0;idenseVector ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = vector->getIndices ( ); CoinSimplexInt numberNonZero = vector->getNumElements ( ); long double * COIN_RESTRICT longRegion = longArray_[which].array(); assert (!vector->packedMode()); // could check all of region for zero but this should trap most errors for (int i=0;idenseVector ( ); CoinSimplexInt * COIN_RESTRICT regionIndex = vector->getIndices ( ); CoinSimplexInt numberNonZero = vector->getNumElements ( ); long double * COIN_RESTRICT longRegion = longArray_[which].array(); assert (!vector->packedMode()); // could check all of region for zero but this should trap most errors for (int i=0;igetIndices(); CoinFactorizationDouble * COIN_RESTRICT region = denseVector(vector); for (int i=0;izeroTolerance_) index[numberNonZero++]=i; else region[i]=0.0; } vector->setNumElements(numberNonZero); } // Clear all hidden arrays void CoinAbcTypeFactorization::clearHiddenArrays() { for (int which=0;whichgetIndices ( ); CoinSimplexInt numberNonZero = vector->getNumElements ( ); } } } #endif #endif Clp-1.15.10/src/ClpSimplex.hpp0000644000076600007660000020616212252354371014446 0ustar coincoin/* $Id: ClpSimplex.hpp 2006 2013-12-12 15:40: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). /* Authors John Forrest */ #ifndef ClpSimplex_H #define ClpSimplex_H #include #include #include "ClpModel.hpp" #include "ClpMatrixBase.hpp" #include "ClpSolve.hpp" #include "ClpConfig.h" class ClpDualRowPivot; class ClpPrimalColumnPivot; class ClpFactorization; class CoinIndexedVector; class ClpNonLinearCost; class ClpNodeStuff; class CoinStructuredModel; class OsiClpSolverInterface; class CoinWarmStartBasis; class ClpDisasterHandler; class ClpConstraint; #ifdef CLP_HAS_ABC #include "AbcCommon.hpp" class AbcTolerancesEtc; class AbcSimplex; #include "CoinAbcCommon.hpp" #endif /** This solves LPs using the simplex method It inherits from ClpModel and all its arrays are created at algorithm time. Originally I tried to work with model arrays but for simplicity of coding I changed to single arrays with structural variables then row variables. Some coding is still based on old style and needs cleaning up. For a description of algorithms: for dual see ClpSimplexDual.hpp and at top of ClpSimplexDual.cpp for primal see ClpSimplexPrimal.hpp and at top of ClpSimplexPrimal.cpp There is an algorithm data member. + for primal variations and - for dual variations */ class ClpSimplex : public ClpModel { friend void ClpSimplexUnitTest(const std::string & mpsDir); public: /** enums for status of various sorts. First 4 match CoinWarmStartBasis, isFixed means fixed at lower bound and out of basis */ enum Status { isFree = 0x00, basic = 0x01, atUpperBound = 0x02, atLowerBound = 0x03, superBasic = 0x04, isFixed = 0x05 }; // For Dual enum FakeBound { noFake = 0x00, lowerFake = 0x01, upperFake = 0x02, bothFake = 0x03 }; /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpSimplex (bool emptyMessages = false ); /** Copy constructor. May scale depending on mode -1 leave mode as is 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ ClpSimplex(const ClpSimplex & rhs, int scalingMode = -1); /** Copy constructor from model. May scale depending on mode -1 leave mode as is 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ ClpSimplex(const ClpModel & rhs, int scalingMode = -1); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped Can optionally modify rhs to take into account variables NOT in list in this case duplicates are not allowed (also see getbackSolution) */ ClpSimplex (const ClpModel * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true, bool fixOthers = false); /** Subproblem constructor. A subset of whole model is created from the row and column lists given. The new order is given by list order and duplicates are allowed. Name and integer information can be dropped Can optionally modify rhs to take into account variables NOT in list in this case duplicates are not allowed (also see getbackSolution) */ ClpSimplex (const ClpSimplex * wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns, bool dropNames = true, bool dropIntegers = true, bool fixOthers = false); /** This constructor modifies original ClpSimplex and stores original stuff in created ClpSimplex. It is only to be used in conjunction with originalModel */ ClpSimplex (ClpSimplex * wholeModel, int numberColumns, const int * whichColumns); /** This copies back stuff from miniModel and then deletes miniModel. Only to be used with mini constructor */ void originalModel(ClpSimplex * miniModel); inline int abcState() const { return abcState_;} inline void setAbcState(int state) { abcState_=state;} #ifdef ABC_INHERIT inline AbcSimplex * abcSimplex() const { return abcSimplex_;} inline void setAbcSimplex(AbcSimplex * simplex) { abcSimplex_=simplex;} /// Returns 0 if dual can be skipped int doAbcDual(); /// Returns 0 if primal can be skipped int doAbcPrimal(int ifValuesPass); #endif /** Array persistence flag If 0 then as now (delete/new) 1 then only do arrays if bigger needed 2 as 1 but give a bit extra if bigger needed */ void setPersistenceFlag(int value); /// Save a copy of model with certain state - normally without cuts void makeBaseModel(); /// Switch off base model void deleteBaseModel(); /// See if we have base model inline ClpSimplex * baseModel() const { return baseModel_; } /** Reset to base model (just size and arrays needed) If model NULL use internal copy */ void setToBaseModel(ClpSimplex * model = NULL); /// Assignment operator. This copies the data ClpSimplex & operator=(const ClpSimplex & rhs); /// Destructor ~ClpSimplex ( ); // Ones below are just ClpModel with some changes /** Loads a problem (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
*/ void loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); void loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /** Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ 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, const double * rowObjective = NULL); /// This one is for after presolve to save memory void loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int * length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective = NULL); /** This loads a model from a coinModel object - returns number of errors. If keepSolution true and size is same as current then keeps current status and solution */ int loadProblem ( CoinModel & modelObject, bool keepSolution = false); /// Read an mps file from the given filename int readMps(const char *filename, bool keepNames = false, bool ignoreErrors = false); /// Read GMPL files from the given filenames int readGMPL(const char *filename, const char * dataName, bool keepNames = false); /// Read file in LP format from file with name filename. /// See class CoinLpIO for description of this format. int readLp(const char *filename, const double epsilon = 1e-5); /** Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm. This is same as ClpModel one, but sets scaling on etc. */ void borrowModel(ClpModel & otherModel); void borrowModel(ClpSimplex & otherModel); /// Pass in Event handler (cloned and deleted at end) void passInEventHandler(const ClpEventHandler * eventHandler); /// Puts solution back into small model void getbackSolution(const ClpSimplex & smallModel, const int * whichRow, const int * whichColumn); /** 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 loadNonLinear(void * info, int & numberConstraints, ClpConstraint ** & constraints); #ifdef ABC_INHERIT /// Loads tolerances etc void loadTolerancesEtc(const AbcTolerancesEtc & data); /// Unloads tolerances etc void unloadTolerancesEtc(AbcTolerancesEtc & data); #endif //@} /**@name Functions most useful to user */ //@{ /** General solve algorithm which can do presolve. See ClpSolve.hpp for options */ int initialSolve(ClpSolve & options); /// Default initial solve int initialSolve(); /// Dual initial solve int initialDualSolve(); /// Primal initial solve int initialPrimalSolve(); /// Barrier initial solve int initialBarrierSolve(); /// Barrier initial solve, not to be followed by crossover int initialBarrierNoCrossSolve(); /** Dual algorithm - see ClpSimplexDual.hpp for method. ifValuesPass==2 just does values pass and then stops. startFinishOptions - bits 1 - do not delete work areas and factorization at end 2 - use old factorization if same number of rows 4 - skip as much initialization of work areas as possible (based on whatsChanged in clpmodel.hpp) ** work in progress maybe other bits later */ int dual(int ifValuesPass = 0, int startFinishOptions = 0); // If using Debug int dualDebug(int ifValuesPass = 0, int startFinishOptions = 0); /** Primal algorithm - see ClpSimplexPrimal.hpp for method. ifValuesPass==2 just does values pass and then stops. startFinishOptions - bits 1 - do not delete work areas and factorization at end 2 - use old factorization if same number of rows 4 - skip as much initialization of work areas as possible (based on whatsChanged in clpmodel.hpp) ** work in progress maybe other bits later */ int primal(int ifValuesPass = 0, int startFinishOptions = 0); /** Solves nonlinear problem 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 */ int nonlinearSLP(int numberPasses, double deltaTolerance); /** Solves problem with nonlinear constraints 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 */ int nonlinearSLP(int numberConstraints, ClpConstraint ** constraints, int numberPasses, double deltaTolerance); /** Solves using barrier (assumes you have good cholesky factor code). Does crossover to simplex if asked*/ int barrier(bool crossover = true); /** Solves non-linear using reduced gradient. Phase = 0 get feasible, =1 use solution */ int reducedGradient(int phase = 0); /// Solve using structure of model and maybe in parallel int solve(CoinStructuredModel * model); #ifdef ABC_INHERIT /** solvetype 0 for dual, 1 for primal startup 1 for values pass interrupt whether to pass across interrupt handler */ void dealWithAbc(int solveType,int startUp,bool interrupt=false); #endif /** This loads a model from a CoinStructuredModel object - returns number of errors. If originalOrder then keep to order stored in blocks, otherwise first column/rows correspond to first block - etc. If keepSolution true and size is same as current then keeps current status and solution */ int loadProblem ( CoinStructuredModel & modelObject, bool originalOrder = true, bool keepSolution = false); /** When scaling is on it is possible that the scaled problem is feasible but the unscaled is not. Clp returns a secondary status code to that effect. This option allows for a cleanup. If you use it I would suggest 1. This only affects actions when scaled optimal 0 - no action 1 - clean up using dual if primal infeasibility 2 - clean up using dual if dual infeasibility 3 - clean up using dual if primal or dual infeasibility 11,12,13 - as 1,2,3 but use primal return code as dual/primal */ int cleanup(int cleanupScaling); /** Dual ranging. This computes increase/decrease in cost for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For non-basic variables the information is trivial to compute and the change in cost is just minus the reduced cost and the sequence number will be that of the non-basic variables. For basic variables a ratio test is between the reduced costs for non-basic variables and the row of the tableau corresponding to the basic variable. The increase/decrease value is always >= 0.0 Up to user to provide correct length arrays where each array is of length numberCheck. which contains list of variables for which information is desired. All other arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays will be information for variable 7. If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with the value of variable if such a change in cost were made (the existing bounds are ignored) Returns non-zero if infeasible unbounded etc */ int dualRanging(int numberCheck, const int * which, double * costIncrease, int * sequenceIncrease, double * costDecrease, int * sequenceDecrease, double * valueIncrease = NULL, double * valueDecrease = NULL); /** Primal ranging. This computes increase/decrease in value for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. This should only be used for non-basic variabls as otherwise information is pretty useless For basic variables the sequence number will be that of the basic variables. Up to user to provide correct length arrays where each array is of length numberCheck. which contains list of variables for which information is desired. All other arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays will be information for variable 7. Returns non-zero if infeasible unbounded etc */ int primalRanging(int numberCheck, const int * which, double * valueIncrease, int * sequenceIncrease, double * valueDecrease, int * sequenceDecrease); /** Modifies coefficients etc and if necessary pivots in and out. All at same status will be done (basis may go singular). User can tell which others have been done (i.e. if status matches). If called from outside will change status and return 0. If called from event handler returns non-zero if user has to take action. indices>=numberColumns are slacks (obviously no coefficients) status array is (char) Status enum */ int modifyCoefficientsAndPivot(int number, const int * which, const CoinBigIndex * start, const int * row, const double * newCoefficient, const unsigned char * newStatus=NULL, const double * newLower=NULL, const double * newUpper=NULL, const double * newObjective=NULL); /** Take out duplicate rows (includes scaled rows and intersections). On exit whichRows has rows to delete - return code is number can be deleted or -1 if would be infeasible. If tolerance is -1.0 use primalTolerance for equality rows and infeasibility If cleanUp not zero then spend more time trying to leave more stable row and make row bounds exact multiple of cleanUp if close enough */ int outDuplicateRows(int numberLook,int * whichRows, bool noOverlaps=false, double tolerance=-1.0, double cleanUp=0.0); /** Try simple crash like techniques to get closer to primal feasibility returns final sum of infeasibilities */ double moveTowardsPrimalFeasible(); /** Try simple crash like techniques to remove super basic slacks but only if > threshold */ void removeSuperBasicSlacks(int threshold=0); /** Mini presolve (faster) Char arrays must be numberRows and numberColumns long on entry second part must be filled in as follows - 0 - possible >0 - take out and do something (depending on value - TBD) -1 row/column can't vanish but can have entries removed/changed -2 don't touch at all on exit <=0 ones will be in presolved problem struct will be created and will be long enough (information on length etc in first entry) user must delete struct */ ClpSimplex * miniPresolve(char * rowType, char * columnType,void ** info); /// After mini presolve void miniPostsolve(const ClpSimplex * presolvedModel,void * info); /** Write the basis in MPS format to the specified file. If writeValues true writes values of structurals (and adds VALUES to end of NAME card) Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex (later)
Returns non-zero on I/O error */ int writeBasis(const char *filename, bool writeValues = false, int formatType = 0) const; /** Read a basis from the given filename, returns -1 on file error, 0 if no values, 1 if values */ int readBasis(const char *filename); /// Returns a basis (to be deleted by user) CoinWarmStartBasis * getBasis() const; /// Passes in factorization void setFactorization( ClpFactorization & factorization); // Swaps factorization ClpFactorization * swapFactorization( ClpFactorization * factorization); /// Copies in factorization to existing one void copyFactorization( ClpFactorization & factorization); /** Tightens primal bounds to make dual faster. Unless fixed or doTight>10, bounds are slightly looser than they could be. This is to make dual go faster and is probably not needed with a presolve. Returns non-zero if problem infeasible. Fudge for branch and bound - put bounds on columns of factor * largest value (at continuous) - should improve stability in branch and bound on infeasible branches (0.0 is off) */ int tightenPrimalBounds(double factor = 0.0, int doTight = 0, bool tightIntegers = false); /** Crash - at present just aimed at dual, returns -2 if dual preferred and crash basis created -1 if dual preferred and all slack basis preferred 0 if basis going in was not all slack 1 if primal preferred and all slack basis preferred 2 if primal preferred and crash basis created. if gap between bounds <="gap" variables can be flipped ( If pivot -1 then can be made super basic!) If "pivot" is -1 No pivoting - always primal 0 No pivoting (so will just be choice of algorithm) 1 Simple pivoting e.g. gub 2 Mini iterations */ int crash(double gap, int pivot); /// Sets row pivot choice algorithm in dual void setDualRowPivotAlgorithm(ClpDualRowPivot & choice); /// Sets column pivot choice algorithm in primal void setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot & choice); /** For strong branching. On input lower and upper are new bounds while on output they are change in objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) Solutions are filled in as well - even down, odd up - also status and number of iterations */ int strongBranching(int numberVariables, const int * variables, double * newLower, double * newUpper, double ** outputSolution, int * outputStatus, int * outputIterations, bool stopOnFirstInfeasible = true, bool alwaysFinish = false, int startFinishOptions = 0); /// Fathom - 1 if solution int fathom(void * stuff); /** Do up to N deep - returns -1 - no solution nNodes_ valid nodes >= if solution and that node gives solution ClpNode array is 2**N long. Values for N and array are in stuff (nNodes_ also in stuff) */ int fathomMany(void * stuff); /// Double checks OK double doubleCheck(); /// Starts Fast dual2 int startFastDual2(ClpNodeStuff * stuff); /// Like Fast dual int fastDual2(ClpNodeStuff * stuff); /// Stops Fast dual2 void stopFastDual2(ClpNodeStuff * stuff); /** Deals with crunch aspects mode 0 - in 1 - out with solution 2 - out without solution returns small model or NULL */ ClpSimplex * fastCrunch(ClpNodeStuff * stuff, int mode); //@} /**@name Needed for functionality of OsiSimplexInterface */ //@{ /** Pivot in a variable and out a variable. Returns 0 if okay, 1 if inaccuracy forced re-factorization, -1 if would be singular. Also updates primal/dual infeasibilities. Assumes sequenceIn_ and pivotRow_ set and also directionIn and Out. */ int pivot(); /** Pivot in a variable and choose an outgoing one. Assumes primal feasible - will not go through a bound. Returns step length in theta Returns ray in ray_ (or NULL if no pivot) Return codes as before but -1 means no acceptable pivot */ int primalPivotResult(); /** Pivot out a variable and choose an incoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Return codes as before but -1 means no acceptable pivot */ int dualPivotResultPart1(); /** Do actual pivot state is 0 if need tableau column, 1 if in rowArray_[1] */ int pivotResultPart2(int algorithm,int state); /** Common bits of coding for dual and primal. Return 0 if okay, 1 if bad matrix, 2 if very bad factorization startFinishOptions - bits 1 - do not delete work areas and factorization at end 2 - use old factorization if same number of rows 4 - skip as much initialization of work areas as possible (based on whatsChanged in clpmodel.hpp) ** work in progress maybe other bits later */ int startup(int ifValuesPass, int startFinishOptions = 0); void finish(int startFinishOptions = 0); /** Factorizes and returns true if optimal. Used by user */ bool statusOfProblem(bool initial = false); /// If user left factorization frequency then compute void defaultFactorizationFrequency(); /// Copy across enabled stuff from one solver to another void copyEnabledStuff(const ClpSimplex * rhs); //@} /**@name most useful gets and sets */ //@{ /// If problem is primal feasible inline bool primalFeasible() const { return (numberPrimalInfeasibilities_ == 0); } /// If problem is dual feasible inline bool dualFeasible() const { return (numberDualInfeasibilities_ == 0); } /// factorization inline ClpFactorization * factorization() const { return factorization_; } /// Sparsity on or off bool sparseFactorization() const; void setSparseFactorization(bool value); /// Factorization frequency int factorizationFrequency() const; void setFactorizationFrequency(int value); /// Dual bound inline double dualBound() const { return dualBound_; } void setDualBound(double value); /// Infeasibility cost inline double infeasibilityCost() const { return infeasibilityCost_; } void setInfeasibilityCost(double value); /** 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 */ /** Perturbation: 50 - switch on perturbation 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 others are for playing */ inline int perturbation() const { return perturbation_; } void setPerturbation(int value); /// Current (or last) algorithm inline int algorithm() const { return algorithm_; } /// Set algorithm inline void setAlgorithm(int value) { algorithm_ = value; } /// Return true if the objective limit test can be relied upon bool isObjectiveLimitTestValid() const ; /// Sum of dual infeasibilities inline double sumDualInfeasibilities() const { return sumDualInfeasibilities_; } inline void setSumDualInfeasibilities(double value) { sumDualInfeasibilities_ = value; } /// Sum of relaxed dual infeasibilities inline double sumOfRelaxedDualInfeasibilities() const { return sumOfRelaxedDualInfeasibilities_; } inline void setSumOfRelaxedDualInfeasibilities(double value) { sumOfRelaxedDualInfeasibilities_ = value; } /// Number of dual infeasibilities inline int numberDualInfeasibilities() const { return numberDualInfeasibilities_; } inline void setNumberDualInfeasibilities(int value) { numberDualInfeasibilities_ = value; } /// Number of dual infeasibilities (without free) inline int numberDualInfeasibilitiesWithoutFree() const { return numberDualInfeasibilitiesWithoutFree_; } /// Sum of primal infeasibilities inline double sumPrimalInfeasibilities() const { return sumPrimalInfeasibilities_; } inline void setSumPrimalInfeasibilities(double value) { sumPrimalInfeasibilities_ = value; } /// Sum of relaxed primal infeasibilities inline double sumOfRelaxedPrimalInfeasibilities() const { return sumOfRelaxedPrimalInfeasibilities_; } inline void setSumOfRelaxedPrimalInfeasibilities(double value) { sumOfRelaxedPrimalInfeasibilities_ = value; } /// Number of primal infeasibilities inline int numberPrimalInfeasibilities() const { return numberPrimalInfeasibilities_; } inline void setNumberPrimalInfeasibilities(int value) { numberPrimalInfeasibilities_ = value; } /** Save model to file, returns 0 if success. This is designed for use outside algorithms so does not save iterating arrays etc. It does not save any messaging information. Does not save scaling values. It does not know about all types of virtual functions. */ int saveModel(const char * fileName); /** Restore model from file, returns 0 if success, deletes current model */ int restoreModel(const char * fileName); /** Just check solution (for external use) - sets sum of infeasibilities etc. If setToBounds 0 then primal column values not changed and used to compute primal row activity values. If 1 or 2 then status used - so all nonbasic variables set to indicated bound and if any values changed (or ==2) basic values re-computed. */ void checkSolution(int setToBounds = 0); /** Just check solution (for internal use) - sets sum of infeasibilities etc. */ void checkSolutionInternal(); /// Check unscaled primal solution but allow for rounding error void checkUnscaledSolution(); /// Useful row length arrays (0,1,2,3,4,5) inline CoinIndexedVector * rowArray(int index) const { return rowArray_[index]; } /// Useful column length arrays (0,1,2,3,4,5) inline CoinIndexedVector * columnArray(int index) const { return columnArray_[index]; } //@} /******************** End of most useful part **************/ /**@name Functions less likely to be useful to casual user */ //@{ /** Given an existing factorization computes and checks primal and dual solutions. Uses input arrays for variables at bounds. Returns feasibility states */ int getSolution ( const double * rowActivities, const double * columnActivities); /** Given an existing factorization computes and checks primal and dual solutions. Uses current problem arrays for bounds. Returns feasibility states */ int getSolution (); /** Constructs a non linear cost from list of non-linearities (columns only) First lower of each column is taken as real lower Last lower is taken as real upper and cost ignored Returns nonzero if bad data e.g. lowers not monotonic */ int createPiecewiseLinearCosts(const int * starts, const double * lower, const double * gradient); /// dual row pivot choice inline ClpDualRowPivot * dualRowPivot() const { return dualRowPivot_; } /// primal column pivot choice inline ClpPrimalColumnPivot * primalColumnPivot() const { return primalColumnPivot_; } /// Returns true if model looks OK inline bool goodAccuracy() const { return (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7); } /** Return model - updates any scalars */ void returnModel(ClpSimplex & otherModel); /** Factorizes using current basis. solveType - 1 iterating, 0 initial, -1 external If 10 added then in primal values pass Return codes are as from ClpFactorization unless initial factorization when total number of singularities is returned. Special case is numberRows_+1 -> all slack basis. */ int internalFactorize(int solveType); /// Save data ClpDataSave saveData() ; /// Restore data void restoreData(ClpDataSave saved); /// Clean up status void cleanStatus(); /// Factorizes using current basis. For external use int factorize(); /** Computes duals from scratch. If givenDjs then allows for nonzero basic djs */ void computeDuals(double * givenDjs); /// Computes primals from scratch void computePrimals ( const double * rowActivities, const double * columnActivities); /** Adds multiple of a column into an array */ void add(double * array, int column, double multiplier) const; /** Unpacks one column of the matrix into indexed array Uses sequenceIn_ Also applies scaling if needed */ void unpack(CoinIndexedVector * rowArray) const ; /** Unpacks one column of the matrix into indexed array Slack if sequence>= numberColumns Also applies scaling if needed */ void unpack(CoinIndexedVector * rowArray, int sequence) const; /** Unpacks one column of the matrix into indexed array ** as packed vector Uses sequenceIn_ Also applies scaling if needed */ void unpackPacked(CoinIndexedVector * rowArray) ; /** Unpacks one column of the matrix into indexed array ** as packed vector Slack if sequence>= numberColumns Also applies scaling if needed */ void unpackPacked(CoinIndexedVector * rowArray, int sequence); #ifndef CLP_USER_DRIVEN protected: #endif /** This does basis housekeeping and does values for in/out variables. Can also decide to re-factorize */ int housekeeping(double objectiveChange); /** This sets largest infeasibility and most infeasible and sum and number of infeasibilities (Primal) */ void checkPrimalSolution(const double * rowActivities = NULL, const double * columnActivies = NULL); /** This sets largest infeasibility and most infeasible and sum and number of infeasibilities (Dual) */ void checkDualSolution(); /** This sets sum and number of infeasibilities (Dual and Primal) */ void checkBothSolutions(); /** If input negative scales objective so maximum <= -value and returns scale factor used. If positive unscales and also redoes dual stuff */ double scaleObjective(double value); /// Solve using Dantzig-Wolfe decomposition and maybe in parallel int solveDW(CoinStructuredModel * model); /// Solve using Benders decomposition and maybe in parallel int solveBenders(CoinStructuredModel * model); public: /** For advanced use. When doing iterative solves things can get nasty so on values pass if incoming solution has largest infeasibility < incomingInfeasibility throw out variables from basis until largest infeasibility < allowedInfeasibility or incoming largest infeasibility. If allowedInfeasibility>= incomingInfeasibility this is always possible altough you may end up with an all slack basis. Defaults are 1.0,10.0 */ void setValuesPassAction(double incomingInfeasibility, double allowedInfeasibility); /** Get a clean factorization - i.e. throw out singularities may do more later */ int cleanFactorization(int ifValuesPass); //@} /**@name most useful gets and sets */ //@{ public: /// Initial value for alpha accuracy calculation (-1.0 off) inline double alphaAccuracy() const { return alphaAccuracy_; } inline void setAlphaAccuracy(double value) { alphaAccuracy_ = value; } public: /// Objective value //inline double objectiveValue() const { //return (objectiveValue_-bestPossibleImprovement_)*optimizationDirection_ - dblParam_[ClpObjOffset]; //} /// Set disaster handler inline void setDisasterHandler(ClpDisasterHandler * handler) { disasterArea_ = handler; } /// Get disaster handler inline ClpDisasterHandler * disasterHandler() const { return disasterArea_; } /// Large bound value (for complementarity etc) inline double largeValue() const { return largeValue_; } void setLargeValue( double value) ; /// Largest error on Ax-b inline double largestPrimalError() const { return largestPrimalError_; } /// Largest error on basic duals inline double largestDualError() const { return largestDualError_; } /// Largest error on Ax-b inline void setLargestPrimalError(double value) { largestPrimalError_ = value; } /// Largest error on basic duals inline void setLargestDualError(double value) { largestDualError_ = value; } /// Get zero tolerance inline double zeroTolerance() const { return zeroTolerance_;/*factorization_->zeroTolerance();*/ } /// Set zero tolerance inline void setZeroTolerance( double value) { zeroTolerance_ = value; } /// Basic variables pivoting on which rows inline int * pivotVariable() const { return pivotVariable_; } /// If automatic scaling on inline bool automaticScaling() const { return automaticScale_ != 0; } inline void setAutomaticScaling(bool onOff) { automaticScale_ = onOff ? 1 : 0; } /// Current dual tolerance inline double currentDualTolerance() const { return dualTolerance_; } inline void setCurrentDualTolerance(double value) { dualTolerance_ = value; } /// Current primal tolerance inline double currentPrimalTolerance() const { return primalTolerance_; } inline void setCurrentPrimalTolerance(double value) { primalTolerance_ = value; } /// How many iterative refinements to do inline int numberRefinements() const { return numberRefinements_; } void setNumberRefinements( int value) ; /// Alpha (pivot element) for use by classes e.g. steepestedge inline double alpha() const { return alpha_; } inline void setAlpha(double value) { alpha_ = value; } /// Reduced cost of last incoming for use by classes e.g. steepestedge inline double dualIn() const { return dualIn_; } /// Set reduced cost of last incoming to force error inline void setDualIn(double value) { dualIn_ = value; } /// Pivot Row for use by classes e.g. steepestedge inline int pivotRow() const { return pivotRow_; } inline void setPivotRow(int value) { pivotRow_ = value; } /// value of incoming variable (in Dual) double valueIncomingDual() const; //@} #ifndef CLP_USER_DRIVEN protected: #endif /**@name protected methods */ //@{ /** May change basis and then returns number changed. Computation of solutions may be overriden by given pi and solution */ int gutsOfSolution ( double * givenDuals, const double * givenPrimals, bool valuesPass = false); /// Does most of deletion (0 = all, 1 = most, 2 most + factorization) void gutsOfDelete(int type); /// Does most of copying void gutsOfCopy(const ClpSimplex & rhs); /** puts in format I like (rowLower,rowUpper) also see StandardMatrix 1 bit does rows (now and columns), (2 bit does column bounds), 4 bit does objective(s). 8 bit does solution scaling in 16 bit does rowArray and columnArray indexed vectors and makes row copy if wanted, also sets columnStart_ etc Also creates scaling arrays if needed. It does scaling if needed. 16 also moves solutions etc in to work arrays On 16 returns false if problem "bad" i.e. matrix or bounds bad If startFinishOptions is -1 then called by user in getSolution so do arrays but keep pivotVariable_ */ bool createRim(int what, bool makeRowCopy = false, int startFinishOptions = 0); /// Does rows and columns void createRim1(bool initial); /// Does objective void createRim4(bool initial); /// Does rows and columns and objective void createRim5(bool initial); /** releases above arrays and does solution scaling out. May also get rid of factorization data - 0 get rid of nothing, 1 get rid of arrays, 2 also factorization */ void deleteRim(int getRidOfFactorizationData = 2); /// Sanity check on input rim data (after scaling) - returns true if okay bool sanityCheck(); //@} public: /**@name public methods */ //@{ /** Return row or column sections - not as much needed as it once was. These just map into single arrays */ inline double * solutionRegion(int section) const { if (!section) return rowActivityWork_; else return columnActivityWork_; } inline double * djRegion(int section) const { if (!section) return rowReducedCost_; else return reducedCostWork_; } inline double * lowerRegion(int section) const { if (!section) return rowLowerWork_; else return columnLowerWork_; } inline double * upperRegion(int section) const { if (!section) return rowUpperWork_; else return columnUpperWork_; } inline double * costRegion(int section) const { if (!section) return rowObjectiveWork_; else return objectiveWork_; } /// Return region as single array inline double * solutionRegion() const { return solution_; } inline double * djRegion() const { return dj_; } inline double * lowerRegion() const { return lower_; } inline double * upperRegion() const { return upper_; } inline double * costRegion() const { return cost_; } inline Status getStatus(int sequence) const { return static_cast (status_[sequence] & 7); } inline void setStatus(int sequence, Status newstatus) { unsigned char & st_byte = status_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | newstatus); } /// Start or reset using maximumRows_ and Columns_ - true if change bool startPermanentArrays(); /** Normally the first factorization does sparse coding because the factorization could be singular. This allows initial dense factorization when it is known to be safe */ void setInitialDenseFactorization(bool onOff); bool initialDenseFactorization() const; /** Return sequence In or Out */ inline int sequenceIn() const { return sequenceIn_; } inline int sequenceOut() const { return sequenceOut_; } /** Set sequenceIn or Out */ inline void setSequenceIn(int sequence) { sequenceIn_ = sequence; } inline void setSequenceOut(int sequence) { sequenceOut_ = sequence; } /** Return direction In or Out */ inline int directionIn() const { return directionIn_; } inline int directionOut() const { return directionOut_; } /** Set directionIn or Out */ inline void setDirectionIn(int direction) { directionIn_ = direction; } inline void setDirectionOut(int direction) { directionOut_ = direction; } /// Value of Out variable inline double valueOut() const { return valueOut_; } /// Set value of out variable inline void setValueOut(double value) { valueOut_ = value; } /// Dual value of Out variable inline double dualOut() const { return dualOut_; } /// Set dual value of out variable inline void setDualOut(double value) { dualOut_ = value; } /// Set lower of out variable inline void setLowerOut(double value) { lowerOut_ = value; } /// Set upper of out variable inline void setUpperOut(double value) { upperOut_ = value; } /// Set theta of out variable inline void setTheta(double value) { theta_ = value; } /// Returns 1 if sequence indicates column inline int isColumn(int sequence) const { return sequence < numberColumns_ ? 1 : 0; } /// Returns sequence number within section inline int sequenceWithin(int sequence) const { return sequence < numberColumns_ ? sequence : sequence - numberColumns_; } /// Return row or column values inline double solution(int sequence) { return solution_[sequence]; } /// Return address of row or column values inline double & solutionAddress(int sequence) { return solution_[sequence]; } inline double reducedCost(int sequence) { return dj_[sequence]; } inline double & reducedCostAddress(int sequence) { return dj_[sequence]; } inline double lower(int sequence) { return lower_[sequence]; } /// Return address of row or column lower bound inline double & lowerAddress(int sequence) { return lower_[sequence]; } inline double upper(int sequence) { return upper_[sequence]; } /// Return address of row or column upper bound inline double & upperAddress(int sequence) { return upper_[sequence]; } inline double cost(int sequence) { return cost_[sequence]; } /// Return address of row or column cost inline double & costAddress(int sequence) { return cost_[sequence]; } /// Return original lower bound inline double originalLower(int iSequence) const { if (iSequence < numberColumns_) return columnLower_[iSequence]; else return rowLower_[iSequence-numberColumns_]; } /// Return original lower bound inline double originalUpper(int iSequence) const { if (iSequence < numberColumns_) return columnUpper_[iSequence]; else return rowUpper_[iSequence-numberColumns_]; } /// Theta (pivot change) inline double theta() const { return theta_; } /** Best possible improvement using djs (primal) or obj change by flipping bounds to make dual feasible (dual) */ inline double bestPossibleImprovement() const { return bestPossibleImprovement_; } /// Return pointer to details of costs inline ClpNonLinearCost * nonLinearCost() const { return nonLinearCost_; } /** Return more special options 1 bit - if presolve says infeasible in ClpSolve return 2 bit - if presolved problem infeasible return 4 bit - keep arrays like upper_ around 8 bit - if factorization kept can still declare optimal at once 16 bit - if checking replaceColumn accuracy before updating 32 bit - say optimal if primal feasible! 64 bit - give up easily in dual (and say infeasible) 128 bit - no objective, 0-1 and in B&B 256 bit - in primal from dual or vice versa 512 bit - alternative use of solveType_ 1024 bit - don't do row copy of factorization 2048 bit - perturb in complete fathoming 4096 bit - try more for complete fathoming 8192 bit - don't even think of using primal if user asks for dual (and vv) 16384 bit - in initialSolve so be more flexible debug 32768 bit - do dual in netlibd */ inline int moreSpecialOptions() const { return moreSpecialOptions_; } /** Set more special options 1 bit - if presolve says infeasible in ClpSolve return 2 bit - if presolved problem infeasible return 4 bit - keep arrays like upper_ around 8 bit - no free or superBasic variables 16 bit - if checking replaceColumn accuracy before updating 32 bit - say optimal if primal feasible! 64 bit - give up easily in dual (and say infeasible) 128 bit - no objective, 0-1 and in B&B 256 bit - in primal from dual or vice versa 512 bit - alternative use of solveType_ 1024 bit - don't do row copy of factorization 2048 bit - perturb in complete fathoming 4096 bit - try more for complete fathoming 8192 bit - don't even think of using primal if user asks for dual (and vv) 16384 bit - in initialSolve so be more flexible 32768 bit - don't swap algorithms from dual if small infeasibility 65536 bit - perturb in postsolve cleanup (even if < 10000 rows) 1048576 bit - don't perturb even if long time */ inline void setMoreSpecialOptions(int value) { moreSpecialOptions_ = value; } //@} /**@name status methods */ //@{ inline void setFakeBound(int sequence, FakeBound fakeBound) { unsigned char & st_byte = status_[sequence]; st_byte = static_cast(st_byte & ~24); st_byte = static_cast(st_byte | (fakeBound << 3)); } inline FakeBound getFakeBound(int sequence) const { return static_cast ((status_[sequence] >> 3) & 3); } inline void setRowStatus(int sequence, Status newstatus) { unsigned char & st_byte = status_[sequence+numberColumns_]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | newstatus); } inline Status getRowStatus(int sequence) const { return static_cast (status_[sequence+numberColumns_] & 7); } inline void setColumnStatus(int sequence, Status newstatus) { unsigned char & st_byte = status_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | newstatus); } inline Status getColumnStatus(int sequence) const { return static_cast (status_[sequence] & 7); } inline void setPivoted( int sequence) { status_[sequence] = static_cast(status_[sequence] | 32); } inline void clearPivoted( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~32); } inline bool pivoted(int sequence) const { return (((status_[sequence] >> 5) & 1) != 0); } /// To flag a variable (not inline to allow for column generation) void setFlagged( int sequence); inline void clearFlagged( int sequence) { status_[sequence] = static_cast(status_[sequence] & ~64); } inline bool flagged(int sequence) const { return ((status_[sequence] & 64) != 0); } /// To say row active in primal pivot row choice inline void setActive( int iRow) { status_[iRow] = static_cast(status_[iRow] | 128); } inline void clearActive( int iRow) { status_[iRow] = static_cast(status_[iRow] & ~128); } inline bool active(int iRow) const { return ((status_[iRow] & 128) != 0); } /** Set up status array (can be used by OsiClp). Also can be used to set up all slack basis */ void createStatus() ; /** Sets up all slack basis and resets solution to as it was after initial load or readMps */ void allSlackBasis(bool resetSolution = false); /// So we know when to be cautious inline int lastBadIteration() const { return lastBadIteration_; } /// Set so we know when to be cautious inline void setLastBadIteration(int value) { lastBadIteration_=value; } /// Progress flag - at present 0 bit says artificials out inline int progressFlag() const { return (progressFlag_ & 3); } /// For dealing with all issues of cycling etc inline ClpSimplexProgress * progress() { return &progress_;} /// Force re-factorization early value inline int forceFactorization() const { return forceFactorization_ ; } /// Force re-factorization early inline void forceFactorization(int value) { forceFactorization_ = value; } /// Raw objective value (so always minimize in primal) inline double rawObjectiveValue() const { return objectiveValue_; } /// Compute objective value from solution and put in objectiveValue_ void computeObjectiveValue(bool useWorkingSolution = false); /// Compute minimization objective value from internal solution without perturbation double computeInternalObjectiveValue(); /** Infeasibility/unbounded ray (NULL returned if none/wrong) Up to user to use delete [] on these arrays. */ double * infeasibilityRay(bool fullRay=false) const; /** Number of extra rows. These are ones which will be dynamically created each iteration. This is for GUB but may have other uses. */ inline int numberExtraRows() const { return numberExtraRows_; } /** Maximum number of basic variables - can be more than number of rows if GUB */ inline int maximumBasic() const { return maximumBasic_; } /// Iteration when we entered dual or primal inline int baseIteration() const { return baseIteration_; } /// Create C++ lines to get to current state void generateCpp( FILE * fp, bool defaultFactor = false); /// Gets clean and emptyish factorization ClpFactorization * getEmptyFactorization(); /// May delete or may make clean and emptyish factorization void setEmptyFactorization(); /// Move status and solution across void moveInfo(const ClpSimplex & rhs, bool justStatus = false); //@} ///@name Basis handling // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal) // *** At present only without scaling // *** Slacks havve -1.0 element (so == row activity) - take care ///Get a row of the tableau (slack part in slack if not NULL) void getBInvARow(int row, double* z, double * slack = NULL); ///Get a row of the basis inverse void getBInvRow(int row, double* z); ///Get a column of the tableau void getBInvACol(int col, double* vec); ///Get a column of the basis inverse void getBInvCol(int col, double* vec); /** Get basic indices (order of indices corresponds to the order of elements in a vector retured by getBInvACol() and getBInvCol()). */ void getBasics(int* index); //@} //------------------------------------------------------------------------- /**@name Changing bounds on variables and constraints */ //@{ /** Set an objective function coefficient */ void setObjectiveCoefficient( int elementIndex, double elementValue ); /** Set an objective function coefficient */ inline void setObjCoeff( int elementIndex, double elementValue ) { setObjectiveCoefficient( elementIndex, elementValue); } /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ void setColumnLower( int elementIndex, double elementValue ); /** Set a single column upper bound
Use DBL_MAX for infinity. */ void setColumnUpper( int elementIndex, double elementValue ); /** Set a single column lower and upper bound */ void setColumnBounds( 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 */ void setColumnSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /** Set a single column lower bound
Use -DBL_MAX for -infinity. */ inline void setColLower( int elementIndex, double elementValue ) { setColumnLower(elementIndex, elementValue); } /** Set a single column upper bound
Use DBL_MAX for infinity. */ inline void setColUpper( int elementIndex, double elementValue ) { setColumnUpper(elementIndex, elementValue); } /** Set a single column lower and upper bound */ inline void setColBounds( int elementIndex, double newlower, double newupper ) { setColumnBounds(elementIndex, newlower, newupper); } /** Set the bounds on a number of columns simultaneously
@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 */ inline void setColSetBounds(const int* indexFirst, const int* indexLast, const double* boundList) { setColumnSetBounds(indexFirst, indexLast, boundList); } /** Set a single row lower bound
Use -DBL_MAX for -infinity. */ void setRowLower( int elementIndex, double elementValue ); /** Set a single row upper bound
Use DBL_MAX for infinity. */ void setRowUpper( int elementIndex, double elementValue ) ; /** Set a single row lower and upper bound */ void setRowBounds( int elementIndex, double lower, double upper ) ; /** Set the bounds on a number of rows simultaneously
@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 */ void setRowSetBounds(const int* indexFirst, const int* indexLast, const double* boundList); /// Resizes rim part of model void resize (int newNumberRows, int newNumberColumns); //@} ////////////////// data ////////////////// protected: /**@name data. Many arrays have a row part and a column part. There is a single array with both - columns then rows and then normally two arrays pointing to rows and columns. The single array is the owner of memory */ //@{ /** Best possible improvement using djs (primal) or obj change by flipping bounds to make dual feasible (dual) */ double bestPossibleImprovement_; /// Zero tolerance double zeroTolerance_; /// Sequence of worst (-1 if feasible) int columnPrimalSequence_; /// Sequence of worst (-1 if feasible) int rowPrimalSequence_; /// "Best" objective value double bestObjectiveValue_; /// More special options - see set for details int moreSpecialOptions_; /// Iteration when we entered dual or primal int baseIteration_; /// Primal tolerance needed to make dual feasible (0 == Primal, <0 == Dual int algorithm_; /** Now for some reliability aids This forces re-factorization early */ int forceFactorization_; /** Perturbation: -50 to +50 - perturb by this power of ten (-6 sounds good) 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 */ int perturbation_; /// Saved status regions unsigned char * saveStatus_; /** Very wasteful way of dealing with infeasibilities in primal. However it will allow non-linearities and use of dual analysis. If it doesn't work it can easily be replaced. */ ClpNonLinearCost * nonLinearCost_; /// So we know when to be cautious int lastBadIteration_; /// So we know when to open up again int lastFlaggedIteration_; /// Can be used for count of fake bounds (dual) or fake costs (primal) int numberFake_; /// Can be used for count of changed costs (dual) or changed bounds (primal) int numberChanged_; /// Progress flag - at present 0 bit says artificials out, 1 free in int progressFlag_; /// First free/super-basic variable (-1 if none) int firstFree_; /** Number of extra rows. These are ones which will be dynamically created each iteration. This is for GUB but may have other uses. */ int numberExtraRows_; /** Maximum number of basic variables - can be more than number of rows if GUB */ int maximumBasic_; /// If may skip final factorize then allow up to this pivots (default 20) int dontFactorizePivots_; /** For advanced use. When doing iterative solves things can get nasty so on values pass if incoming solution has largest infeasibility < incomingInfeasibility throw out variables from basis until largest infeasibility < allowedInfeasibility. if allowedInfeasibility>= incomingInfeasibility this is always possible altough you may end up with an all slack basis. Defaults are 1.0,10.0 */ double incomingInfeasibility_; double allowedInfeasibility_; /// Automatic scaling of objective and rhs and bounds int automaticScale_; /// Maximum perturbation array size (take out when code rewritten) int maximumPerturbationSize_; /// Perturbation array (maximumPerturbationSize_) double * perturbationArray_; /// A copy of model with certain state - normally without cuts ClpSimplex * baseModel_; /// For dealing with all issues of cycling etc ClpSimplexProgress progress_; #ifdef ABC_INHERIT AbcSimplex * abcSimplex_; #define CLP_ABC_WANTED 1 #define CLP_ABC_WANTED_PARALLEL 2 #define CLP_ABC_FULL_DONE 8 // bits 256,512,1024 for crash #endif #define CLP_ABC_BEEN_FEASIBLE 65536 int abcState_; public: /// Spare int array for passing information [0]!=0 switches on mutable int spareIntArray_[4]; /// Spare double array for passing information [0]!=0 switches on mutable double spareDoubleArray_[4]; protected: /// Allow OsiClp certain perks friend class OsiClpSolverInterface; //@} }; //############################################################################# /** A function that tests the methods in the ClpSimplex class. The only reason for it not to be a member method is that this way it doesn't have to be compiled into the library. And that's a gain, because the library should be compiled with optimization on, but this method should be compiled with debugging. It also does some testing of ClpFactorization class */ void ClpSimplexUnitTest(const std::string & mpsDir); // For Devex stuff #define DEVEX_TRY_NORM 1.0e-4 #define DEVEX_ADD_ONE 1.0 #endif Clp-1.15.10/src/CoinAbcOrderedFactorization4.cpp0000644000076600007660000000107712101105055017765 0ustar coincoin/* $Id: CoinAbcOrderedFactorization4.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -1 #define ABC_ORDERED_FACTORIZATION #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization4.cpp" #endif Clp-1.15.10/src/ClpNode.hpp0000644000076600007660000002335612101105055013676 0ustar coincoin/* $Id: ClpNode.hpp 1910 2013-01-27 02:00:13Z 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 ClpNode_H #define ClpNode_H #include "CoinPragma.hpp" // This implements all stuff for Clp fathom /** This contains what is in a Clp "node" */ class ClpFactorization; class ClpDualRowSteepest; class ClpNodeStuff; class ClpNode { public: /**@name Useful methods */ //@{ /** Applies node to model 0 - just tree bounds 1 - tree bounds and basis etc 2 - saved bounds and basis etc */ void applyNode(ClpSimplex * model, int doBoundsEtc ); /// Choose a new variable void chooseVariable(ClpSimplex * model, ClpNodeStuff * info); /// Fix on reduced costs int fixOnReducedCosts(ClpSimplex * model); /// Create odd arrays void createArrays(ClpSimplex * model); /// Clean up as crunch is different model void cleanUpForCrunch(); //@} /**@name Gets and sets */ //@{ /// Objective value inline double objectiveValue() const { return objectiveValue_; } /// Set objective value inline void setObjectiveValue(double value) { objectiveValue_ = value; } /// Primal solution inline const double * primalSolution() const { return primalSolution_; } /// Dual solution inline const double * dualSolution() const { return dualSolution_; } /// Initial value of integer variable inline double branchingValue() const { return branchingValue_; } /// Sum infeasibilities inline double sumInfeasibilities() const { return sumInfeasibilities_; } /// Number infeasibilities inline int numberInfeasibilities() const { return numberInfeasibilities_; } /// Relative depth inline int depth() const { return depth_; } /// Estimated solution value inline double estimatedSolution() const { return estimatedSolution_; } /** Way for integer variable -1 down , +1 up */ int way() const; /// Return true if branch exhausted bool fathomed() const; /// Change state of variable i.e. go other way void changeState(); /// Sequence number of integer variable (-1 if none) inline int sequence() const { return sequence_; } /// If odd arrays exist inline bool oddArraysExist() const { return lower_ != NULL; } /// Status array inline const unsigned char * statusArray() const { return status_; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpNode(); /// Constructor from model ClpNode (ClpSimplex * model, const ClpNodeStuff * stuff, int depth); /// Does work of constructor (partly so gdb will work) void gutsOfConstructor(ClpSimplex * model, const ClpNodeStuff * stuff, int arraysExist, int depth); /** Destructor */ virtual ~ClpNode(); //@} /**@name Copy methods (at present illegal - will abort) */ //@{ /** The copy constructor. */ ClpNode(const ClpNode&); /// Operator = ClpNode& operator=(const ClpNode&); //@} protected: // For state of branch typedef struct { unsigned int firstBranch: 1; // nonzero if first branch on variable is up unsigned int branch: 2; // 0 means do first branch next, 1 second, 2 finished unsigned int spare: 29; } branchState; /**@name Data */ //@{ /// Initial value of integer variable double branchingValue_; /// Value of objective double objectiveValue_; /// Sum of infeasibilities double sumInfeasibilities_; /// Estimated solution value double estimatedSolution_; /// Factorization ClpFactorization * factorization_; /// Steepest edge weights ClpDualRowSteepest * weights_; /// Status vector unsigned char * status_; /// Primal solution double * primalSolution_; /// Dual solution double * dualSolution_; /// Integer lower bounds (only used in fathomMany) int * lower_; /// Integer upper bounds (only used in fathomMany) int * upper_; /// Pivot variables for factorization int * pivotVariables_; /// Variables fixed by reduced costs (at end of branch) 0x10000000 added if fixed to UB int * fixed_; /// State of branch branchState branchState_; /// Sequence number of integer variable (-1 if none) int sequence_; /// Number of infeasibilities int numberInfeasibilities_; /// Relative depth int depth_; /// Number fixed by reduced cost int numberFixed_; /// Flags - 1 duals scaled int flags_; /// Maximum number fixed by reduced cost int maximumFixed_; /// Maximum rows so far int maximumRows_; /// Maximum columns so far int maximumColumns_; /// Maximum Integers so far int maximumIntegers_; //@} }; class ClpNodeStuff { public: /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpNodeStuff(); /** Destructor */ virtual ~ClpNodeStuff(); //@} /**@name Copy methods (only copies ints etc, nulls arrays) */ //@{ /** The copy constructor. */ ClpNodeStuff(const ClpNodeStuff&); /// Operator = ClpNodeStuff& operator=(const ClpNodeStuff&); /// Zaps stuff 1 - arrays, 2 ints, 3 both void zap(int type); //@} /**@name Fill methods */ //@{ /** Fill with pseudocosts */ void fillPseudoCosts(const double * down, const double * up, const int * priority, const int * numberDown, const int * numberUp, const int * numberDownInfeasible, const int * numberUpInfeasible, int number); /// Update pseudo costs void update(int way, int sequence, double change, bool feasible); /// Return maximum number of nodes int maximumNodes() const; /// Return maximum space for nodes int maximumSpace() const; //@} public: /**@name Data */ //@{ /// Integer tolerance double integerTolerance_; /// Integer increment double integerIncrement_; /// Small change in branch double smallChange_; /// Down pseudo costs double * downPseudo_; /// Up pseudo costs double * upPseudo_; /// Priority int * priority_; /// Number of times down int * numberDown_; /// Number of times up int * numberUp_; /// Number of times down infeasible int * numberDownInfeasible_; /// Number of times up infeasible int * numberUpInfeasible_; /// Copy of costs (local) double * saveCosts_; /// Array of ClpNodes ClpNode ** nodeInfo_; /// Large model if crunched ClpSimplex * large_; /// Which rows in large model int * whichRow_; /// Which columns in large model int * whichColumn_; #ifndef NO_FATHOM_PRINT /// Cbc's message handler CoinMessageHandler * handler_; #endif /// Number bounds in large model int nBound_; /// Save of specialOptions_ (local) int saveOptions_; /** Options to pass to solver 1 - create external reduced costs for columns 2 - create external reduced costs for rows 4 - create external row activity (columns always done) Above only done if feasible 32 - just create up to nDepth_+1 nodes 65536 - set if activated */ int solverOptions_; /// Maximum number of nodes to do int maximumNodes_; /// Number before trust from CbcModel int numberBeforeTrust_; /// State of search from CbcModel int stateOfSearch_; /// Number deep int nDepth_; /// Number nodes returned (-1 if fathom aborted) int nNodes_; /// Number of nodes explored int numberNodesExplored_; /// Number of iterations int numberIterations_; /// Type of presolve - 0 none, 1 crunch int presolveType_; #ifndef NO_FATHOM_PRINT /// Depth passed in int startingDepth_; /// Node at which called int nodeCalled_; #endif //@} }; class ClpHashValue { public: /**@name Useful methods */ //@{ /// Return index or -1 if not found int index(double value) const; /// Add value to list and return index int addValue(double value) ; /// Number of different entries inline int numberEntries() const { return numberHash_; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpHashValue(); /** Useful constructor. */ ClpHashValue(ClpSimplex * model); /** Destructor */ virtual ~ClpHashValue(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpHashValue(const ClpHashValue&); /// = ClpHashValue& operator=(const ClpHashValue&); //@} private: /**@name private stuff */ //@{ /** returns hash */ int hash(double value) const; /// Resizes void resize(bool increaseMax); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Data // for hashing typedef struct { double value; int index, next; } CoinHashLink; /// Hash table mutable CoinHashLink *hash_; /// Number of entries in hash table int numberHash_; /// Maximum number of entries in hash table i.e. size int maxHash_; /// Last used space int lastUsed_; //@} }; #endif Clp-1.15.10/src/ClpDynamicMatrix.cpp0000644000076600007660000034003112131314313015547 0ustar coincoin/* $Id: ClpDynamicMatrix.cpp 1941 2013-04-10 16:52:27Z 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 "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpNonLinearCost.hpp" // at end to get min/max! #include "ClpDynamicMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDynamicMatrix::ClpDynamicMatrix () : ClpPackedMatrix(), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), sumOfRelaxedDualInfeasibilities_(0.0), sumOfRelaxedPrimalInfeasibilities_(0.0), savedBestGubDual_(0.0), savedBestSet_(0), backToPivotRow_(NULL), keyVariable_(NULL), toIndex_(NULL), fromIndex_(NULL), numberSets_(0), numberActiveSets_(0), objectiveOffset_(0.0), lowerSet_(NULL), upperSet_(NULL), status_(NULL), model_(NULL), firstAvailable_(0), firstAvailableBefore_(0), firstDynamic_(0), lastDynamic_(0), numberStaticRows_(0), numberElements_(0), numberDualInfeasibilities_(0), numberPrimalInfeasibilities_(0), noCheck_(-1), infeasibilityWeight_(0.0), numberGubColumns_(0), maximumGubColumns_(0), maximumElements_(0), startSet_(NULL), next_(NULL), startColumn_(NULL), row_(NULL), element_(NULL), cost_(NULL), id_(NULL), dynamicStatus_(NULL), columnLower_(NULL), columnUpper_(NULL) { setType(15); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDynamicMatrix::ClpDynamicMatrix (const ClpDynamicMatrix & rhs) : ClpPackedMatrix(rhs) { objectiveOffset_ = rhs.objectiveOffset_; numberSets_ = rhs.numberSets_; numberActiveSets_ = rhs.numberActiveSets_; firstAvailable_ = rhs.firstAvailable_; firstAvailableBefore_ = rhs.firstAvailableBefore_; firstDynamic_ = rhs.firstDynamic_; lastDynamic_ = rhs.lastDynamic_; numberStaticRows_ = rhs.numberStaticRows_; numberElements_ = rhs.numberElements_; backToPivotRow_ = ClpCopyOfArray(rhs.backToPivotRow_, lastDynamic_); keyVariable_ = ClpCopyOfArray(rhs.keyVariable_, numberSets_); toIndex_ = ClpCopyOfArray(rhs.toIndex_, numberSets_); fromIndex_ = ClpCopyOfArray(rhs.fromIndex_, getNumRows() + 1 - numberStaticRows_); lowerSet_ = ClpCopyOfArray(rhs.lowerSet_, numberSets_); upperSet_ = ClpCopyOfArray(rhs.upperSet_, numberSets_); status_ = ClpCopyOfArray(rhs.status_, static_cast(2*numberSets_+4*sizeof(int))); model_ = rhs.model_; sumDualInfeasibilities_ = rhs. sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; savedBestGubDual_ = rhs.savedBestGubDual_; savedBestSet_ = rhs.savedBestSet_; noCheck_ = rhs.noCheck_; infeasibilityWeight_ = rhs.infeasibilityWeight_; // Now secondary data numberGubColumns_ = rhs.numberGubColumns_; maximumGubColumns_ = rhs.maximumGubColumns_; maximumElements_ = rhs.maximumElements_; startSet_ = ClpCopyOfArray(rhs.startSet_, numberSets_+1); next_ = ClpCopyOfArray(rhs.next_, maximumGubColumns_); startColumn_ = ClpCopyOfArray(rhs.startColumn_, maximumGubColumns_ + 1); row_ = ClpCopyOfArray(rhs.row_, maximumElements_); element_ = ClpCopyOfArray(rhs.element_, maximumElements_); cost_ = ClpCopyOfArray(rhs.cost_, maximumGubColumns_); id_ = ClpCopyOfArray(rhs.id_, lastDynamic_ - firstDynamic_); columnLower_ = ClpCopyOfArray(rhs.columnLower_, maximumGubColumns_); columnUpper_ = ClpCopyOfArray(rhs.columnUpper_, maximumGubColumns_); dynamicStatus_ = ClpCopyOfArray(rhs.dynamicStatus_, 2*maximumGubColumns_); } /* This is the real constructor*/ ClpDynamicMatrix::ClpDynamicMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * columnLower, const double * columnUpper, const unsigned char * status, const unsigned char * dynamicStatus) : ClpPackedMatrix() { setType(15); objectiveOffset_ = model->objectiveOffset(); model_ = model; numberSets_ = numberSets; numberGubColumns_ = numberGubColumns; maximumGubColumns_ = numberGubColumns_; if (numberGubColumns_) maximumElements_ = startColumn[numberGubColumns_]; else maximumElements_ = 0; startSet_ = new int [numberSets_+1]; next_ = new int [maximumGubColumns_]; // fill in startSet and next int iSet; if (numberGubColumns_) { for (iSet = 0; iSet < numberSets_; iSet++) { int first = starts[iSet]; int last = starts[iSet+1] - 1; startSet_[iSet] = first; for (int i = first; i < last; i++) next_[i] = i + 1; next_[last] = -iSet - 1; } startSet_[numberSets_] = starts[numberSets_]; } int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); numberStaticRows_ = numberRows; savedBestGubDual_ = 0.0; savedBestSet_ = 0; // Number of columns needed int frequency = model->factorizationFrequency(); int numberGubInSmall = numberRows + frequency + CoinMin(frequency, numberSets_) + 4; // But we may have two per row + one for incoming (make it two) numberGubInSmall = CoinMax(2*numberRows+2,numberGubInSmall); // for small problems this could be too big //numberGubInSmall = CoinMin(numberGubInSmall,numberGubColumns_); int numberNeeded = numberGubInSmall + numberColumns; firstAvailable_ = numberColumns; firstAvailableBefore_ = firstAvailable_; firstDynamic_ = numberColumns; lastDynamic_ = numberNeeded; startColumn_ = ClpCopyOfArray(startColumn, numberGubColumns_ + 1); if (!numberGubColumns_) { if (!startColumn_) startColumn_ = new CoinBigIndex [1]; startColumn_[0] = 0; } CoinBigIndex numberElements = startColumn_[numberGubColumns_]; row_ = ClpCopyOfArray(row, numberElements); element_ = new double[numberElements]; CoinBigIndex i; for (i = 0; i < numberElements; i++) element_[i] = element[i]; cost_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) { cost_[i] = cost[i]; // I don't think I need sorted but ... CoinSort_2(row_ + startColumn_[i], row_ + startColumn_[i+1], element_ + startColumn_[i]); } if (columnLower) { columnLower_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) columnLower_[i] = columnLower[i]; } else { columnLower_ = NULL; } if (columnUpper) { columnUpper_ = new double[numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) columnUpper_[i] = columnUpper[i]; } else { columnUpper_ = NULL; } lowerSet_ = new double[numberSets_]; for (i = 0; i < numberSets_; i++) { if (lower[i] > -1.0e20) lowerSet_[i] = lower[i]; else lowerSet_[i] = -1.0e30; } upperSet_ = new double[numberSets_]; for (i = 0; i < numberSets_; i++) { if (upper[i] < 1.0e20) upperSet_[i] = upper[i]; else upperSet_[i] = 1.0e30; } id_ = new int[numberGubInSmall]; for (i = 0; i < numberGubInSmall; i++) id_[i] = -1; ClpPackedMatrix* originalMatrixA = dynamic_cast< ClpPackedMatrix*>(model->clpMatrix()); assert (originalMatrixA); CoinPackedMatrix * originalMatrix = originalMatrixA->getPackedMatrix(); originalMatrixA->setMatrixNull(); // so can be deleted safely // guess how much space needed double guess = numberElements; guess /= static_cast (numberColumns); guess *= 2 * numberGubInSmall; numberElements_ = static_cast (guess); numberElements_ = CoinMin(numberElements_, numberElements) + originalMatrix->getNumElements(); matrix_ = originalMatrix; //delete originalMatrixA; flags_ &= ~1; // resize model (matrix stays same) // modify frequency if (frequency>=50) frequency = 50+(frequency-50)/2; int newRowSize = numberRows + CoinMin(numberSets_, frequency+numberRows) + 1; model->resize(newRowSize, numberNeeded); for (i = numberRows; i < newRowSize; i++) model->setRowStatus(i, ClpSimplex::basic); if (columnUpper_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i = firstDynamic_; i < lastDynamic_; i++) columnUpper[i] = 1.0e10; } // resize matrix // extra 1 is so can keep number of elements handy originalMatrix->reserve(numberNeeded, numberElements_, true); originalMatrix->reserve(numberNeeded + 1, numberElements_, false); originalMatrix->getMutableVectorStarts()[numberColumns] = originalMatrix->getNumElements(); originalMatrix->setDimensions(newRowSize, -1); numberActiveColumns_ = firstDynamic_; // redo number of columns numberColumns = matrix_->getNumCols(); backToPivotRow_ = new int[numberNeeded]; keyVariable_ = new int[numberSets_]; if (status) { status_ = ClpCopyOfArray(status, static_cast(2*numberSets_+4*sizeof(int))); assert (dynamicStatus); dynamicStatus_ = ClpCopyOfArray(dynamicStatus, 2*numberGubColumns_); } else { status_ = new unsigned char [2*numberSets_+4*sizeof(int)]; memset(status_, 0, numberSets_); int i; for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } dynamicStatus_ = new unsigned char [2*numberGubColumns_]; memset(dynamicStatus_, 0, numberGubColumns_); // for clarity for (i = 0; i < numberGubColumns_; i++) setDynamicStatus(i, atLowerBound); } toIndex_ = new int[numberSets_]; for (iSet = 0; iSet < numberSets_; iSet++) toIndex_[iSet] = -1; fromIndex_ = new int [newRowSize-numberStaticRows_+1]; numberActiveSets_ = 0; rhsOffset_ = NULL; if (numberGubColumns_) { if (!status) { gubCrash(); } else { initialProblem(); } } noCheck_ = -1; infeasibilityWeight_ = 0.0; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDynamicMatrix::~ClpDynamicMatrix () { delete [] backToPivotRow_; delete [] keyVariable_; delete [] toIndex_; delete [] fromIndex_; delete [] lowerSet_; delete [] upperSet_; delete [] status_; delete [] startSet_; delete [] next_; delete [] startColumn_; delete [] row_; delete [] element_; delete [] cost_; delete [] id_; delete [] dynamicStatus_; delete [] columnLower_; delete [] columnUpper_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDynamicMatrix & ClpDynamicMatrix::operator=(const ClpDynamicMatrix& rhs) { if (this != &rhs) { ClpPackedMatrix::operator=(rhs); delete [] backToPivotRow_; delete [] keyVariable_; delete [] toIndex_; delete [] fromIndex_; delete [] lowerSet_; delete [] upperSet_; delete [] status_; delete [] startSet_; delete [] next_; delete [] startColumn_; delete [] row_; delete [] element_; delete [] cost_; delete [] id_; delete [] dynamicStatus_; delete [] columnLower_; delete [] columnUpper_; objectiveOffset_ = rhs.objectiveOffset_; numberSets_ = rhs.numberSets_; numberActiveSets_ = rhs.numberActiveSets_; firstAvailable_ = rhs.firstAvailable_; firstAvailableBefore_ = rhs.firstAvailableBefore_; firstDynamic_ = rhs.firstDynamic_; lastDynamic_ = rhs.lastDynamic_; numberStaticRows_ = rhs.numberStaticRows_; numberElements_ = rhs.numberElements_; backToPivotRow_ = ClpCopyOfArray(rhs.backToPivotRow_, lastDynamic_); keyVariable_ = ClpCopyOfArray(rhs.keyVariable_, numberSets_); toIndex_ = ClpCopyOfArray(rhs.toIndex_, numberSets_); fromIndex_ = ClpCopyOfArray(rhs.fromIndex_, getNumRows() + 1 - numberStaticRows_); lowerSet_ = ClpCopyOfArray(rhs.lowerSet_, numberSets_); upperSet_ = ClpCopyOfArray(rhs.upperSet_, numberSets_); status_ = ClpCopyOfArray(rhs.status_, static_cast(2*numberSets_+4*sizeof(int))); model_ = rhs.model_; sumDualInfeasibilities_ = rhs. sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_; sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_; numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_; numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_; savedBestGubDual_ = rhs.savedBestGubDual_; savedBestSet_ = rhs.savedBestSet_; noCheck_ = rhs.noCheck_; infeasibilityWeight_ = rhs.infeasibilityWeight_; // Now secondary data numberGubColumns_ = rhs.numberGubColumns_; maximumGubColumns_ = rhs.maximumGubColumns_; maximumElements_ = rhs.maximumElements_; startSet_ = ClpCopyOfArray(rhs.startSet_, numberSets_+1); next_ = ClpCopyOfArray(rhs.next_, maximumGubColumns_); startColumn_ = ClpCopyOfArray(rhs.startColumn_, maximumGubColumns_ + 1); row_ = ClpCopyOfArray(rhs.row_, maximumElements_); element_ = ClpCopyOfArray(rhs.element_, maximumElements_); cost_ = ClpCopyOfArray(rhs.cost_, maximumGubColumns_); id_ = ClpCopyOfArray(rhs.id_, lastDynamic_ - firstDynamic_); columnLower_ = ClpCopyOfArray(rhs.columnLower_, maximumGubColumns_); columnUpper_ = ClpCopyOfArray(rhs.columnUpper_, maximumGubColumns_); dynamicStatus_ = ClpCopyOfArray(rhs.dynamicStatus_, 2*maximumGubColumns_); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpDynamicMatrix::clone() const { return new ClpDynamicMatrix(*this); } // Partial pricing void ClpDynamicMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; assert(!model->rowScale()); if (numberSets_) { // Do packed part before gub // always??? //printf("normal packed price - start %d end %d (passed end %d, first %d)\n", ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); } else { // no gub ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); return; } if (numberWanted > 0) { // and do some proportion of full set int startG2 = static_cast (startFraction * numberSets_); int endG2 = static_cast (endFraction * numberSets_ + 0.1); endG2 = CoinMin(endG2, numberSets_); //printf("gub price - set start %d end %d\n", // startG2,endG2); double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); double bestDj; int numberRows = model->numberRows(); int slackOffset = lastDynamic_ + numberRows; int structuralOffset = slackOffset + numberSets_; // If nothing found yet can go all the way to end int endAll = endG2; if (bestSequence < 0 && !startG2) endAll = numberSets_; if (bestSequence >= 0) { if (bestSequence != savedBestSequence_) bestDj = fabs(reducedCost[bestSequence]); // dj from slacks or permanent else bestDj = savedBestDj_; } else { bestDj = tolerance; } int saveSequence = bestSequence; double djMod = 0.0; double bestDjMod = 0.0; //printf("iteration %d start %d end %d - wanted %d\n",model->numberIterations(), // startG2,endG2,numberWanted); int bestSet = -1; #if 0 // make sure first available is clean (in case last iteration rejected) cost[firstAvailable_] = 0.0; length[firstAvailable_] = 0; model->nonLinearCost()->setOne(firstAvailable_, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); { for (int i = firstAvailable_; i < lastDynamic_; i++) assert(!cost[i]); } #endif int minSet = minimumObjectsScan_ < 0 ? 5 : minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ < 0 ? 5 : minimumGoodReducedCosts_; for (int iSet = startG2; iSet < endAll; iSet++) { if (numberWanted + minNeg < originalWanted_ && iSet > startG2 + minSet) { // give up numberWanted = 0; break; } else if (iSet == endG2 && bestSequence >= 0) { break; } int gubRow = toIndex_[iSet]; if (gubRow >= 0) { djMod = duals[gubRow+numberStaticRows_]; // have I got sign right? } else { int iBasic = keyVariable_[iSet]; if (iBasic >= maximumGubColumns_) { djMod = 0.0; // set not in } else { // get dj without djMod = 0.0; for (CoinBigIndex j = startColumn_[iBasic]; j < startColumn_[iBasic+1]; j++) { int jRow = row_[j]; djMod -= duals[jRow] * element_[j]; } djMod += cost_[iBasic]; // See if gub slack possible - dj is djMod if (getStatus(iSet) == ClpSimplex::atLowerBound) { double value = -djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = slackOffset + iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet) == ClpSimplex::atUpperBound) { double value = djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = slackOffset + iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } } int iSequence = startSet_[iSet]; while (iSequence >= 0) { DynamicStatus status = getDynamicStatus(iSequence); if (status == atLowerBound || status == atUpperBound) { double value = cost_[iSequence] - djMod; for (CoinBigIndex j = startColumn_[iSequence]; j < startColumn_[iSequence+1]; j++) { int jRow = row_[j]; value -= duals[jRow] * element_[j]; } // change sign if at lower bound if (status == atLowerBound) value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSequence)) { if (false/*status == atLowerBound &&keyValue(iSet)<1.0e-7*/) { // can't come in because // of ones at ub numberWanted++; } else { bestDj = value; bestSequence = structuralOffset + iSequence; bestDjMod = djMod; bestSet = iSet; } } else { // just to make sure we don't exit before got something numberWanted++; } } } } iSequence = next_[iSequence]; //onto next in set } if (numberWanted <= 0) { numberWanted = 0; break; } } if (bestSequence != saveSequence) { savedBestGubDual_ = bestDjMod; savedBestDj_ = bestDj; savedBestSequence_ = bestSequence; savedBestSet_ = bestSet; } // See if may be finished if (!startG2 && bestSequence < 0) infeasibilityWeight_ = model_->infeasibilityCost(); else if (bestSequence >= 0) infeasibilityWeight_ = -1.0; } currentWanted_ = numberWanted; } /* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpDynamicMatrix::rhsOffset(ClpSimplex * model, bool forceRefresh, bool #ifdef CLP_DEBUG check #endif ) { // forceRefresh=true;printf("take out forceRefresh\n"); if (!model_->numberIterations()) forceRefresh = true; //check=false; #ifdef CLP_DEBUG double * saveE = NULL; if (rhsOffset_ && check) { int numberRows = model->numberRows(); saveE = new double[numberRows]; } #endif if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway int numberRows = model->numberRows(); double * rhs = new double[numberRows]; int iRow; int iSet; CoinZeroN(rhs, numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; double objectiveOffset = 0.0; for (iColumn = 0; iColumn < firstDynamic_; iColumn++) { if (model->getStatus(iColumn) != ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; rhs[jRow] -= value * element[j]; } } } if (columnLower_ || columnUpper_) { double * solution = new double [numberGubColumns_]; for (iSet = 0; iSet < numberSets_; iSet++) { int j = startSet_[iSet]; while (j >= 0) { double value = 0.0; if (getDynamicStatus(j) != inSmall) { if (getDynamicStatus(j) == atLowerBound) { if (columnLower_) value = columnLower_[j]; } else if (getDynamicStatus(j) == atUpperBound) { value = columnUpper_[j]; } else if (getDynamicStatus(j) == soloKey) { value = keyValue(iSet); } objectiveOffset += value * cost_[j]; } solution[j] = value; j = next_[j]; //onto next in set } } // ones in gub and in small problem for (iColumn = firstDynamic_; iColumn < firstAvailable_; iColumn++) { if (model_->getStatus(iColumn) != ClpSimplex::basic) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull] = smallSolution[iColumn]; } } for (iSet = 0; iSet < numberSets_; iSet++) { int kRow = toIndex_[iSet]; if (kRow >= 0) kRow += numberStaticRows_; int j = startSet_[iSet]; while (j >= 0) { double value = solution[j]; if (value) { for (CoinBigIndex k = startColumn_[j]; k < startColumn_[j+1]; k++) { int iRow = row_[k]; rhs[iRow] -= element_[k] * value; } if (kRow >= 0) rhs[kRow] -= value; } j = next_[j]; //onto next in set } } delete [] solution; } else { // bounds ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { int kRow = toIndex_[iSet]; if (kRow < 0) { int iColumn = keyVariable_[iSet]; if (iColumn < maximumGubColumns_) { // key is not treated as basic double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lowerSet_[iSet]; else b = upperSet_[iSet]; if (b) { objectiveOffset += b * cost_[iColumn]; for (CoinBigIndex j = startColumn_[iColumn]; j < startColumn_[iColumn+1]; j++) { int iRow = row_[j]; rhs[iRow] -= element_[j] * b; } } } } } } if (fabs(model->objectiveOffset() - objectiveOffset_ - objectiveOffset) > 1.0e-1) printf("old offset %g, true %g\n", model->objectiveOffset(), objectiveOffset_ - objectiveOffset); for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** bad effective %d - true %g old %g\n", iRow, rhs[iRow], rhsOffset_[iRow]); } CoinMemcpyN(rhs, numberRows, saveE); delete [] rhs; } #endif if (forceRefresh || (refreshFrequency_ && model->numberIterations() >= lastRefresh_ + refreshFrequency_)) { int numberRows = model->numberRows(); int iSet; CoinZeroN(rhsOffset_, numberRows); // do ones at bounds before gub const double * smallSolution = model->solutionRegion(); const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int iColumn; double objectiveOffset = 0.0; for (iColumn = 0; iColumn < firstDynamic_; iColumn++) { if (model->getStatus(iColumn) != ClpSimplex::basic) { double value = smallSolution[iColumn]; for (CoinBigIndex j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; rhsOffset_[jRow] -= value * element[j]; } } } if (columnLower_ || columnUpper_) { double * solution = new double [numberGubColumns_]; for (iSet = 0; iSet < numberSets_; iSet++) { int j = startSet_[iSet]; while (j >= 0) { double value = 0.0; if (getDynamicStatus(j) != inSmall) { if (getDynamicStatus(j) == atLowerBound) { if (columnLower_) value = columnLower_[j]; } else if (getDynamicStatus(j) == atUpperBound) { value = columnUpper_[j]; assert (value<1.0e30); } else if (getDynamicStatus(j) == soloKey) { value = keyValue(iSet); } objectiveOffset += value * cost_[j]; } solution[j] = value; j = next_[j]; //onto next in set } } // ones in gub and in small problem for (iColumn = firstDynamic_; iColumn < firstAvailable_; iColumn++) { if (model_->getStatus(iColumn) != ClpSimplex::basic) { int jFull = id_[iColumn-firstDynamic_]; solution[jFull] = smallSolution[iColumn]; } } for (iSet = 0; iSet < numberSets_; iSet++) { int kRow = toIndex_[iSet]; if (kRow >= 0) kRow += numberStaticRows_; int j = startSet_[iSet]; while (j >= 0) { //? use DynamicStatus status = getDynamicStatus(j); double value = solution[j]; if (value) { for (CoinBigIndex k = startColumn_[j]; k < startColumn_[j+1]; k++) { int iRow = row_[k]; rhsOffset_[iRow] -= element_[k] * value; } if (kRow >= 0) rhsOffset_[kRow] -= value; } j = next_[j]; //onto next in set } } delete [] solution; } else { // bounds ClpSimplex::Status iStatus; for (int iSet = 0; iSet < numberSets_; iSet++) { int kRow = toIndex_[iSet]; if (kRow < 0) { int iColumn = keyVariable_[iSet]; if (iColumn < maximumGubColumns_) { // key is not treated as basic double b = 0.0; // key is structural - where is slack iStatus = getStatus(iSet); assert (iStatus != ClpSimplex::basic); if (iStatus == ClpSimplex::atLowerBound) b = lowerSet_[iSet]; else b = upperSet_[iSet]; if (b) { objectiveOffset += b * cost_[iColumn]; for (CoinBigIndex j = startColumn_[iColumn]; j < startColumn_[iColumn+1]; j++) { int iRow = row_[j]; rhsOffset_[iRow] -= element_[j] * b; } } } } } } model->setObjectiveOffset(objectiveOffset_ - objectiveOffset); #ifdef CLP_DEBUG if (saveE) { int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(saveE[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** %d - old eff %g new %g\n", iRow, saveE[iRow], rhsOffset_[iRow]); } delete [] saveE; } #endif lastRefresh_ = model->numberIterations(); } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpDynamicMatrix::updatePivot(ClpSimplex * model, double oldInValue, double oldOutValue) { // now update working model int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); int numberColumns = model->numberColumns(); if (sequenceIn != sequenceOut && sequenceIn < numberColumns) backToPivotRow_[sequenceIn] = model->pivotRow(); if (sequenceIn >= firstDynamic_ && sequenceIn < numberColumns) { int bigSequence = id_[sequenceIn-firstDynamic_]; if (getDynamicStatus(bigSequence) != inSmall) { firstAvailable_++; setDynamicStatus(bigSequence, inSmall); } } // make sure slack is synchronized if (sequenceIn >= numberColumns + numberStaticRows_) { int iDynamic = sequenceIn - numberColumns - numberStaticRows_; int iSet = fromIndex_[iDynamic]; setStatus(iSet, model->getStatus(sequenceIn)); } if (sequenceOut >= numberColumns + numberStaticRows_) { int iDynamic = sequenceOut - numberColumns - numberStaticRows_; int iSet = fromIndex_[iDynamic]; // out may have gone through barrier - so check double valueOut = model->lowerRegion()[sequenceOut]; if (fabs(valueOut - static_cast (lowerSet_[iSet])) < fabs(valueOut - static_cast (upperSet_[iSet]))) setStatus(iSet, ClpSimplex::atLowerBound); else setStatus(iSet, ClpSimplex::atUpperBound); if (lowerSet_[iSet] == upperSet_[iSet]) setStatus(iSet, ClpSimplex::isFixed); #if 0 if (getStatus(iSet) != model->getStatus(sequenceOut)) printf("** set %d status %d, var status %d\n", iSet, getStatus(iSet), model->getStatus(sequenceOut)); #endif } ClpMatrixBase::updatePivot(model, oldInValue, oldOutValue); #ifdef CLP_DEBUG char * inSmall = new char [numberGubColumns_]; memset(inSmall, 0, numberGubColumns_); const double * solution = model->solutionRegion(); for (int i = 0; i < numberGubColumns_; i++) if (getDynamicStatus(i) == ClpDynamicMatrix::inSmall) inSmall[i] = 1; for (int i = firstDynamic_; i < firstAvailable_; i++) { int k = id_[i-firstDynamic_]; inSmall[k] = 0; //if (k>=23289&&k<23357&&solution[i]) //printf("var %d (in small %d) has value %g\n",k,i,solution[i]); } for (int i = 0; i < numberGubColumns_; i++) assert (!inSmall[i]); delete [] inSmall; #ifndef NDEBUG for (int i = 0; i < numberActiveSets_; i++) { int iSet = fromIndex_[i]; assert (toIndex_[iSet] == i); //if (getStatus(iSet)!=model->getRowStatus(i+numberStaticRows_)) //printf("*** set %d status %d, var status %d\n",iSet, // getStatus(iSet),model->getRowStatus(i+numberStaticRows_)); //assert (model->getRowStatus(i+numberStaticRows_)==getStatus(iSet)); //if (iSet==1035) { //printf("rhs for set %d (%d) is %g %g - cost %g\n",iSet,i,model->lowerRegion(0)[i+numberStaticRows_], // model->upperRegion(0)[i+numberStaticRows_],model->costRegion(0)[i+numberStaticRows_]); //} } #endif #endif if (numberStaticRows_+numberActiveSets_numberRows()) return 0; else return 1; } /* utility dual function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ void ClpDynamicMatrix::dualExpanded(ClpSimplex * model, CoinIndexedVector * /*array*/, double * /*other*/, int mode) { switch (mode) { // modify costs before transposeUpdate case 0: break; // create duals for key variables (without check on dual infeasible) case 1: break; // as 1 but check slacks and compute djs case 2: { // do pivots int * pivotVariable = model->pivotVariable(); int numberRows = numberStaticRows_ + numberActiveSets_; int numberColumns = model->numberColumns(); for (int iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; if (iPivot < numberColumns) backToPivotRow_[iPivot] = iRow; } if (noCheck_ >= 0) { if (infeasibilityWeight_ != model_->infeasibilityCost()) { // don't bother checking sumDualInfeasibilities_ = 100.0; numberDualInfeasibilities_ = 1; sumOfRelaxedDualInfeasibilities_ = 100.0; return; } } // In theory we should subtract out ones we have done but .... // If key slack then dual 0.0 // If not then slack could be dual infeasible // dj for key is zero so that defines dual on set int i; double * dual = model->dualRowSolution(); double dualTolerance = model->dualTolerance(); double relaxedTolerance = dualTolerance; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, model->largestDualError()); // allow tolerance at least slightly bigger than standard relaxedTolerance = relaxedTolerance + error; // but we will be using difference relaxedTolerance -= dualTolerance; sumDualInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; sumOfRelaxedDualInfeasibilities_ = 0.0; for (i = 0; i < numberSets_; i++) { double value = 0.0; int gubRow = toIndex_[i]; if (gubRow < 0) { int kColumn = keyVariable_[i]; if (kColumn < maximumGubColumns_) { // dj without set value = cost_[kColumn]; for (CoinBigIndex j = startColumn_[kColumn]; j < startColumn_[kColumn+1]; j++) { int iRow = row_[j]; value -= dual[iRow] * element_[j]; } double infeasibility = 0.0; if (getStatus(i) == ClpSimplex::atLowerBound) { if (-value > dualTolerance) infeasibility = -value - dualTolerance; } else if (getStatus(i) == ClpSimplex::atUpperBound) { if (value > dualTolerance) infeasibility = value - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } } else { value = dual[gubRow+numberStaticRows_]; } // Now subtract out from all int k = startSet_[i]; while (k >= 0) { if (getDynamicStatus(k) != inSmall) { double djValue = cost_[k] - value; for (CoinBigIndex j = startColumn_[k]; j < startColumn_[k+1]; j++) { int iRow = row_[j]; djValue -= dual[iRow] * element_[j]; } double infeasibility = 0.0; if (getDynamicStatus(k) == atLowerBound) { if (djValue < -dualTolerance) infeasibility = -djValue - dualTolerance; } else if (getDynamicStatus(k) == atUpperBound) { // at upper bound if (djValue > dualTolerance) infeasibility = djValue - dualTolerance; } if (infeasibility > 0.0) { sumDualInfeasibilities_ += infeasibility; if (infeasibility > relaxedTolerance) sumOfRelaxedDualInfeasibilities_ += infeasibility; numberDualInfeasibilities_ ++; } } k = next_[k]; //onto next in set } } } infeasibilityWeight_ = -1.0; break; // Report on infeasibilities of key variables case 3: { model->setSumDualInfeasibilities(model->sumDualInfeasibilities() + sumDualInfeasibilities_); model->setNumberDualInfeasibilities(model->numberDualInfeasibilities() + numberDualInfeasibilities_); model->setSumOfRelaxedDualInfeasibilities(model->sumOfRelaxedDualInfeasibilities() + sumOfRelaxedDualInfeasibilities_); } break; // modify costs before transposeUpdate for partial pricing case 4: break; } } /* general utility function for dealing with dynamic constraints mode=n see ClpGubMatrix.hpp for definition Remember to update here when settled down */ int ClpDynamicMatrix::generalExpanded(ClpSimplex * model, int mode, int &number) { int returnCode = 0; #if 0 //ndef NDEBUG { int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); int * pivotVariable = model->pivotVariable(); if (pivotVariable&&model->numberIterations()) { for (int i=numberStaticRows_+numberActiveSets_;inumberRows()]; rhsOffset(model, true); } int i; int numberBasic = number; int numberColumns = model->numberColumns(); // Use different array so can build from true pivotVariable_ //int * pivotVariable = model->pivotVariable(); int * pivotVariable = model->rowArray(0)->getIndices(); for (i = 0; i < numberColumns; i++) { if (model->getColumnStatus(i) == ClpSimplex::basic) pivotVariable[numberBasic++] = i; } number = numberBasic; } break; // Do initial extra rows + maximum basic case 2: { number = model->numberRows(); } break; // Before normal replaceColumn case 3: { if (numberActiveSets_ + numberStaticRows_ == model_->numberRows()) { // no space - re-factorize returnCode = 4; number = -1; // say no need for normal replaceColumn } } break; // To see if can dual or primal case 4: { returnCode = 1; } break; // save status case 5: { memcpy(status_+numberSets_,status_,numberSets_); memcpy(status_+2*numberSets_,&numberActiveSets_,sizeof(int)); memcpy(dynamicStatus_+maximumGubColumns_, dynamicStatus_,maximumGubColumns_); } break; // restore status case 6: { memcpy(status_,status_+numberSets_,numberSets_); memcpy(&numberActiveSets_,status_+2*numberSets_,sizeof(int)); memcpy(dynamicStatus_,dynamicStatus_+maximumGubColumns_, maximumGubColumns_); initialProblem(); } break; // unflag all variables case 8: { for (int i = 0; i < numberGubColumns_; i++) { if (flagged(i)) { unsetFlagged(i); returnCode++; } } } break; // redo costs in primal case 9: { double * cost = model->costRegion(); double * solution = model->solutionRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); int i; bool doCosts = (number & 4) != 0; bool doBounds = (number & 1) != 0; for ( i = firstDynamic_; i < firstAvailable_; i++) { int jColumn = id_[i-firstDynamic_]; if (doBounds) { if (!columnLower_ && !columnUpper_) { columnLower[i] = 0.0; columnUpper[i] = COIN_DBL_MAX; } else { if (columnLower_) columnLower[i] = columnLower_[jColumn]; else columnLower[i] = 0.0; if (columnUpper_) columnUpper[i] = columnUpper_[jColumn]; else columnUpper[i] = COIN_DBL_MAX; } } if (doCosts) { cost[i] = cost_[jColumn]; // Original bounds if (model->nonLinearCost()) model->nonLinearCost()->setOne(i, solution[i], this->columnLower(jColumn), this->columnUpper(jColumn), cost_[jColumn]); } } // and active sets for (i = 0; i < numberActiveSets_; i++ ) { int iSet = fromIndex_[i]; int iSequence = lastDynamic_ + numberStaticRows_ + i; if (doBounds) { if (lowerSet_[iSet] > -1.0e20) columnLower[iSequence] = lowerSet_[iSet]; else columnLower[iSequence] = -COIN_DBL_MAX; if (upperSet_[iSet] < 1.0e20) columnUpper[iSequence] = upperSet_[iSet]; else columnUpper[iSequence] = COIN_DBL_MAX; } if (doCosts) { if (model->nonLinearCost()) { double trueLower; if (lowerSet_[iSet] > -1.0e20) trueLower = lowerSet_[iSet]; else trueLower = -COIN_DBL_MAX; double trueUpper; if (upperSet_[iSet] < 1.0e20) trueUpper = upperSet_[iSet]; else trueUpper = COIN_DBL_MAX; model->nonLinearCost()->setOne(iSequence, solution[iSequence], trueLower, trueUpper, 0.0); } } } } break; // return 1 if there may be changing bounds on variable (column generation) case 10: { // return 1 as bounds on rhs will change returnCode = 1; } break; // make sure set is clean case 7: { // first flag if (number >= firstDynamic_ && number < lastDynamic_) { int sequence = id_[number-firstDynamic_]; setFlagged(sequence); //model->clearFlagged(number); } else if (number>=model_->numberColumns()+numberStaticRows_) { // slack int iSet = fromIndex_[number-model_->numberColumns()- numberStaticRows_]; setFlaggedSlack(iSet); //model->clearFlagged(number); } } case 11: { //int sequenceIn = model->sequenceIn(); if (number >= firstDynamic_ && number < lastDynamic_) { //assert (number == model->sequenceIn()); // take out variable (but leave key) double * cost = model->costRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * solution = model->solutionRegion(); int * length = matrix_->getMutableVectorLengths(); #ifndef NDEBUG if (length[number]) { int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int iRow = row[startColumn[number] + length[number] - 1]; int which = iRow - numberStaticRows_; assert (which >= 0); int iSet = fromIndex_[which]; assert (toIndex_[iSet] == which); } #endif // no need firstAvailable_--; solution[firstAvailable_] = 0.0; cost[firstAvailable_] = 0.0; length[firstAvailable_] = 0; model->nonLinearCost()->setOne(firstAvailable_, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; // not really in small problem int iBig = id_[number-firstDynamic_]; if (model->getStatus(number) == ClpSimplex::atLowerBound) { setDynamicStatus(iBig, atLowerBound); if (columnLower_) modifyOffset(number, columnLower_[iBig]); } else { setDynamicStatus(iBig, atUpperBound); modifyOffset(number, columnUpper_[iBig]); } } else if (number>=model_->numberColumns()+numberStaticRows_) { // slack int iSet = fromIndex_[number-model_->numberColumns()- numberStaticRows_]; printf("what now - set %d\n",iSet); } } break; default: break; } return returnCode; } /* Purely for column generation and similar ideas. Allows matrix and any bounds or costs to be updated (sensibly). Returns non-zero if any changes. */ int ClpDynamicMatrix::refresh(ClpSimplex * model) { // If at beginning then create initial problem if (firstDynamic_ == firstAvailable_) { initialProblem(); return 1; } else if (!model->nonLinearCost()) { // will be same as last time return 1; } #ifndef NDEBUG { int numberColumns = model->numberColumns(); int numberRows = model->numberRows(); int * pivotVariable = model->pivotVariable(); for (int i=numberStaticRows_+numberActiveSets_;inumberColumns(); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double * cost = model->costRegion(); double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); CoinBigIndex numberElements = startColumn[firstDynamic_]; // first just do lookup and basic stuff int currentNumber = firstAvailable_; firstAvailable_ = firstDynamic_; double objectiveChange = 0.0; double * solution = model->solutionRegion(); int currentNumberActiveSets = numberActiveSets_; for (iColumn = firstDynamic_; iColumn < currentNumber; iColumn++) { int iRow = row[startColumn[iColumn] + length[iColumn] - 1]; int which = iRow - numberStaticRows_; assert (which >= 0); int iSet = fromIndex_[which]; assert (toIndex_[iSet] == which); if (model->getStatus(iColumn) == ClpSimplex::basic) { active[which]++; // may as well make key keyVariable_[iSet] = id_[iColumn-firstDynamic_]; } } int i; numberActiveSets_ = 0; int numberDeleted = 0; for (i = 0; i < currentNumberActiveSets; i++) { int iRow = i + numberStaticRows_; int numberActive = active[i]; int iSet = fromIndex_[i]; if (model->getRowStatus(iRow) == ClpSimplex::basic) { numberActive++; // may as well make key keyVariable_[iSet] = maximumGubColumns_ + iSet; } if (numberActive > 1) { // keep active[i] = numberActiveSets_; numberActiveSets_++; } else { active[i] = -1; } } for (iColumn = firstDynamic_; iColumn < currentNumber; iColumn++) { int iRow = row[startColumn[iColumn] + length[iColumn] - 1]; int which = iRow - numberStaticRows_; int jColumn = id_[iColumn-firstDynamic_]; if (model->getStatus(iColumn) == ClpSimplex::atLowerBound || model->getStatus(iColumn) == ClpSimplex::atUpperBound) { double value = solution[iColumn]; bool toLowerBound = true; assert (jColumn>=0);assert (iColumn>=0); if (columnUpper_) { if (!columnLower_) { if (fabs(value - columnUpper_[jColumn]) < fabs(value)) toLowerBound = false; } else if (fabs(value - columnUpper_[jColumn]) < fabs(value - columnLower_[jColumn])) { toLowerBound = false; } } if (toLowerBound) { // throw out to lower bound if (columnLower_) { setDynamicStatus(jColumn, atLowerBound); // treat solution as if exactly at a bound double value = columnLower[iColumn]; objectiveChange += cost[iColumn] * value; } else { setDynamicStatus(jColumn, atLowerBound); } } else { // throw out to upper bound setDynamicStatus(jColumn, atUpperBound); double value = columnUpper[iColumn]; objectiveChange += cost[iColumn] * value; } numberDeleted++; } else { assert(model->getStatus(iColumn) != ClpSimplex::superBasic); // deal with later int iPut = active[which]; if (iPut >= 0) { // move id_[firstAvailable_-firstDynamic_] = jColumn; int numberThis = startColumn_[jColumn+1] - startColumn_[jColumn] + 1; length[firstAvailable_] = numberThis; cost[firstAvailable_] = cost[iColumn]; columnLower[firstAvailable_] = columnLower[iColumn]; columnUpper[firstAvailable_] = columnUpper[iColumn]; model->nonLinearCost()->setOne(firstAvailable_, solution[iColumn], 0.0, COIN_DBL_MAX, cost_[jColumn]); CoinBigIndex base = startColumn_[jColumn]; for (int j = 0; j < numberThis - 1; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } row[numberElements] = iPut + numberStaticRows_; element[numberElements++] = 1.0; model->setStatus(firstAvailable_, model->getStatus(iColumn)); solution[firstAvailable_] = solution[iColumn]; firstAvailable_++; startColumn[firstAvailable_] = numberElements; } } } // zero solution CoinZeroN(solution + firstAvailable_, currentNumber - firstAvailable_); // zero cost CoinZeroN(cost + firstAvailable_, currentNumber - firstAvailable_); // zero lengths CoinZeroN(length + firstAvailable_, currentNumber - firstAvailable_); for ( iColumn = firstAvailable_; iColumn < currentNumber; iColumn++) { model->nonLinearCost()->setOne(iColumn, 0.0, 0.0, COIN_DBL_MAX, 0.0); model->setStatus(iColumn, ClpSimplex::atLowerBound); columnLower[iColumn] = 0.0; columnUpper[iColumn] = COIN_DBL_MAX; } // move rhs and set rest to infinite numberActiveSets_ = 0; for (i = 0; i < currentNumberActiveSets; i++) { int iSet = fromIndex_[i]; assert (toIndex_[iSet] == i); int iRow = i + numberStaticRows_; int iPut = active[i]; if (iPut >= 0) { int in = iRow + numberColumns; int out = iPut + numberColumns + numberStaticRows_; solution[out] = solution[in]; columnLower[out] = columnLower[in]; columnUpper[out] = columnUpper[in]; cost[out] = cost[in]; double trueLower; if (lowerSet_[iSet] > -1.0e20) trueLower = lowerSet_[iSet]; else trueLower = -COIN_DBL_MAX; double trueUpper; if (upperSet_[iSet] < 1.0e20) trueUpper = upperSet_[iSet]; else trueUpper = COIN_DBL_MAX; model->nonLinearCost()->setOne(out, solution[out], trueLower, trueUpper, 0.0); model->setStatus(out, model->getStatus(in)); toIndex_[iSet] = numberActiveSets_; rhsOffset_[numberActiveSets_+numberStaticRows_] = rhsOffset_[i+numberStaticRows_]; fromIndex_[numberActiveSets_++] = fromIndex_[i]; } else { // adjust offset // put out as key int jColumn = keyVariable_[iSet]; toIndex_[iSet] = -1; if (jColumn < maximumGubColumns_) { setDynamicStatus(jColumn, soloKey); double value = keyValue(iSet); objectiveChange += cost_[jColumn] * value; modifyOffset(jColumn, -value); } } } model->setObjectiveOffset(model->objectiveOffset() - objectiveChange); delete [] active; for (i = numberActiveSets_; i < currentNumberActiveSets; i++) { int iSequence = i + numberStaticRows_ + numberColumns; solution[iSequence] = 0.0; columnLower[iSequence] = -COIN_DBL_MAX; columnUpper[iSequence] = COIN_DBL_MAX; cost[iSequence] = 0.0; model->nonLinearCost()->setOne(iSequence, solution[iSequence], columnLower[iSequence], columnUpper[iSequence], 0.0); model->setStatus(iSequence, ClpSimplex::basic); rhsOffset_[i+numberStaticRows_] = 0.0; } if (currentNumberActiveSets != numberActiveSets_ || numberDeleted) { // deal with pivotVariable int * pivotVariable = model->pivotVariable(); int sequence = firstDynamic_; int iRow = 0; int base1 = firstDynamic_; int base2 = lastDynamic_; int base3 = numberColumns + numberStaticRows_; int numberRows = numberStaticRows_ + currentNumberActiveSets; while (sequence < firstAvailable_) { int iPivot = pivotVariable[iRow]; while (iPivot < base1 || (iPivot >= base2 && iPivot < base3)) { iPivot = pivotVariable[++iRow]; } pivotVariable[iRow++] = sequence; sequence++; } // move normal basic ones down int iPut = iRow; for (; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; if (iPivot < base1 || (iPivot >= base2 && iPivot < base3)) { pivotVariable[iPut++] = iPivot; } } // and basic others for (i = 0; i < numberActiveSets_; i++) { if (model->getRowStatus(i + numberStaticRows_) == ClpSimplex::basic) { pivotVariable[iPut++] = i + base3; } } if (iPut= 0) { printf("var %d status %d ", jj, dynamicStatus_[jj]); jj = next_[jj]; } printf("\n"); #endif #ifdef CLP_DEBUG { // debug coding to analyze set int i; int kSet = -6; if (kSet >= 0) { int * back = new int [numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) back[i] = -1; for (i = firstDynamic_; i < firstAvailable_; i++) back[id_[i-firstDynamic_]] = i; int sequence = startSet_[kSet]; if (toIndex_[kSet] < 0) { printf("Not in - Set %d - slack status %d, key %d\n", kSet, status_[kSet], keyVariable_[kSet]); while (sequence >= 0) { printf("( %d status %d ) ", sequence, getDynamicStatus(sequence)); sequence = next_[sequence]; } } else { int iRow = numberStaticRows_ + toIndex_[kSet]; printf("In - Set %d - slack status %d, key %d offset %g slack %g\n", kSet, status_[kSet], keyVariable_[kSet], rhsOffset_[iRow], model->solutionRegion(0)[iRow]); while (sequence >= 0) { int iBack = back[sequence]; printf("( %d status %d value %g) ", sequence, getDynamicStatus(sequence), model->solutionRegion()[iBack]); sequence = next_[sequence]; } } printf("\n"); delete [] back; } } #endif int n = numberActiveSets_; for (i = 0; i < numberSets_; i++) { if (toIndex_[i] < 0) { //assert(keyValue(i)>=lowerSet_[i]&&keyValue(i)<=upperSet_[i]); n++; } int k=0; for (int j=startSet_[i];jspecialOptions() != 16) { ClpPackedMatrix::times(scalar, x, y); } else { int iRow; const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * startColumn = matrix_->getVectorStarts(); const int * length = matrix_->getVectorLengths(); int * pivotVariable = model_->pivotVariable(); for (iRow = 0; iRow < numberStaticRows_ + numberActiveSets_; iRow++) { y[iRow] -= scalar * rhsOffset_[iRow]; int iColumn = pivotVariable[iRow]; if (iColumn < lastDynamic_) { CoinBigIndex j; double value = scalar * x[iColumn]; if (value) { for (j = startColumn[iColumn]; j < startColumn[iColumn] + length[iColumn]; j++) { int jRow = row[j]; y[jRow] += value * element[j]; } } } } } } // Modifies rhs offset void ClpDynamicMatrix::modifyOffset(int sequence, double amount) { if (amount) { assert (rhsOffset_); CoinBigIndex j; for (j = startColumn_[sequence]; j < startColumn_[sequence+1]; j++) { int iRow = row_[j]; rhsOffset_[iRow] += amount * element_[j]; } } } // Gets key value when none in small double ClpDynamicMatrix::keyValue(int iSet) const { double value = 0.0; if (toIndex_[iSet] < 0) { int key = keyVariable_[iSet]; if (key < maximumGubColumns_) { if (getStatus(iSet) == ClpSimplex::atLowerBound) value = lowerSet_[iSet]; else value = upperSet_[iSet]; int numberKey = 0; int j = startSet_[iSet]; while (j >= 0) { DynamicStatus status = getDynamicStatus(j); assert (status != inSmall); if (status == soloKey) { numberKey++; } else if (status == atUpperBound) { value -= columnUpper_[j]; } else if (columnLower_) { value -= columnLower_[j]; } j = next_[j]; //onto next in set } assert (numberKey == 1); } else { int j = startSet_[iSet]; while (j >= 0) { DynamicStatus status = getDynamicStatus(j); assert (status != inSmall); assert (status != soloKey); if (status == atUpperBound) { value += columnUpper_[j]; } else if (columnLower_) { value += columnLower_[j]; } j = next_[j]; //onto next in set } #if 0 // slack must be feasible double oldValue=value; value = CoinMax(value,lowerSet_[iSet]); value = CoinMin(value,upperSet_[iSet]); if (value!=oldValue) printf("using %g (not %g) for slack on set %d (%g,%g)\n", value,oldValue,iSet,lowerSet_[iSet],upperSet_[iSet]); #endif } } return value; } // Switches off dj checking each factorization (for BIG models) void ClpDynamicMatrix::switchOffCheck() { noCheck_ = 0; infeasibilityWeight_ = 0.0; } /* Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ void ClpDynamicMatrix::createVariable(ClpSimplex * model, int & bestSequence) { int numberRows = model->numberRows(); int slackOffset = lastDynamic_ + numberRows; int structuralOffset = slackOffset + numberSets_; int bestSequence2 = savedBestSequence_ - structuralOffset; if (bestSequence >= slackOffset) { double * columnLower = model->lowerRegion(); double * columnUpper = model->upperRegion(); double * solution = model->solutionRegion(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); if (toIndex_[savedBestSet_] < 0) { // need to put key into basis int newRow = numberActiveSets_ + numberStaticRows_; model->dualRowSolution()[newRow] = savedBestGubDual_; double valueOfKey = keyValue(savedBestSet_); // done before toIndex_ set toIndex_[savedBestSet_] = numberActiveSets_; fromIndex_[numberActiveSets_++] = savedBestSet_; int iSequence = lastDynamic_ + newRow; // we need to get lower and upper correct double shift = 0.0; int j = startSet_[savedBestSet_]; while (j >= 0) { if (getDynamicStatus(j) == atUpperBound) shift += columnUpper_[j]; else if (getDynamicStatus(j) == atLowerBound && columnLower_) shift += columnLower_[j]; j = next_[j]; //onto next in set } if (lowerSet_[savedBestSet_] > -1.0e20) columnLower[iSequence] = lowerSet_[savedBestSet_]; else columnLower[iSequence] = -COIN_DBL_MAX; if (upperSet_[savedBestSet_] < 1.0e20) columnUpper[iSequence] = upperSet_[savedBestSet_]; else columnUpper[iSequence] = COIN_DBL_MAX; #ifdef CLP_DEBUG if (model_->logLevel() == 63) { printf("%d in in set %d, key is %d rhs %g %g - keyvalue %g\n", bestSequence2, savedBestSet_, keyVariable_[savedBestSet_], columnLower[iSequence], columnUpper[iSequence], valueOfKey); int j = startSet_[savedBestSet_]; while (j >= 0) { if (getDynamicStatus(j) == atUpperBound) printf("%d atup ", j); else if (getDynamicStatus(j) == atLowerBound) printf("%d atlo ", j); else if (getDynamicStatus(j) == soloKey) printf("%d solo ", j); else abort(); j = next_[j]; //onto next in set } printf("\n"); } #endif if (keyVariable_[savedBestSet_] < maximumGubColumns_) { // slack not key model_->pivotVariable()[newRow] = firstAvailable_; backToPivotRow_[firstAvailable_] = newRow; model->setStatus(iSequence, getStatus(savedBestSet_)); model->djRegion()[iSequence] = savedBestGubDual_; solution[iSequence] = valueOfKey; // create variable and pivot in int key = keyVariable_[savedBestSet_]; setDynamicStatus(key, inSmall); double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[key+1] - startColumn_[key] + 1; if (numberElements + numberThis > numberElements_) { // need to redo numberElements_ = CoinMax(3 * numberElements_ / 2, numberElements + numberThis); matrix_->reserve(lastDynamic_, numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } // already set startColumn[firstAvailable_]=numberElements; length[firstAvailable_] = numberThis; model->costRegion()[firstAvailable_] = cost_[key]; CoinBigIndex base = startColumn_[key]; for (int j = 0; j < numberThis - 1; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } row[numberElements] = newRow; element[numberElements++] = 1.0; id_[firstAvailable_-firstDynamic_] = key; model->setObjectiveOffset(model->objectiveOffset() + cost_[key]* valueOfKey); model->solutionRegion()[firstAvailable_] = valueOfKey; model->setStatus(firstAvailable_, ClpSimplex::basic); // ***** need to adjust effective rhs if (!columnLower_ && !columnUpper_) { columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { if (columnLower_) columnLower[firstAvailable_] = columnLower_[key]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[key]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; } model->nonLinearCost()->setOne(firstAvailable_, solution[firstAvailable_], columnLower[firstAvailable_], columnUpper[firstAvailable_], cost_[key]); startColumn[firstAvailable_+1] = numberElements; reducedCost[firstAvailable_] = 0.0; modifyOffset(key, valueOfKey); rhsOffset_[newRow] = -shift; // sign? #ifdef CLP_DEBUG model->rowArray(1)->checkClear(); #endif // now pivot in unpack(model, model->rowArray(1), firstAvailable_); model->factorization()->updateColumnFT(model->rowArray(2), model->rowArray(1)); double alpha = model->rowArray(1)->denseVector()[newRow]; int updateStatus = model->factorization()->replaceColumn(model, model->rowArray(2), model->rowArray(1), newRow, alpha); model->rowArray(1)->clear(); if (updateStatus) { if (updateStatus == 3) { // out of memory // increase space if not many iterations if (model->factorization()->pivots() < 0.5 * model->factorization()->maximumPivots() && model->factorization()->pivots() < 400) model->factorization()->areaFactor( model->factorization()->areaFactor() * 1.1); } else { printf("Bad returncode %d from replaceColumn\n", updateStatus); } bestSequence = -1; return; } // firstAvailable_ only finally updated if good pivot (in updatePivot) // otherwise it reverts to firstAvailableBefore_ firstAvailable_++; } else { // slack key model->setStatus(iSequence, ClpSimplex::basic); model->djRegion()[iSequence] = 0.0; solution[iSequence] = valueOfKey+shift; rhsOffset_[newRow] = -shift; // sign? } // correct slack model->costRegion()[iSequence] = 0.0; model->nonLinearCost()->setOne(iSequence, solution[iSequence], columnLower[iSequence], columnUpper[iSequence], 0.0); } if (savedBestSequence_ >= structuralOffset) { // recompute dj and create double value = cost_[bestSequence2] - savedBestGubDual_; for (CoinBigIndex jBigIndex = startColumn_[bestSequence2]; jBigIndex < startColumn_[bestSequence2+1]; jBigIndex++) { int jRow = row_[jBigIndex]; value -= duals[jRow] * element_[jBigIndex]; } int gubRow = toIndex_[savedBestSet_] + numberStaticRows_; double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); CoinBigIndex numberElements = startColumn[firstAvailable_]; int numberThis = startColumn_[bestSequence2+1] - startColumn_[bestSequence2] + 1; if (numberElements + numberThis > numberElements_) { // need to redo numberElements_ = CoinMax(3 * numberElements_ / 2, numberElements + numberThis); matrix_->reserve(lastDynamic_, numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } // already set startColumn[firstAvailable_]=numberElements; length[firstAvailable_] = numberThis; model->costRegion()[firstAvailable_] = cost_[bestSequence2]; CoinBigIndex base = startColumn_[bestSequence2]; for (int j = 0; j < numberThis - 1; j++) { row[numberElements] = row_[base+j]; element[numberElements++] = element_[base+j]; } row[numberElements] = gubRow; element[numberElements++] = 1.0; id_[firstAvailable_-firstDynamic_] = bestSequence2; //printf("best %d\n",bestSequence2); model->solutionRegion()[firstAvailable_] = 0.0; model->clearFlagged(firstAvailable_); if (!columnLower_ && !columnUpper_) { model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { DynamicStatus status = getDynamicStatus(bestSequence2); if (columnLower_) columnLower[firstAvailable_] = columnLower_[bestSequence2]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[bestSequence2]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; if (status == atLowerBound) { solution[firstAvailable_] = columnLower[firstAvailable_]; model->setStatus(firstAvailable_, ClpSimplex::atLowerBound); } else { solution[firstAvailable_] = columnUpper[firstAvailable_]; model->setStatus(firstAvailable_, ClpSimplex::atUpperBound); } } model->setObjectiveOffset(model->objectiveOffset() + cost_[bestSequence2]* solution[firstAvailable_]); model->nonLinearCost()->setOne(firstAvailable_, solution[firstAvailable_], columnLower[firstAvailable_], columnUpper[firstAvailable_], cost_[bestSequence2]); bestSequence = firstAvailable_; // firstAvailable_ only updated if good pivot (in updatePivot) startColumn[firstAvailable_+1] = numberElements; //printf("price struct %d - dj %g gubpi %g\n",bestSequence,value,savedBestGubDual_); reducedCost[bestSequence] = value; } else { // slack - row must just have been created assert (toIndex_[savedBestSet_] == numberActiveSets_ - 1); int newRow = numberStaticRows_ + numberActiveSets_ - 1; bestSequence = lastDynamic_ + newRow; reducedCost[bestSequence] = savedBestGubDual_; } } // clear for next iteration savedBestSequence_ = -1; } // Returns reduced cost of a variable double ClpDynamicMatrix::reducedCost(ClpSimplex * model, int sequence) const { int numberRows = model->numberRows(); int slackOffset = lastDynamic_ + numberRows; if (sequence < slackOffset) return model->djRegion()[sequence]; else return savedBestDj_; } // Does gub crash void ClpDynamicMatrix::gubCrash() { // Do basis - cheapest or slack if feasible int longestSet = 0; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) { int n = 0; int j = startSet_[iSet]; while (j >= 0) { n++; j = next_[j]; } longestSet = CoinMax(longestSet, n); } double * upper = new double[longestSet+1]; double * cost = new double[longestSet+1]; double * lower = new double[longestSet+1]; double * solution = new double[longestSet+1]; int * back = new int[longestSet+1]; double tolerance = model_->primalTolerance(); double objectiveOffset = 0.0; for (iSet = 0; iSet < numberSets_; iSet++) { int iBasic = -1; double value = 0.0; // find cheapest int numberInSet = 0; int j = startSet_[iSet]; while (j >= 0) { if (!columnLower_) lower[numberInSet] = 0.0; else lower[numberInSet] = columnLower_[j]; if (!columnUpper_) upper[numberInSet] = COIN_DBL_MAX; else upper[numberInSet] = columnUpper_[j]; back[numberInSet++] = j; j = next_[j]; } CoinFillN(solution, numberInSet, 0.0); // and slack iBasic = numberInSet; solution[iBasic] = -value; lower[iBasic] = -upperSet_[iSet]; upper[iBasic] = -lowerSet_[iSet]; int kphase; if (value < lowerSet_[iSet] - tolerance || value > upperSet_[iSet] + tolerance) { // infeasible kphase = 0; // remember bounds are flipped so opposite to natural if (value < lowerSet_[iSet] - tolerance) cost[iBasic] = 1.0; else cost[iBasic] = -1.0; CoinZeroN(cost, numberInSet); double dualTolerance = model_->dualTolerance(); for (int iphase = kphase; iphase < 2; iphase++) { if (iphase) { cost[numberInSet] = 0.0; for (int j = 0; j < numberInSet; j++) cost[j] = cost_[back[j]]; } // now do one row lp bool improve = true; while (improve) { improve = false; double dual = cost[iBasic]; int chosen = -1; double best = dualTolerance; int way = 0; for (int i = 0; i <= numberInSet; i++) { double dj = cost[i] - dual; double improvement = 0.0; if (iphase || i < numberInSet) assert (solution[i] >= lower[i] && solution[i] <= upper[i]); if (dj > dualTolerance) improvement = dj * (solution[i] - lower[i]); else if (dj < -dualTolerance) improvement = dj * (solution[i] - upper[i]); if (improvement > best) { best = improvement; chosen = i; if (dj < 0.0) { way = 1; } else { way = -1; } } } if (chosen >= 0) { improve = true; // now see how far if (way > 0) { // incoming increasing so basic decreasing // if phase 0 then go to nearest bound double distance = upper[chosen] - solution[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] > upper[iBasic]); basicDistance = solution[iBasic] - upper[iBasic]; } else { basicDistance = solution[iBasic] - lower[iBasic]; } // need extra coding for unbounded assert (CoinMin(distance, basicDistance) < 1.0e20); if (distance > basicDistance) { // incoming becomes basic solution[chosen] += basicDistance; if (!iphase) solution[iBasic] = upper[iBasic]; else solution[iBasic] = lower[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = upper[chosen]; solution[iBasic] -= distance; } } else { // incoming decreasing so basic increasing // if phase 0 then go to nearest bound double distance = solution[chosen] - lower[chosen]; double basicDistance; if (!iphase) { assert (iBasic == numberInSet); assert (solution[iBasic] < lower[iBasic]); basicDistance = lower[iBasic] - solution[iBasic]; } else { basicDistance = upper[iBasic] - solution[iBasic]; } // need extra coding for unbounded - for now just exit if (CoinMin(distance, basicDistance) > 1.0e20) { printf("unbounded on set %d\n", iSet); iphase = 1; iBasic = numberInSet; break; } if (distance > basicDistance) { // incoming becomes basic solution[chosen] -= basicDistance; if (!iphase) solution[iBasic] = lower[iBasic]; else solution[iBasic] = upper[iBasic]; iBasic = chosen; } else { // flip solution[chosen] = lower[chosen]; solution[iBasic] += distance; } } if (!iphase) { if(iBasic < numberInSet) break; // feasible else if (solution[iBasic] >= lower[iBasic] && solution[iBasic] <= upper[iBasic]) break; // feasible (on flip) } } } } } // do solution i.e. bounds if (columnLower_ || columnUpper_) { for (int j = 0; j < numberInSet; j++) { if (j != iBasic) { objectiveOffset += solution[j] * cost[j]; if (columnLower_ && columnUpper_) { if (fabs(solution[j] - columnLower_[back[j]]) > fabs(solution[j] - columnUpper_[back[j]])) setDynamicStatus(back[j], atUpperBound); } else if (columnUpper_ && solution[j] > 0.0) { setDynamicStatus(back[j], atUpperBound); } else { setDynamicStatus(back[j], atLowerBound); assert(!solution[j]); } } } } // convert iBasic back and do bounds if (iBasic == numberInSet) { // slack basic setStatus(iSet, ClpSimplex::basic); iBasic = iSet + maximumGubColumns_; } else { iBasic = back[iBasic]; setDynamicStatus(iBasic, soloKey); // remember bounds flipped if (upper[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::isFixed); else if (solution[numberInSet] == upper[numberInSet]) setStatus(iSet, ClpSimplex::atLowerBound); else if (solution[numberInSet] == lower[numberInSet]) setStatus(iSet, ClpSimplex::atUpperBound); else abort(); } keyVariable_[iSet] = iBasic; } model_->setObjectiveOffset(objectiveOffset_ - objectiveOffset); delete [] lower; delete [] solution; delete [] upper; delete [] cost; delete [] back; // make sure matrix is in good shape matrix_->orderMatrix(); } // Populates initial matrix from dynamic status void ClpDynamicMatrix::initialProblem() { int iSet; double * element = matrix_->getMutableElements(); int * row = matrix_->getMutableIndices(); CoinBigIndex * startColumn = matrix_->getMutableVectorStarts(); int * length = matrix_->getMutableVectorLengths(); double * cost = model_->objective(); double * solution = model_->primalColumnSolution(); double * columnLower = model_->columnLower(); double * columnUpper = model_->columnUpper(); double * rowSolution = model_->primalRowSolution(); double * rowLower = model_->rowLower(); double * rowUpper = model_->rowUpper(); CoinBigIndex numberElements = startColumn[firstDynamic_]; firstAvailable_ = firstDynamic_; numberActiveSets_ = 0; for (iSet = 0; iSet < numberSets_; iSet++) { toIndex_[iSet] = -1; int numberActive = 0; int whichKey = -1; if (getStatus(iSet) == ClpSimplex::basic) { whichKey = maximumGubColumns_ + iSet; numberActive = 1; } else { whichKey = -1; } int j = startSet_[iSet]; while (j >= 0) { assert (getDynamicStatus(j) != soloKey || whichKey == -1); if (getDynamicStatus(j) == inSmall) { numberActive++; } else if (getDynamicStatus(j) == soloKey) { whichKey = j; numberActive++; } j = next_[j]; //onto next in set } if (numberActive > 1) { int iRow = numberActiveSets_ + numberStaticRows_; rowSolution[iRow] = 0.0; double lowerValue; if (lowerSet_[iSet] > -1.0e20) lowerValue = lowerSet_[iSet]; else lowerValue = -COIN_DBL_MAX; double upperValue; if (upperSet_[iSet] < 1.0e20) upperValue = upperSet_[iSet]; else upperValue = COIN_DBL_MAX; rowLower[iRow] = lowerValue; rowUpper[iRow] = upperValue; if (getStatus(iSet) == ClpSimplex::basic) { model_->setRowStatus(iRow, ClpSimplex::basic); rowSolution[iRow] = 0.0; } else if (getStatus(iSet) == ClpSimplex::atLowerBound) { model_->setRowStatus(iRow, ClpSimplex::atLowerBound); rowSolution[iRow] = lowerValue; } else { model_->setRowStatus(iRow, ClpSimplex::atUpperBound); rowSolution[iRow] = upperValue; } j = startSet_[iSet]; while (j >= 0) { DynamicStatus status = getDynamicStatus(j); if (status == inSmall) { int numberThis = startColumn_[j+1] - startColumn_[j] + 1; if (numberElements + numberThis > numberElements_) { // need to redo numberElements_ = CoinMax(3 * numberElements_ / 2, numberElements + numberThis); matrix_->reserve(lastDynamic_, numberElements_); element = matrix_->getMutableElements(); row = matrix_->getMutableIndices(); // these probably okay but be safe startColumn = matrix_->getMutableVectorStarts(); length = matrix_->getMutableVectorLengths(); } length[firstAvailable_] = numberThis; cost[firstAvailable_] = cost_[j]; CoinBigIndex base = startColumn_[j]; for (int k = 0; k < numberThis - 1; k++) { row[numberElements] = row_[base+k]; element[numberElements++] = element_[base+k]; } row[numberElements] = iRow; element[numberElements++] = 1.0; id_[firstAvailable_-firstDynamic_] = j; solution[firstAvailable_] = 0.0; model_->setStatus(firstAvailable_, ClpSimplex::basic); if (!columnLower_ && !columnUpper_) { columnLower[firstAvailable_] = 0.0; columnUpper[firstAvailable_] = COIN_DBL_MAX; } else { if (columnLower_) columnLower[firstAvailable_] = columnLower_[j]; else columnLower[firstAvailable_] = 0.0; if (columnUpper_) columnUpper[firstAvailable_] = columnUpper_[j]; else columnUpper[firstAvailable_] = COIN_DBL_MAX; if (status != atUpperBound) { solution[firstAvailable_] = columnLower[firstAvailable_]; } else { solution[firstAvailable_] = columnUpper[firstAvailable_]; } } firstAvailable_++; startColumn[firstAvailable_] = numberElements; } j = next_[j]; //onto next in set } model_->setRowStatus(numberActiveSets_ + numberStaticRows_, getStatus(iSet)); toIndex_[iSet] = numberActiveSets_; fromIndex_[numberActiveSets_++] = iSet; } else { // solo key bool needKey=false; if (numberActive) { if (whichKeyupperSet_[iSet]+1.0e-8) needKey=true; } } else { needKey = true; } if (needKey) { // all to lb then up some (slack/null if possible) int length=99999999; int which=-1; double sum=0.0; for (int iColumn=startSet_[iSet];iColumnstartColumn_[iColumn+1]-startColumn_[iColumn]) { which=iColumn; length=startColumn_[iColumn+1]-startColumn_[iColumn]; } } if (sum>lowerSet_[iSet]-1.0e-8) { // slack can be basic setStatus(iSet,ClpSimplex::basic); keyVariable_[iSet] = maximumGubColumns_ + iSet; } else { // use shortest setDynamicStatus(which,soloKey); keyVariable_[iSet] = which; setStatus(iSet,ClpSimplex::atLowerBound); } } } assert (toIndex_[iSet] >= 0 || whichKey >= 0); keyVariable_[iSet] = whichKey; } // clean up pivotVariable int numberColumns = model_->numberColumns(); int numberRows = model_->numberRows(); int * pivotVariable = model_->pivotVariable(); if (pivotVariable) { for (int i=0; igetRowStatus(i)!=ClpSimplex::basic) pivotVariable[i]=-1; else pivotVariable[i]=numberColumns+i; } for (int i=numberStaticRows_+numberActiveSets_;igetColumnStatus(i)==ClpSimplex::basic) { while(putcostRegion(); double * columnLower = model_->lowerRegion(); double * columnUpper = model_->upperRegion(); double * solution = model_->solutionRegion(); int numberRows = model_->numberRows(); for (int i = numberActiveSets_; i < numberRows-numberStaticRows_; i++) { int iSequence = i + numberStaticRows_ + numberColumns; solution[iSequence] = 0.0; columnLower[iSequence] = -COIN_DBL_MAX; columnUpper[iSequence] = COIN_DBL_MAX; cost[iSequence] = 0.0; model_->nonLinearCost()->setOne(iSequence, solution[iSequence], columnLower[iSequence], columnUpper[iSequence], 0.0); model_->setStatus(iSequence, ClpSimplex::basic); rhsOffset_[i+numberStaticRows_] = 0.0; } #if 0 for (int i=0;icolumnLower(); const double * columnUpperA = model_->columnUpper(); const double * costA = model_->objective(); const double * rowLowerA = model_->rowLower(); const double * rowUpperA = model_->rowUpper(); start[0]=0; numberElements=0; for (int i=0;i= 0) { if (startColumn_[j+1] - startColumn_[j] == numberEntries) { const int * row2 = row_ + startColumn_[j]; const double * element2 = element_ + startColumn_[j]; bool same = true; for (int k = 0; k < numberEntries; k++) { if (row[k] != row2[k] || element[k] != element2[k]) { same = false; break; } } if (same) { bool odd = false; if (cost != cost_[j]) odd = true; if (columnLower_ && lower != columnLower_[j]) odd = true; if (columnUpper_ && upper != columnUpper_[j]) odd = true; if (odd) { printf("seems odd - same els but cost,lo,up are %g,%g,%g and %g,%g,%g\n", cost, lower, upper, cost_[j], columnLower_ ? columnLower_[j] : 0.0, columnUpper_ ? columnUpper_[j] : 1.0e100); } else { setDynamicStatus(j, status); return j; } } } j = next_[j]; } if (numberGubColumns_ == maximumGubColumns_ || startColumn_[numberGubColumns_] + numberEntries > maximumElements_) { CoinBigIndex j; int i; int put = 0; int numberElements = 0; CoinBigIndex start = 0; // compress - leave ones at ub and basic int * which = new int [numberGubColumns_]; for (i = 0; i < numberGubColumns_; i++) { CoinBigIndex end = startColumn_[i+1]; // what about ubs if column generation? if (getDynamicStatus(i) != atLowerBound) { // keep in for (j = start; j < end; j++) { row_[numberElements] = row_[j]; element_[numberElements++] = element_[j]; } startColumn_[put+1] = numberElements; cost_[put] = cost_[i]; if (columnLower_) columnLower_[put] = columnLower_[i]; if (columnUpper_) columnUpper_[put] = columnUpper_[i]; dynamicStatus_[put] = dynamicStatus_[i]; id_[put] = id_[i]; which[i] = put; put++; } else { // out which[i] = -1; } start = end; } // now redo startSet_ and next_ int * newNext = new int [maximumGubColumns_]; for (int jSet = 0; jSet < numberSets_; jSet++) { int sequence = startSet_[jSet]; while (which[sequence] < 0) { // out assert (next_[sequence] >= 0); sequence = next_[sequence]; } startSet_[jSet] = which[sequence]; int last = which[sequence]; while (next_[sequence] >= 0) { sequence = next_[sequence]; if(which[sequence] >= 0) { // keep newNext[last] = which[sequence]; last = which[sequence]; } } newNext[last] = -jSet - 1; } delete [] next_; next_ = newNext; delete [] which; abort(); } CoinBigIndex start = startColumn_[numberGubColumns_]; CoinMemcpyN(row, numberEntries, row_ + start); CoinMemcpyN(element, numberEntries, element_ + start); startColumn_[numberGubColumns_+1] = start + numberEntries; cost_[numberGubColumns_] = cost; if (columnLower_) columnLower_[numberGubColumns_] = lower; else assert (!lower); if (columnUpper_) columnUpper_[numberGubColumns_] = upper; else assert (upper > 1.0e20); setDynamicStatus(numberGubColumns_, status); // Do next_ j = startSet_[iSet]; startSet_[iSet] = numberGubColumns_; next_[numberGubColumns_] = j; numberGubColumns_++; return numberGubColumns_ - 1; } // Returns which set a variable is in int ClpDynamicMatrix::whichSet (int sequence) const { while (next_[sequence] >= 0) sequence = next_[sequence]; int iSet = - next_[sequence] - 1; return iSet; } Clp-1.15.10/src/ClpDynamicExampleMatrix.hpp0000644000076600007660000001550112131314313017071 0ustar coincoin/* $Id: ClpDynamicExampleMatrix.hpp 1941 2013-04-10 16:52:27Z 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 ClpDynamicExampleMatrix_H #define ClpDynamicExampleMatrix_H #include "CoinPragma.hpp" #include "ClpDynamicMatrix.hpp" class ClpSimplex; /** This implements a dynamic matrix when we have a limit on the number of "interesting rows". This version inherits from ClpDynamicMatrix and knows that the real matrix is gub. This acts just like ClpDynamicMatrix but generates columns. This "generates" columns by choosing from stored set. It is maent as a starting point as to how you could use shortest path to generate columns. So it has its own copy of all data needed. It populates ClpDynamicWatrix with enough to allow for gub keys and active variables. In turn ClpDynamicMatrix populates a CoinPackedMatrix with active columns and rows. As there is one copy here and one in ClpDynamicmatrix these names end in Gen_ It is obviously more efficient to just use ClpDynamicMatrix but the ideas is to show how much code a user would have to write. This does not work very well with bounds */ class ClpDynamicExampleMatrix : public ClpDynamicMatrix { public: /**@name Main functions provided */ //@{ /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); /** Creates a variable. This is called after partial pricing and will modify matrix. Will update bestSequence. */ virtual void createVariable(ClpSimplex * model, int & bestSequence); /** If addColumn forces compression then this allows descendant to know what to do. If >= then entry stayed in, if -1 then entry went out to lower bound.of zero. Entries at upper bound (really nonzero) never go out (at present). */ virtual void packDown(const int * in, int numberToPack); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpDynamicExampleMatrix(); /** This is the real constructor. It assumes factorization frequency will not be changed. This resizes model !!!! The contents of original matrix in model will be taken over and original matrix will be sanitized so can be deleted (to avoid a very small memory leak) */ ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, int numberColumns, const int * starts, const double * lower, const double * upper, const int * startColumn, const int * row, const double * element, const double * cost, const double * columnLower = NULL, const double * columnUpper = NULL, const unsigned char * status = NULL, const unsigned char * dynamicStatus = NULL, int numberIds = 0, const int *ids = NULL); #if 0 /// This constructor just takes over ownership (except for lower, upper) ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, int numberColumns, int * starts, const double * lower, const double * upper, int * startColumn, int * row, double * element, double * cost, double * columnLower = NULL, double * columnUpper = NULL, const unsigned char * status = NULL, const unsigned char * dynamicStatus = NULL, int numberIds = 0, const int *ids = NULL); #endif /** Destructor */ virtual ~ClpDynamicExampleMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpDynamicExampleMatrix(const ClpDynamicExampleMatrix&); ClpDynamicExampleMatrix& operator=(const ClpDynamicExampleMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; //@} /**@name gets and sets */ //@{ /// Starts of each column inline CoinBigIndex * startColumnGen() const { return startColumnGen_; } /// rows inline int * rowGen() const { return rowGen_; } /// elements inline double * elementGen() const { return elementGen_; } /// costs inline double * costGen() const { return costGen_; } /// full starts inline int * fullStartGen() const { return fullStartGen_; } /// ids in next level matrix inline int * idGen() const { return idGen_; } /// Optional lower bounds on columns inline double * columnLowerGen() const { return columnLowerGen_; } /// Optional upper bounds on columns inline double * columnUpperGen() const { return columnUpperGen_; } /// size inline int numberColumns() const { return numberColumns_; } inline void setDynamicStatusGen(int sequence, DynamicStatus status) { unsigned char & st_byte = dynamicStatusGen_[sequence]; st_byte = static_cast(st_byte & ~7); st_byte = static_cast(st_byte | status); } inline DynamicStatus getDynamicStatusGen(int sequence) const { return static_cast (dynamicStatusGen_[sequence] & 7); } /// Whether flagged inline bool flaggedGen(int i) const { return (dynamicStatusGen_[i] & 8) != 0; } inline void setFlaggedGen(int i) { dynamicStatusGen_[i] = static_cast(dynamicStatusGen_[i] | 8); } inline void unsetFlagged(int i) { dynamicStatusGen_[i] = static_cast(dynamicStatusGen_[i] & ~8); } //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// size int numberColumns_; /// Starts of each column CoinBigIndex * startColumnGen_; /// rows int * rowGen_; /// elements double * elementGen_; /// costs double * costGen_; /// start of each set int * fullStartGen_; /// for status and which bound unsigned char * dynamicStatusGen_; /** identifier for each variable up one level (startColumn_, etc). This is of length maximumGubColumns_. For this version it is just sequence number at this level */ int * idGen_; /// Optional lower bounds on columns double * columnLowerGen_; /// Optional upper bounds on columns double * columnUpperGen_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyMumps.cpp0000644000076600007660000004033612130104455015611 0ustar coincoin/* $Id: ClpCholeskyMumps.cpp 1931 2013-04-06 20:44:29Z 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 "CoinPragma.hpp" #include "ClpConfig.h" #define MPI_COMM_WORLD CLP_MPI_COMM_WORLD #define JOB_INIT -1 #define JOB_END -2 #define USE_COMM_WORLD -987654 extern "C" { #include "dmumps_c.h" #include "mpi.h" } #include "ClpCholeskyMumps.hpp" #include "ClpMessage.hpp" #include "ClpInterior.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyMumps::ClpCholeskyMumps (int denseThreshold) : ClpCholeskyBase(denseThreshold) { mumps_ = (DMUMPS_STRUC_C*)malloc(sizeof(DMUMPS_STRUC_C)); type_ = 16; mumps_->n = 0; mumps_->nz = 0; mumps_->a = NULL; mumps_->jcn = NULL; mumps_->irn = NULL; mumps_->job = JOB_INIT;//initialize mumps mumps_->par = 1;//working host for sequential version mumps_->sym = 2;//general symmetric matrix mumps_->comm_fortran = USE_COMM_WORLD; int myid; int justName; MPI_Init(&justName, NULL); #ifndef NDEBUG int ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid); assert (!ierr); #else MPI_Comm_rank(MPI_COMM_WORLD, &myid); #endif dmumps_c(mumps_); #define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */ #define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */ mumps_->ICNTL(5) = 1; // say compressed format mumps_->ICNTL(4) = 2; // log messages mumps_->ICNTL(24) = 1; // Deal with zeros on diagonal mumps_->CNTL(3) = 1.0e-20; // drop if diagonal less than this // output off mumps_->ICNTL(1) = -1; mumps_->ICNTL(2) = -1; mumps_->ICNTL(3) = -1; mumps_->ICNTL(4) = 0; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyMumps::ClpCholeskyMumps (const ClpCholeskyMumps & rhs) : ClpCholeskyBase(rhs) { abort(); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyMumps::~ClpCholeskyMumps () { mumps_->job = JOB_END; dmumps_c(mumps_); /* Terminate instance */ MPI_Finalize(); free(mumps_); } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyMumps & ClpCholeskyMumps::operator=(const ClpCholeskyMumps& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); abort(); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyMumps::clone() const { return new ClpCholeskyMumps(*this); } /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyMumps::order(ClpInterior * model) { numberRows_ = model->numberRows(); if (doKKT_) { numberRows_ += numberRows_ + model->numberColumns(); printf("finish coding MUMPS KKT!\n"); abort(); } rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // NOT COMPRESSED FOR NOW ??? - Space for starts mumps_->ICNTL(5) = 0; // say NOT compressed format try { choleskyStart_ = new CoinBigIndex[numberRows_+1+sizeFactor_]; } catch (...) { // no memory return -1; } // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; // To Fortran and fake for (iRow = 0; iRow < numberRows_ + 1; iRow++) { int k = choleskyStart_[iRow]; int kEnd = choleskyStart_[iRow+1]; k += numberRows_ + 1; kEnd += numberRows_ + 1; for (; k < kEnd; k++) choleskyStart_[k] = iRow + 1; choleskyStart_[iRow]++; } mumps_->nz = sizeFactor_; mumps_->irn = choleskyStart_ + numberRows_ + 1; mumps_->jcn = choleskyRow_; mumps_->a = NULL; for (CoinBigIndex i = 0; i < sizeFactor_; i++) { choleskyRow_[i]++; #ifndef NDEBUG assert (mumps_->irn[i] >= 1 && mumps_->irn[i] <= numberRows_); assert (mumps_->jcn[i] >= 1 && mumps_->jcn[i] <= numberRows_); #endif } // validate //mumps code here mumps_->n = numberRows_; mumps_->nelt = numberRows_; mumps_->eltptr = choleskyStart_; mumps_->eltvar = choleskyRow_; mumps_->a_elt = NULL; mumps_->rhs = NULL; mumps_->job = 1; // order dmumps_c(mumps_); mumps_->a = sparseFactor_; if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS ordering failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); return 1; } else { double size = mumps_->infog[19]; if (size < 0) size *= -1000000; COIN_DETAIL_PRINT(printf("%g nonzeros, flop count %g\n", size, mumps_->rinfog[0])); } for (iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } return 0; } /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyMumps::symbolic() { return 0; } /* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyMumps::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; //double smallest; //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = 0.0; perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = sqrt(perturbation);; perturbation = 1.0; } double delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactor_ + choleskyStart_[iRow] - 1; // Fortran int * which = choleskyRow_ + choleskyStart_[iRow] - 1; // Fortran int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } } int j; for (j = 0; j < number; j++) { int jRow = which[j] - 1; // to Fortran put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_); largest2 *= 1.0e-20; int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStart_[iRow] - 1; // to Fortran double diagonal = sparseFactor_[start]; if (diagonal > largest2) { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); } else { sparseFactor_[start] = CoinMax(diagonal, 1.0e-10); rowsDropped[iRow] = 2; numberDroppedBefore++; } } } delete [] work; // code here mumps_->a_elt = sparseFactor_; mumps_->rhs = NULL; mumps_->job = 2; // factorize dmumps_c(mumps_); if (mumps_->infog[0]) { COIN_DETAIL_PRINT(printf("MUMPS factorization failed -error %d %d\n", mumps_->infog[0], mumps_->infog[1])); } choleskyCondition_ = 1.0; bool cleanCholesky; if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier //int oldDropped=numberRowsDropped_; if (newDropped || numberRowsDropped_) { //std::cout <<"Rank "<oldDropped) //std::cout<<" ( "<rhs = region; mumps_->job = 3; // solve dmumps_c(mumps_); } Clp-1.15.10/src/AbcWarmStart.hpp0000644000076600007660000001567612101105055014712 0ustar coincoin/* $Id: AbcWarmStart.hpp 1910 2013-01-27 02:00:13Z stefan $ */ /*! \legal Copyright (C) 2002, International Business Machines Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. This code is licensed under the terms of the Eclipse Public License (EPL). */ #ifndef AbcWarmStart_H #define AbcWarmStart_H #include "AbcCommon.hpp" #include "CoinWarmStartBasis.hpp" // could test using ClpSimplex (or for fans) #define CLP_WARMSTART #ifdef CLP_WARMSTART #include "ClpSimplex.hpp" #define AbcSimplex ClpSimplex #else #include "AbcSimplex.hpp" #endif class AbcWarmStart; //############################################################################# class AbcWarmStartOrganizer { public: /// Create Basis type 0 void createBasis0(); /// Create Basis type 1,2 void createBasis12(); /// Create Basis type 3,4 void createBasis34(); /// delete basis void deleteBasis(AbcWarmStart * basis); /*! \name Constructors, destructors, and related functions */ //@{ /** Default constructor Creates a warm start object organizer */ AbcWarmStartOrganizer(AbcSimplex * model=NULL); /** Copy constructor */ AbcWarmStartOrganizer(const AbcWarmStartOrganizer& ws) ; /** Destructor */ virtual ~AbcWarmStartOrganizer(); /** Assignment */ virtual AbcWarmStartOrganizer& operator=(const AbcWarmStartOrganizer& rhs) ; //@} protected: /** \name Protected data members */ //@{ /// Pointer to AbcSimplex (can only be applied to that) AbcSimplex * model_; /// Pointer to first basis AbcWarmStart * firstBasis_; /// Pointer to last basis AbcWarmStart * lastBasis_; /// Number of bases int numberBases_; /// Size of bases (extra) int sizeBases_; //@} }; /*! \class AbcWarmStart As CoinWarmStartBasis but with alternatives (Also uses Clp status meaning for slacks) */ class AbcWarmStart : public virtual CoinWarmStartBasis { public: /*! \name Methods to modify the warm start object */ //@{ /*! \brief Set basis capacity; existing basis is discarded. After execution of this routine, the warm start object does not describe a valid basis: all structural and artificial variables have status isFree. */ virtual void setSize(int ns, int na) ; /*! \brief Set basis capacity; existing basis is maintained. After execution of this routine, the warm start object describes a valid basis: the status of new structural variables (added columns) is set to nonbasic at lower bound, and the status of new artificial variables (added rows) is set to basic. (The basis can be invalid if new structural variables do not have a finite lower bound.) */ virtual void resize (int newNumberRows, int newNumberColumns); /** \brief Delete a set of rows from the basis \warning This routine assumes that the set of indices to be deleted is sorted in ascending order and contains no duplicates. Use deleteRows() if this is not the case. \warning The resulting basis is guaranteed valid only if all deleted constraints are slack (hence the associated logicals are basic). Removal of a tight constraint with a nonbasic logical implies that some basic variable must be made nonbasic. This correction is left to the client. */ virtual void compressRows (int tgtCnt, const int *tgts) ; /** \brief Delete a set of rows from the basis \warning The resulting basis is guaranteed valid only if all deleted constraints are slack (hence the associated logicals are basic). Removal of a tight constraint with a nonbasic logical implies that some basic variable must be made nonbasic. This correction is left to the client. */ virtual void deleteRows(int rawTgtCnt, const int *rawTgts) ; /** \brief Delete a set of columns from the basis \warning The resulting basis is guaranteed valid only if all deleted variables are nonbasic. Removal of a basic variable implies that some nonbasic variable must be made basic. This correction is left to the client. */ virtual void deleteColumns(int number, const int * which); /// Set model inline void setModel(AbcSimplex * model) { model_=model;} /// Get model inline AbcSimplex * model() const { return model_;} /// Create Basis type 0 void createBasis0(const AbcSimplex * model); /// Create Basis type 12 void createBasis12(const AbcSimplex * model); /// Create Basis type 34 void createBasis34(const AbcSimplex * model); /*! \name Constructors, destructors, and related functions */ //@{ /** Default constructor Creates a warm start object representing an empty basis (0 rows, 0 columns). */ AbcWarmStart(); /** Constructs a warm start object with the specified status vectors. The parameters are copied. Consider assignBasisStatus(int,int,char*&,char*&) if the object should assume ownership. \sa AbcWarmStart::Status for a description of the packing used in the status arrays. */ AbcWarmStart(AbcSimplex * model,int type) ; /** Copy constructor */ AbcWarmStart(const AbcWarmStart& ws) ; /** `Virtual constructor' */ virtual CoinWarmStart *clone() const { return new AbcWarmStart(*this); } /** Destructor */ virtual ~AbcWarmStart(); /** Assignment */ virtual AbcWarmStart& operator=(const AbcWarmStart& rhs) ; /** Assign the status vectors to be the warm start information. In this method the AbcWarmStart object assumes ownership of the pointers and upon return the argument pointers will be NULL. If copying is desirable, use the \link AbcWarmStart(int,int,const char*,const char*) array constructor \endlink or the \link operator=(const AbcWarmStart&) assignment operator \endlink. \note The pointers passed to this method will be freed using delete[], so they must be created using new[]. */ virtual void assignBasisStatus(int ns, int na, char*& sStat, char*& aStat) ; //@} protected: /** \name Protected data members */ //@{ /** Type of basis (always status arrays) 0 - as CoinWarmStartBasis 1,2 - plus factor order as shorts or ints (top bit set means column) 3,4 - plus compact saved factorization add 8 to say steepest edge weights stored (as floats) may want to change next,previous to tree info so can use a different basis for weights */ int typeExtraInformation_; /// Length of extra information in bytes int lengthExtraInformation_; /// The extra information. char * extraInformation_; /// Pointer back to AbcSimplex (can only be applied to that) AbcSimplex * model_; /// Pointer back to AbcWarmStartOrganizer for organization AbcWarmStartOrganizer * organizer_; /// Pointer to previous basis AbcWarmStart * previousBasis_; /// Pointer to next basis AbcWarmStart * nextBasis_; /// Sequence stamp for deletion int stamp_; /** Number of valid rows (rest should have slacks) Check to see if weights are OK for these rows and then just btran new ones for weights */ int numberValidRows_; //@} }; #endif Clp-1.15.10/src/ClpInterior.cpp0000644000076600007660000012673712131314313014610 0ustar coincoin/* $Id: ClpInterior.cpp 1941 2013-04-10 16:52:27Z 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 "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpMatrixBase.hpp" #include "ClpLsqr.hpp" #include "ClpPdcoBase.hpp" #include "CoinDenseVector.hpp" #include "ClpMessage.hpp" #include "ClpHelperFunctions.hpp" #include "ClpCholeskyDense.hpp" #include "ClpLinearObjective.hpp" #include "ClpQuadraticObjective.hpp" #include #include #include #include //############################################################################# ClpInterior::ClpInterior () : ClpModel(), largestPrimalError_(0.0), largestDualError_(0.0), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), worstComplementarity_(0.0), xsize_(0.0), zsize_(0.0), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rhs_(NULL), x_(NULL), y_(NULL), dj_(NULL), lsqrObject_(NULL), pdcoStuff_(NULL), mu_(0.0), objectiveNorm_(1.0e-12), rhsNorm_(1.0e-12), solutionNorm_(1.0e-12), dualObjective_(0.0), primalObjective_(0.0), diagonalNorm_(1.0e-12), stepLength_(0.995), linearPerturbation_(1.0e-12), diagonalPerturbation_(1.0e-15), gamma_(0.0), delta_(0), targetGap_(1.0e-12), projectionTolerance_(1.0e-7), maximumRHSError_(0.0), maximumBoundInfeasibility_(0.0), maximumDualError_(0.0), diagonalScaleFactor_(0.0), scaleFactor_(1.0), actualPrimalStep_(0.0), actualDualStep_(0.0), smallestInfeasibility_(0.0), complementarityGap_(0.0), baseObjectiveNorm_(0.0), worstDirectionAccuracy_(0.0), maximumRHSChange_(0.0), errorRegion_(NULL), rhsFixRegion_(NULL), upperSlack_(NULL), lowerSlack_(NULL), diagonal_(NULL), solution_(NULL), workArray_(NULL), deltaX_(NULL), deltaY_(NULL), deltaZ_(NULL), deltaW_(NULL), deltaSU_(NULL), deltaSL_(NULL), primalR_(NULL), dualR_(NULL), rhsB_(NULL), rhsU_(NULL), rhsL_(NULL), rhsZ_(NULL), rhsW_(NULL), rhsC_(NULL), zVec_(NULL), wVec_(NULL), cholesky_(NULL), numberComplementarityPairs_(0), numberComplementarityItems_(0), maximumBarrierIterations_(200), gonePrimalFeasible_(false), goneDualFeasible_(false), algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); // put in placeholder } // Subproblem constructor ClpInterior::ClpInterior ( const ClpModel * rhs, int numberRows, const int * whichRow, int numberColumns, const int * whichColumn, bool dropNames, bool dropIntegers) : ClpModel(rhs, numberRows, whichRow, numberColumns, whichColumn, dropNames, dropIntegers), largestPrimalError_(0.0), largestDualError_(0.0), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), worstComplementarity_(0.0), xsize_(0.0), zsize_(0.0), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rhs_(NULL), x_(NULL), y_(NULL), dj_(NULL), lsqrObject_(NULL), pdcoStuff_(NULL), mu_(0.0), objectiveNorm_(1.0e-12), rhsNorm_(1.0e-12), solutionNorm_(1.0e-12), dualObjective_(0.0), primalObjective_(0.0), diagonalNorm_(1.0e-12), stepLength_(0.99995), linearPerturbation_(1.0e-12), diagonalPerturbation_(1.0e-15), gamma_(0.0), delta_(0), targetGap_(1.0e-12), projectionTolerance_(1.0e-7), maximumRHSError_(0.0), maximumBoundInfeasibility_(0.0), maximumDualError_(0.0), diagonalScaleFactor_(0.0), scaleFactor_(0.0), actualPrimalStep_(0.0), actualDualStep_(0.0), smallestInfeasibility_(0.0), complementarityGap_(0.0), baseObjectiveNorm_(0.0), worstDirectionAccuracy_(0.0), maximumRHSChange_(0.0), errorRegion_(NULL), rhsFixRegion_(NULL), upperSlack_(NULL), lowerSlack_(NULL), diagonal_(NULL), solution_(NULL), workArray_(NULL), deltaX_(NULL), deltaY_(NULL), deltaZ_(NULL), deltaW_(NULL), deltaSU_(NULL), deltaSL_(NULL), primalR_(NULL), dualR_(NULL), rhsB_(NULL), rhsU_(NULL), rhsL_(NULL), rhsZ_(NULL), rhsW_(NULL), rhsC_(NULL), zVec_(NULL), wVec_(NULL), cholesky_(NULL), numberComplementarityPairs_(0), numberComplementarityItems_(0), maximumBarrierIterations_(200), gonePrimalFeasible_(false), goneDualFeasible_(false), algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); } //----------------------------------------------------------------------------- ClpInterior::~ClpInterior () { gutsOfDelete(); } //############################################################################# /* This does housekeeping */ int ClpInterior::housekeeping() { numberIterations_++; return 0; } // Copy constructor. ClpInterior::ClpInterior(const ClpInterior &rhs) : ClpModel(rhs), largestPrimalError_(0.0), largestDualError_(0.0), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), worstComplementarity_(0.0), xsize_(0.0), zsize_(0.0), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rhs_(NULL), x_(NULL), y_(NULL), dj_(NULL), lsqrObject_(NULL), pdcoStuff_(NULL), errorRegion_(NULL), rhsFixRegion_(NULL), upperSlack_(NULL), lowerSlack_(NULL), diagonal_(NULL), solution_(NULL), workArray_(NULL), deltaX_(NULL), deltaY_(NULL), deltaZ_(NULL), deltaW_(NULL), deltaSU_(NULL), deltaSL_(NULL), primalR_(NULL), dualR_(NULL), rhsB_(NULL), rhsU_(NULL), rhsL_(NULL), rhsZ_(NULL), rhsW_(NULL), rhsC_(NULL), zVec_(NULL), wVec_(NULL), cholesky_(NULL) { gutsOfDelete(); gutsOfCopy(rhs); solveType_ = 3; // say interior based life form } // Copy constructor from model ClpInterior::ClpInterior(const ClpModel &rhs) : ClpModel(rhs), largestPrimalError_(0.0), largestDualError_(0.0), sumDualInfeasibilities_(0.0), sumPrimalInfeasibilities_(0.0), worstComplementarity_(0.0), xsize_(0.0), zsize_(0.0), lower_(NULL), rowLowerWork_(NULL), columnLowerWork_(NULL), upper_(NULL), rowUpperWork_(NULL), columnUpperWork_(NULL), cost_(NULL), rhs_(NULL), x_(NULL), y_(NULL), dj_(NULL), lsqrObject_(NULL), pdcoStuff_(NULL), mu_(0.0), objectiveNorm_(1.0e-12), rhsNorm_(1.0e-12), solutionNorm_(1.0e-12), dualObjective_(0.0), primalObjective_(0.0), diagonalNorm_(1.0e-12), stepLength_(0.99995), linearPerturbation_(1.0e-12), diagonalPerturbation_(1.0e-15), gamma_(0.0), delta_(0), targetGap_(1.0e-12), projectionTolerance_(1.0e-7), maximumRHSError_(0.0), maximumBoundInfeasibility_(0.0), maximumDualError_(0.0), diagonalScaleFactor_(0.0), scaleFactor_(0.0), actualPrimalStep_(0.0), actualDualStep_(0.0), smallestInfeasibility_(0.0), complementarityGap_(0.0), baseObjectiveNorm_(0.0), worstDirectionAccuracy_(0.0), maximumRHSChange_(0.0), errorRegion_(NULL), rhsFixRegion_(NULL), upperSlack_(NULL), lowerSlack_(NULL), diagonal_(NULL), solution_(NULL), workArray_(NULL), deltaX_(NULL), deltaY_(NULL), deltaZ_(NULL), deltaW_(NULL), deltaSU_(NULL), deltaSL_(NULL), primalR_(NULL), dualR_(NULL), rhsB_(NULL), rhsU_(NULL), rhsL_(NULL), rhsZ_(NULL), rhsW_(NULL), rhsC_(NULL), zVec_(NULL), wVec_(NULL), cholesky_(NULL), numberComplementarityPairs_(0), numberComplementarityItems_(0), maximumBarrierIterations_(200), gonePrimalFeasible_(false), goneDualFeasible_(false), algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); } // Assignment operator. This copies the data ClpInterior & ClpInterior::operator=(const ClpInterior & rhs) { if (this != &rhs) { gutsOfDelete(); ClpModel::operator=(rhs); gutsOfCopy(rhs); } return *this; } void ClpInterior::gutsOfCopy(const ClpInterior & rhs) { lower_ = ClpCopyOfArray(rhs.lower_, numberColumns_ + numberRows_); rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; upper_ = ClpCopyOfArray(rhs.upper_, numberColumns_ + numberRows_); rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; //cost_ = ClpCopyOfArray(rhs.cost_,2*(numberColumns_+numberRows_)); cost_ = ClpCopyOfArray(rhs.cost_, numberColumns_); rhs_ = ClpCopyOfArray(rhs.rhs_, numberRows_); x_ = ClpCopyOfArray(rhs.x_, numberColumns_); y_ = ClpCopyOfArray(rhs.y_, numberRows_); dj_ = ClpCopyOfArray(rhs.dj_, numberColumns_ + numberRows_); lsqrObject_ = rhs.lsqrObject_ != NULL ? new ClpLsqr(*rhs.lsqrObject_) : NULL; pdcoStuff_ = rhs.pdcoStuff_ != NULL ? rhs.pdcoStuff_->clone() : NULL; largestPrimalError_ = rhs.largestPrimalError_; largestDualError_ = rhs.largestDualError_; sumDualInfeasibilities_ = rhs.sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; worstComplementarity_ = rhs.worstComplementarity_; xsize_ = rhs.xsize_; zsize_ = rhs.zsize_; solveType_ = rhs.solveType_; mu_ = rhs.mu_; objectiveNorm_ = rhs.objectiveNorm_; rhsNorm_ = rhs.rhsNorm_; solutionNorm_ = rhs.solutionNorm_; dualObjective_ = rhs.dualObjective_; primalObjective_ = rhs.primalObjective_; diagonalNorm_ = rhs.diagonalNorm_; stepLength_ = rhs.stepLength_; linearPerturbation_ = rhs.linearPerturbation_; diagonalPerturbation_ = rhs.diagonalPerturbation_; gamma_ = rhs.gamma_; delta_ = rhs.delta_; targetGap_ = rhs.targetGap_; projectionTolerance_ = rhs.projectionTolerance_; maximumRHSError_ = rhs.maximumRHSError_; maximumBoundInfeasibility_ = rhs.maximumBoundInfeasibility_; maximumDualError_ = rhs.maximumDualError_; diagonalScaleFactor_ = rhs.diagonalScaleFactor_; scaleFactor_ = rhs.scaleFactor_; actualPrimalStep_ = rhs.actualPrimalStep_; actualDualStep_ = rhs.actualDualStep_; smallestInfeasibility_ = rhs.smallestInfeasibility_; complementarityGap_ = rhs.complementarityGap_; baseObjectiveNorm_ = rhs.baseObjectiveNorm_; worstDirectionAccuracy_ = rhs.worstDirectionAccuracy_; maximumRHSChange_ = rhs.maximumRHSChange_; errorRegion_ = ClpCopyOfArray(rhs.errorRegion_, numberRows_); rhsFixRegion_ = ClpCopyOfArray(rhs.rhsFixRegion_, numberRows_); deltaY_ = ClpCopyOfArray(rhs.deltaY_, numberRows_); upperSlack_ = ClpCopyOfArray(rhs.upperSlack_, numberRows_ + numberColumns_); lowerSlack_ = ClpCopyOfArray(rhs.lowerSlack_, numberRows_ + numberColumns_); diagonal_ = ClpCopyOfArray(rhs.diagonal_, numberRows_ + numberColumns_); deltaX_ = ClpCopyOfArray(rhs.deltaX_, numberRows_ + numberColumns_); deltaZ_ = ClpCopyOfArray(rhs.deltaZ_, numberRows_ + numberColumns_); deltaW_ = ClpCopyOfArray(rhs.deltaW_, numberRows_ + numberColumns_); deltaSU_ = ClpCopyOfArray(rhs.deltaSU_, numberRows_ + numberColumns_); deltaSL_ = ClpCopyOfArray(rhs.deltaSL_, numberRows_ + numberColumns_); primalR_ = ClpCopyOfArray(rhs.primalR_, numberRows_ + numberColumns_); dualR_ = ClpCopyOfArray(rhs.dualR_, numberRows_ + numberColumns_); rhsB_ = ClpCopyOfArray(rhs.rhsB_, numberRows_); rhsU_ = ClpCopyOfArray(rhs.rhsU_, numberRows_ + numberColumns_); rhsL_ = ClpCopyOfArray(rhs.rhsL_, numberRows_ + numberColumns_); rhsZ_ = ClpCopyOfArray(rhs.rhsZ_, numberRows_ + numberColumns_); rhsW_ = ClpCopyOfArray(rhs.rhsW_, numberRows_ + numberColumns_); rhsC_ = ClpCopyOfArray(rhs.rhsC_, numberRows_ + numberColumns_); solution_ = ClpCopyOfArray(rhs.solution_, numberRows_ + numberColumns_); workArray_ = ClpCopyOfArray(rhs.workArray_, numberRows_ + numberColumns_); zVec_ = ClpCopyOfArray(rhs.zVec_, numberRows_ + numberColumns_); wVec_ = ClpCopyOfArray(rhs.wVec_, numberRows_ + numberColumns_); cholesky_ = rhs.cholesky_->clone(); numberComplementarityPairs_ = rhs.numberComplementarityPairs_; numberComplementarityItems_ = rhs.numberComplementarityItems_; maximumBarrierIterations_ = rhs.maximumBarrierIterations_; gonePrimalFeasible_ = rhs.gonePrimalFeasible_; goneDualFeasible_ = rhs.goneDualFeasible_; algorithm_ = rhs.algorithm_; } void ClpInterior::gutsOfDelete() { delete [] lower_; lower_ = NULL; rowLowerWork_ = NULL; columnLowerWork_ = NULL; delete [] upper_; upper_ = NULL; rowUpperWork_ = NULL; columnUpperWork_ = NULL; delete [] cost_; cost_ = NULL; delete [] rhs_; rhs_ = NULL; delete [] x_; x_ = NULL; delete [] y_; y_ = NULL; delete [] dj_; dj_ = NULL; delete lsqrObject_; lsqrObject_ = NULL; //delete pdcoStuff_; // FIXME pdcoStuff_ = NULL; delete [] errorRegion_; errorRegion_ = NULL; delete [] rhsFixRegion_; rhsFixRegion_ = NULL; delete [] deltaY_; deltaY_ = NULL; delete [] upperSlack_; upperSlack_ = NULL; delete [] lowerSlack_; lowerSlack_ = NULL; delete [] diagonal_; diagonal_ = NULL; delete [] deltaX_; deltaX_ = NULL; delete [] deltaZ_; deltaZ_ = NULL; delete [] deltaW_; deltaW_ = NULL; delete [] deltaSU_; deltaSU_ = NULL; delete [] deltaSL_; deltaSL_ = NULL; delete [] primalR_; primalR_ = NULL; delete [] dualR_; dualR_ = NULL; delete [] rhsB_; rhsB_ = NULL; delete [] rhsU_; rhsU_ = NULL; delete [] rhsL_; rhsL_ = NULL; delete [] rhsZ_; rhsZ_ = NULL; delete [] rhsW_; rhsW_ = NULL; delete [] rhsC_; rhsC_ = NULL; delete [] solution_; solution_ = NULL; delete [] workArray_; workArray_ = NULL; delete [] zVec_; zVec_ = NULL; delete [] wVec_; wVec_ = NULL; delete cholesky_; } bool ClpInterior::createWorkingData() { bool goodMatrix = true; //check matrix if (!matrix_->allElementsInRange(this, 1.0e-12, 1.0e20)) { problemStatus_ = 4; goodMatrix = false; } int nTotal = numberRows_ + numberColumns_; delete [] solution_; solution_ = new CoinWorkDouble[nTotal]; CoinMemcpyN(columnActivity_, numberColumns_, solution_); CoinMemcpyN(rowActivity_, numberRows_, solution_ + numberColumns_); delete [] cost_; cost_ = new CoinWorkDouble[nTotal]; int i; CoinWorkDouble direction = optimizationDirection_ * objectiveScale_; // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; const double * obj = objective(); for (i = 0; i < numberColumns_; i++) cost_[i] = direction * obj[i]; memset(cost_ + numberColumns_, 0, numberRows_ * sizeof(CoinWorkDouble)); // do scaling if needed if (scalingFlag_ > 0 && !rowScale_) { if (matrix_->scale(this)) scalingFlag_ = -scalingFlag_; // not scaled after all } delete [] lower_; delete [] upper_; lower_ = new CoinWorkDouble[nTotal]; upper_ = new CoinWorkDouble[nTotal]; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; CoinMemcpyN(rowLower_, numberRows_, rowLowerWork_); CoinMemcpyN(rowUpper_, numberRows_, rowUpperWork_); CoinMemcpyN(columnLower_, numberColumns_, columnLowerWork_); CoinMemcpyN(columnUpper_, numberColumns_, columnUpperWork_); // clean up any mismatches on infinity for (i = 0; i < numberColumns_; i++) { if (columnLowerWork_[i] < -1.0e30) columnLowerWork_[i] = -COIN_DBL_MAX; if (columnUpperWork_[i] > 1.0e30) columnUpperWork_[i] = COIN_DBL_MAX; } // clean up any mismatches on infinity for (i = 0; i < numberRows_; i++) { if (rowLowerWork_[i] < -1.0e30) rowLowerWork_[i] = -COIN_DBL_MAX; if (rowUpperWork_[i] > 1.0e30) rowUpperWork_[i] = COIN_DBL_MAX; } // check rim of problem okay if (!sanityCheck()) goodMatrix = false; if(rowScale_) { for (i = 0; i < numberColumns_; i++) { CoinWorkDouble multiplier = rhsScale_ / columnScale_[i]; cost_[i] *= columnScale_[i]; if (columnLowerWork_[i] > -1.0e50) columnLowerWork_[i] *= multiplier; if (columnUpperWork_[i] < 1.0e50) columnUpperWork_[i] *= multiplier; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble multiplier = rhsScale_ * rowScale_[i]; if (rowLowerWork_[i] > -1.0e50) rowLowerWork_[i] *= multiplier; if (rowUpperWork_[i] < 1.0e50) rowUpperWork_[i] *= multiplier; } } else if (rhsScale_ != 1.0) { for (i = 0; i < numberColumns_ + numberRows_; i++) { if (lower_[i] > -1.0e50) lower_[i] *= rhsScale_; if (upper_[i] < 1.0e50) upper_[i] *= rhsScale_; } } assert (!errorRegion_); errorRegion_ = new CoinWorkDouble [numberRows_]; assert (!rhsFixRegion_); rhsFixRegion_ = new CoinWorkDouble [numberRows_]; assert (!deltaY_); deltaY_ = new CoinWorkDouble [numberRows_]; CoinZeroN(deltaY_, numberRows_); assert (!upperSlack_); upperSlack_ = new CoinWorkDouble [nTotal]; assert (!lowerSlack_); lowerSlack_ = new CoinWorkDouble [nTotal]; assert (!diagonal_); diagonal_ = new CoinWorkDouble [nTotal]; assert (!deltaX_); deltaX_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaX_, nTotal); assert (!deltaZ_); deltaZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaZ_, nTotal); assert (!deltaW_); deltaW_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaW_, nTotal); assert (!deltaSU_); deltaSU_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSU_, nTotal); assert (!deltaSL_); deltaSL_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSL_, nTotal); assert (!primalR_); assert (!dualR_); // create arrays if we are doing KKT if (cholesky_->type() >= 20) { primalR_ = new CoinWorkDouble [nTotal]; CoinZeroN(primalR_, nTotal); dualR_ = new CoinWorkDouble [numberRows_]; CoinZeroN(dualR_, numberRows_); } assert (!rhsB_); rhsB_ = new CoinWorkDouble [numberRows_]; CoinZeroN(rhsB_, numberRows_); assert (!rhsU_); rhsU_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsU_, nTotal); assert (!rhsL_); rhsL_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsL_, nTotal); assert (!rhsZ_); rhsZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsZ_, nTotal); assert (!rhsW_); rhsW_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsW_, nTotal); assert (!rhsC_); rhsC_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsC_, nTotal); assert (!workArray_); workArray_ = new CoinWorkDouble [nTotal]; CoinZeroN(workArray_, nTotal); assert (!zVec_); zVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(zVec_, nTotal); assert (!wVec_); wVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(wVec_, nTotal); assert (!dj_); dj_ = new CoinWorkDouble [nTotal]; if (!status_) status_ = new unsigned char [numberRows_+numberColumns_]; memset(status_, 0, numberRows_ + numberColumns_); return goodMatrix; } void ClpInterior::deleteWorkingData() { int i; if (optimizationDirection_ != 1.0 || objectiveScale_ != 1.0) { CoinWorkDouble scaleC = optimizationDirection_ / objectiveScale_; // and modify all dual signs for (i = 0; i < numberColumns_; i++) reducedCost_[i] = scaleC * dj_[i]; for (i = 0; i < numberRows_; i++) dual_[i] *= scaleC; } if (rowScale_) { CoinWorkDouble scaleR = 1.0 / rhsScale_; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble scaleFactor = columnScale_[i]; CoinWorkDouble valueScaled = columnActivity_[i]; columnActivity_[i] = valueScaled * scaleFactor * scaleR; CoinWorkDouble valueScaledDual = reducedCost_[i]; reducedCost_[i] = valueScaledDual / scaleFactor; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble scaleFactor = rowScale_[i]; CoinWorkDouble valueScaled = rowActivity_[i]; rowActivity_[i] = (valueScaled * scaleR) / scaleFactor; CoinWorkDouble valueScaledDual = dual_[i]; dual_[i] = valueScaledDual * scaleFactor; } } else if (rhsScale_ != 1.0) { CoinWorkDouble scaleR = 1.0 / rhsScale_; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble valueScaled = columnActivity_[i]; columnActivity_[i] = valueScaled * scaleR; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble valueScaled = rowActivity_[i]; rowActivity_[i] = valueScaled * scaleR; } } delete [] cost_; cost_ = NULL; delete [] solution_; solution_ = NULL; delete [] lower_; lower_ = NULL; delete [] upper_; upper_ = NULL; delete [] errorRegion_; errorRegion_ = NULL; delete [] rhsFixRegion_; rhsFixRegion_ = NULL; delete [] deltaY_; deltaY_ = NULL; delete [] upperSlack_; upperSlack_ = NULL; delete [] lowerSlack_; lowerSlack_ = NULL; delete [] diagonal_; diagonal_ = NULL; delete [] deltaX_; deltaX_ = NULL; delete [] workArray_; workArray_ = NULL; delete [] zVec_; zVec_ = NULL; delete [] wVec_; wVec_ = NULL; delete [] dj_; dj_ = NULL; } // Sanity check on input data - returns true if okay bool ClpInterior::sanityCheck() { // bad if empty if (!numberColumns_ || ((!numberRows_ || !matrix_->getNumElements()) && objective_->type() < 2)) { problemStatus_ = emptyProblem(); return false; } int numberBad ; CoinWorkDouble largestBound, smallestBound, minimumGap; CoinWorkDouble smallestObj, largestObj; int firstBad; int modifiedBounds = 0; int i; numberBad = 0; firstBad = -1; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; smallestObj = 1.0e100; largestObj = 0.0; // If bounds are too close - fix CoinWorkDouble fixTolerance = 1.1 * primalTolerance(); for (i = numberColumns_; i < numberColumns_ + numberRows_; i++) { CoinWorkDouble value; value = CoinAbs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance()) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = CoinAbs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = CoinAbs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } if (largestBound) handler_->message(CLP_RIMSTATISTICS3, messages_) << static_cast(smallestBound) << static_cast(largestBound) << static_cast(minimumGap) << CoinMessageEol; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble value; value = CoinAbs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance()) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = CoinAbs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = CoinAbs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } char rowcol[] = {'R', 'C'}; if (numberBad) { handler_->message(CLP_BAD_BOUNDS, messages_) << numberBad << rowcol[isColumn(firstBad)] << sequenceWithin(firstBad) << CoinMessageEol; problemStatus_ = 4; return false; } if (modifiedBounds) handler_->message(CLP_MODIFIEDBOUNDS, messages_) << modifiedBounds << CoinMessageEol; handler_->message(CLP_RIMSTATISTICS1, messages_) << static_cast(smallestObj) << static_cast(largestObj) << CoinMessageEol; if (largestBound) handler_->message(CLP_RIMSTATISTICS2, messages_) << static_cast(smallestBound) << static_cast(largestBound) << static_cast(minimumGap) << CoinMessageEol; return true; } /* Loads a problem (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
*/ void ClpInterior::loadProblem ( const ClpMatrixBase& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); } void ClpInterior::loadProblem ( const CoinPackedMatrix& matrix, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); } /* Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ void ClpInterior::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, const double * rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub, rowObjective); } void ClpInterior::loadProblem ( const int numcols, const int numrows, const CoinBigIndex* start, const int* index, const double* value, const int * length, const double* collb, const double* colub, const double* obj, const double* rowlb, const double* rowub, const double * rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, length, collb, colub, obj, rowlb, rowub, rowObjective); } // Read an mps file from the given filename int ClpInterior::readMps(const char *filename, bool keepNames, bool ignoreErrors) { int status = ClpModel::readMps(filename, keepNames, ignoreErrors); return status; } #include "ClpPdco.hpp" /* Pdco algorithm - see ClpPdco.hpp for method */ int ClpInterior::pdco() { return ((ClpPdco *) this)->pdco(); } // ** Temporary version int ClpInterior::pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo) { return ((ClpPdco *) this)->pdco(stuff, options, info, outfo); } #include "ClpPredictorCorrector.hpp" // Primal-Dual Predictor-Corrector barrier int ClpInterior::primalDual() { return (static_cast (this))->solve(); } void ClpInterior::checkSolution() { int iRow, iColumn; CoinWorkDouble * reducedCost = reinterpret_cast(reducedCost_); CoinWorkDouble * dual = reinterpret_cast(dual_); CoinMemcpyN(cost_, numberColumns_, reducedCost); matrix_->transposeTimes(-1.0, dual, reducedCost); // Now modify reduced costs for quadratic CoinWorkDouble quadraticOffset = quadraticDjs(reducedCost, solution_, scaleFactor_); objectiveValue_ = 0.0; // now look at solution sumPrimalInfeasibilities_ = 0.0; sumDualInfeasibilities_ = 0.0; CoinWorkDouble dualTolerance = 10.0 * dblParam_[ClpDualTolerance]; CoinWorkDouble primalTolerance = dblParam_[ClpPrimalTolerance]; CoinWorkDouble primalTolerance2 = 10.0 * dblParam_[ClpPrimalTolerance]; worstComplementarity_ = 0.0; complementarityGap_ = 0.0; // Done scaled - use permanent regions for output // but internal for bounds const CoinWorkDouble * lower = lower_ + numberColumns_; const CoinWorkDouble * upper = upper_ + numberColumns_; for (iRow = 0; iRow < numberRows_; iRow++) { CoinWorkDouble infeasibility = 0.0; CoinWorkDouble distanceUp = CoinMin(upper[iRow] - rowActivity_[iRow], static_cast(1.0e10)); CoinWorkDouble distanceDown = CoinMin(rowActivity_[iRow] - lower[iRow], static_cast(1.0e10)); if (distanceUp > primalTolerance2) { CoinWorkDouble value = dual[iRow]; // should not be negative if (value < -dualTolerance) { sumDualInfeasibilities_ += -dualTolerance - value; value = - value * distanceUp; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (distanceDown > primalTolerance2) { CoinWorkDouble value = dual[iRow]; // should not be positive if (value > dualTolerance) { sumDualInfeasibilities_ += value - dualTolerance; value = value * distanceDown; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (rowActivity_[iRow] > upper[iRow]) { infeasibility = rowActivity_[iRow] - upper[iRow]; } else if (rowActivity_[iRow] < lower[iRow]) { infeasibility = lower[iRow] - rowActivity_[iRow]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance; } } lower = lower_; upper = upper_; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinWorkDouble infeasibility = 0.0; objectiveValue_ += cost_[iColumn] * columnActivity_[iColumn]; CoinWorkDouble distanceUp = CoinMin(upper[iColumn] - columnActivity_[iColumn], static_cast(1.0e10)); CoinWorkDouble distanceDown = CoinMin(columnActivity_[iColumn] - lower[iColumn], static_cast(1.0e10)); if (distanceUp > primalTolerance2) { CoinWorkDouble value = reducedCost[iColumn]; // should not be negative if (value < -dualTolerance) { sumDualInfeasibilities_ += -dualTolerance - value; value = - value * distanceUp; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (distanceDown > primalTolerance2) { CoinWorkDouble value = reducedCost[iColumn]; // should not be positive if (value > dualTolerance) { sumDualInfeasibilities_ += value - dualTolerance; value = value * distanceDown; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (columnActivity_[iColumn] > upper[iColumn]) { infeasibility = columnActivity_[iColumn] - upper[iColumn]; } else if (columnActivity_[iColumn] < lower[iColumn]) { infeasibility = lower[iColumn] - columnActivity_[iColumn]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance; } } #if COIN_LONG_WORK // ok as packs down CoinMemcpyN(reducedCost, numberColumns_, reducedCost_); #endif // add in offset objectiveValue_ += 0.5 * quadraticOffset; } // Set cholesky (and delete present one) void ClpInterior::setCholesky(ClpCholeskyBase * cholesky) { delete cholesky_; cholesky_ = cholesky; } /* Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm. This is same as ClpModel one. */ void ClpInterior::borrowModel(ClpModel & otherModel) { ClpModel::borrowModel(otherModel); } /* Return model - updates any scalars */ void ClpInterior::returnModel(ClpModel & otherModel) { ClpModel::returnModel(otherModel); } // Return number fixed to see if worth presolving int ClpInterior::numberFixed() const { int i; int nFixed = 0; for (i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) { if (columnUpper_[i] > columnLower_[i]) { if (fixedOrFree(i)) nFixed++; } } } for (i = 0; i < numberRows_; i++) { if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) { if (rowUpper_[i] > rowLower_[i]) { if (fixedOrFree(i + numberColumns_)) nFixed++; } } } return nFixed; } // fix variables interior says should be void ClpInterior::fixFixed(bool reallyFix) { // Arrays for change in columns and rhs CoinWorkDouble * columnChange = new CoinWorkDouble[numberColumns_]; CoinWorkDouble * rowChange = new CoinWorkDouble[numberRows_]; CoinZeroN(columnChange, numberColumns_); CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); int i; CoinWorkDouble tolerance = primalTolerance(); for (i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) { if (columnUpper_[i] > columnLower_[i]) { if (fixedOrFree(i)) { if (columnActivity_[i] - columnLower_[i] < columnUpper_[i] - columnActivity_[i]) { CoinWorkDouble change = columnLower_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnUpper_[i] = columnLower_[i]; columnChange[i] = change; columnActivity_[i] = columnLower_[i]; } } else { CoinWorkDouble change = columnUpper_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnLower_[i] = columnUpper_[i]; columnChange[i] = change; columnActivity_[i] = columnUpper_[i]; } } } } } } CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); // If makes mess of things then don't do CoinWorkDouble newSum = 0.0; for (i = 0; i < numberRows_; i++) { CoinWorkDouble value = rowActivity_[i] + rowChange[i]; if (value > rowUpper_[i] + tolerance) newSum += value - rowUpper_[i] - tolerance; else if (value < rowLower_[i] - tolerance) newSum -= value - rowLower_[i] + tolerance; } if (newSum > 1.0e-5 + 1.5 * sumPrimalInfeasibilities_) { // put back and skip changes for (i = 0; i < numberColumns_; i++) columnActivity_[i] -= columnChange[i]; } else { CoinZeroN(rowActivity_, numberRows_); matrix_->times(1.0, columnActivity_, rowActivity_); if (reallyFix) { for (i = 0; i < numberRows_; i++) { if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) { if (rowUpper_[i] > rowLower_[i]) { if (fixedOrFree(i + numberColumns_)) { if (rowActivity_[i] - rowLower_[i] < rowUpper_[i] - rowActivity_[i]) { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowUpper_[i] = rowLower_[i]; rowActivity_[i] = rowLower_[i]; } } else { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowLower_[i] = rowUpper_[i]; rowActivity_[i] = rowUpper_[i]; } } } } } } } } delete [] rowChange; delete [] columnChange; } /* Modifies djs to allow for quadratic. returns quadratic offset */ CoinWorkDouble ClpInterior::quadraticDjs(CoinWorkDouble * djRegion, const CoinWorkDouble * solution, CoinWorkDouble scaleFactor) { CoinWorkDouble quadraticOffset = 0.0; #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_)); #else ClpQuadraticObjective * quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_)); #endif if (quadraticObj) { CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); const int * columnQuadratic = quadratic->getIndices(); const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); double * quadraticElement = quadratic->getMutableElements(); int numberColumns = quadratic->getNumCols(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinWorkDouble value = 0.0; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble valueJ = solution[jColumn]; CoinWorkDouble elementValue = quadraticElement[j]; //value += valueI*valueJ*elementValue; value += valueJ * elementValue; quadraticOffset += solution[iColumn] * valueJ * elementValue; } djRegion[iColumn] += scaleFactor * value; } } return quadraticOffset; } Clp-1.15.10/src/ClpSolve.hpp0000644000076600007660000003347412130015370014105 0ustar coincoin/* $Id: ClpSolve.hpp 1928 2013-04-06 12:54: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). /* Authors John Forrest */ #ifndef ClpSolve_H #define ClpSolve_H /** This is a very simple class to guide algorithms. It is used to tidy up passing parameters to initialSolve and maybe for output from that */ class ClpSolve { public: /** enums for solve function */ enum SolveType { useDual = 0, usePrimal, usePrimalorSprint, useBarrier, useBarrierNoCross, automatic, notImplemented }; enum PresolveType { presolveOn = 0, presolveOff, presolveNumber, presolveNumberCost }; /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpSolve ( ); /// Constructor when you really know what you are doing ClpSolve ( SolveType method, PresolveType presolveType, int numberPasses, int options[6], int extraInfo[6], int independentOptions[3]); /// Generates code for above constructor void generateCpp(FILE * fp); /// Copy constructor. ClpSolve(const ClpSolve &); /// Assignment operator. This copies the data ClpSolve & operator=(const ClpSolve & rhs); /// Destructor ~ClpSolve ( ); //@} /**@name Functions most useful to user */ //@{ /** Special options - bits 0 4 - use crash (default allslack in dual, idiot in primal) 8 - all slack basis in primal 2 16 - switch off interrupt handling 3 32 - do not try and make plus minus one matrix 64 - do not use sprint even if problem looks good */ /** which translation is: which: 0 - startup in Dual (nothing if basis exists).: 0 - no basis 1 - crash 2 - use initiative about idiot! but no crash 1 - startup in Primal (nothing if basis exists): 0 - use initiative 1 - use crash 2 - use idiot and look at further info 3 - use sprint and look at further info 4 - use all slack 5 - use initiative but no idiot 6 - use initiative but no sprint 7 - use initiative but no crash 8 - do allslack or idiot 9 - do allslack or sprint 10 - slp before 11 - no nothing and primal(0) 2 - interrupt handling - 0 yes, 1 no (for threadsafe) 3 - whether to make +- 1matrix - 0 yes, 1 no 4 - for barrier 0 - dense cholesky 1 - Wssmp allowing some long columns 2 - Wssmp not allowing long columns 3 - Wssmp using KKT 4 - Using Florida ordering 8 - bit set to do scaling 16 - set to be aggressive with gamma/delta? 32 - Use KKT 5 - for presolve 1 - switch off dual stuff 6 - for detailed printout (initially just presolve) 1 - presolve statistics */ void setSpecialOption(int which, int value, int extraInfo = -1); int getSpecialOption(int which) const; /// Solve types void setSolveType(SolveType method, int extraInfo = -1); SolveType getSolveType(); // Presolve types void setPresolveType(PresolveType amount, int extraInfo = -1); PresolveType getPresolveType(); int getPresolvePasses() const; /// Extra info for idiot (or sprint) int getExtraInfo(int which) const; /** Say to return at once if infeasible, default is to solve */ void setInfeasibleReturn(bool trueFalse); inline bool infeasibleReturn() const { return independentOptions_[0] != 0; } /// Whether we want to do dual part of presolve inline bool doDual() const { return (independentOptions_[1] & 1) == 0; } inline void setDoDual(bool doDual_) { if (doDual_) independentOptions_[1] &= ~1; else independentOptions_[1] |= 1; } /// Whether we want to do singleton part of presolve inline bool doSingleton() const { return (independentOptions_[1] & 2) == 0; } inline void setDoSingleton(bool doSingleton_) { if (doSingleton_) independentOptions_[1] &= ~2; else independentOptions_[1] |= 2; } /// Whether we want to do doubleton part of presolve inline bool doDoubleton() const { return (independentOptions_[1] & 4) == 0; } inline void setDoDoubleton(bool doDoubleton_) { if (doDoubleton_) independentOptions_[1] &= ~4; else independentOptions_[1] |= 4; } /// Whether we want to do tripleton part of presolve inline bool doTripleton() const { return (independentOptions_[1] & 8) == 0; } inline void setDoTripleton(bool doTripleton_) { if (doTripleton_) independentOptions_[1] &= ~8; else independentOptions_[1] |= 8; } /// Whether we want to do tighten part of presolve inline bool doTighten() const { return (independentOptions_[1] & 16) == 0; } inline void setDoTighten(bool doTighten_) { if (doTighten_) independentOptions_[1] &= ~16; else independentOptions_[1] |= 16; } /// Whether we want to do forcing part of presolve inline bool doForcing() const { return (independentOptions_[1] & 32) == 0; } inline void setDoForcing(bool doForcing_) { if (doForcing_) independentOptions_[1] &= ~32; else independentOptions_[1] |= 32; } /// Whether we want to do impliedfree part of presolve inline bool doImpliedFree() const { return (independentOptions_[1] & 64) == 0; } inline void setDoImpliedFree(bool doImpliedfree) { if (doImpliedfree) independentOptions_[1] &= ~64; else independentOptions_[1] |= 64; } /// Whether we want to do dupcol part of presolve inline bool doDupcol() const { return (independentOptions_[1] & 128) == 0; } inline void setDoDupcol(bool doDupcol_) { if (doDupcol_) independentOptions_[1] &= ~128; else independentOptions_[1] |= 128; } /// Whether we want to do duprow part of presolve inline bool doDuprow() const { return (independentOptions_[1] & 256) == 0; } inline void setDoDuprow(bool doDuprow_) { if (doDuprow_) independentOptions_[1] &= ~256; else independentOptions_[1] |= 256; } /// Whether we want to do singleton column part of presolve inline bool doSingletonColumn() const { return (independentOptions_[1] & 512) == 0; } inline void setDoSingletonColumn(bool doSingleton_) { if (doSingleton_) independentOptions_[1] &= ~512; else independentOptions_[1] |= 512; } /// Whether we want to kill small substitutions inline bool doKillSmall() const { return (independentOptions_[1] & 1024) == 0; } inline void setDoKillSmall(bool doKill) { if (doKill) independentOptions_[1] &= ~1024; else independentOptions_[1] |= 1024; } /// Set whole group inline int presolveActions() const { return independentOptions_[1] & 0xffff; } inline void setPresolveActions(int action) { independentOptions_[1] = (independentOptions_[1] & 0xffff0000) | (action & 0xffff); } /// Largest column for substitution (normally 3) inline int substitution() const { return independentOptions_[2]; } inline void setSubstitution(int value) { independentOptions_[2] = value; } //@} ////////////////// data ////////////////// private: /**@name data. */ //@{ /// Solve type SolveType method_; /// Presolve type PresolveType presolveType_; /// Amount of presolve int numberPasses_; /// Options - last is switch for OsiClp int options_[7]; /// Extra information int extraInfo_[7]; /** Extra algorithm dependent options 0 - if set return from clpsolve if infeasible 1 - To be copied over to presolve options 2 - max substitution level */ int independentOptions_[3]; //@} }; /// For saving extra information to see if looping. class ClpSimplexProgress { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor ClpSimplexProgress ( ); /// Constructor from model ClpSimplexProgress ( ClpSimplex * model ); /// Copy constructor. ClpSimplexProgress(const ClpSimplexProgress &); /// Assignment operator. This copies the data ClpSimplexProgress & operator=(const ClpSimplexProgress & rhs); /// Destructor ~ClpSimplexProgress ( ); /// Resets as much as possible void reset(); /// Fill from model void fillFromModel ( ClpSimplex * model ); //@} /**@name Check progress */ //@{ /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, >=0 if give up and use as problem status */ int looping ( ); /// Start check at beginning of whileIterating void startCheck(); /// Returns cycle length in whileIterating int cycle(int in, int out, int wayIn, int wayOut); /// Returns previous objective (if -1) - current if (0) double lastObjective(int back = 1) const; /// Set real primal infeasibility and move back void setInfeasibility(double value); /// Returns real primal infeasibility (if -1) - current if (0) double lastInfeasibility(int back = 1) const; /// Modify objective e.g. if dual infeasible in dual void modifyObjective(double value); /// Returns previous iteration number (if -1) - current if (0) int lastIterationNumber(int back = 1) const; /// clears all iteration numbers (to switch off panic) void clearIterationNumbers(); /// Odd state inline void newOddState() { oddState_ = - oddState_ - 1; } inline void endOddState() { oddState_ = abs(oddState_); } inline void clearOddState() { oddState_ = 0; } inline int oddState() const { return oddState_; } /// number of bad times inline int badTimes() const { return numberBadTimes_; } inline void clearBadTimes() { numberBadTimes_ = 0; } /// number of really bad times inline int reallyBadTimes() const { return numberReallyBadTimes_; } inline void incrementReallyBadTimes() { numberReallyBadTimes_++; } /// number of times flagged inline int timesFlagged() const { return numberTimesFlagged_; } inline void clearTimesFlagged() { numberTimesFlagged_ = 0; } inline void incrementTimesFlagged() { numberTimesFlagged_++; } //@} /**@name Data */ #define CLP_PROGRESS 5 //#define CLP_PROGRESS_WEIGHT 10 //@{ /// Objective values double objective_[CLP_PROGRESS]; /// Sum of infeasibilities for algorithm double infeasibility_[CLP_PROGRESS]; /// Sum of real primal infeasibilities for primal double realInfeasibility_[CLP_PROGRESS]; #ifdef CLP_PROGRESS_WEIGHT /// Objective values for weights double objectiveWeight_[CLP_PROGRESS_WEIGHT]; /// Sum of infeasibilities for algorithm for weights double infeasibilityWeight_[CLP_PROGRESS_WEIGHT]; /// Sum of real primal infeasibilities for primal for weights double realInfeasibilityWeight_[CLP_PROGRESS_WEIGHT]; /// Drop for weights double drop_; /// Best? for weights double best_; #endif /// Initial weight for weights double initialWeight_; #define CLP_CYCLE 12 /// For cycle checking //double obj_[CLP_CYCLE]; int in_[CLP_CYCLE]; int out_[CLP_CYCLE]; char way_[CLP_CYCLE]; /// Pointer back to model so we can get information ClpSimplex * model_; /// Number of infeasibilities int numberInfeasibilities_[CLP_PROGRESS]; /// Iteration number at which occurred int iterationNumber_[CLP_PROGRESS]; #ifdef CLP_PROGRESS_WEIGHT /// Number of infeasibilities for weights int numberInfeasibilitiesWeight_[CLP_PROGRESS_WEIGHT]; /// Iteration number at which occurred for weights int iterationNumberWeight_[CLP_PROGRESS_WEIGHT]; #endif /// Number of times checked (so won't stop too early) int numberTimes_; /// Number of times it looked like loop int numberBadTimes_; /// Number really bad times int numberReallyBadTimes_; /// Number of times no iterations as flagged int numberTimesFlagged_; /// If things are in an odd state int oddState_; //@} }; #include "ClpConfig.h" #if CLP_HAS_ABC #include "AbcCommon.hpp" /// For saving extra information to see if looping. class AbcSimplexProgress : public ClpSimplexProgress { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor AbcSimplexProgress ( ); /// Constructor from model AbcSimplexProgress ( ClpSimplex * model ); /// Copy constructor. AbcSimplexProgress(const AbcSimplexProgress &); /// Assignment operator. This copies the data AbcSimplexProgress & operator=(const AbcSimplexProgress & rhs); /// Destructor ~AbcSimplexProgress ( ); //@} /**@name Check progress */ //@{ /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, >=0 if give up and use as problem status */ int looping ( ); //@} /**@name Data */ //@} }; #endif #endif Clp-1.15.10/src/ClpDummyMatrix.hpp0000644000076600007660000001634611510657452015312 0ustar coincoin/* $Id: ClpDummyMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpDummyMatrix_H #define ClpDummyMatrix_H #include "CoinPragma.hpp" #include "ClpMatrixBase.hpp" /** This implements a dummy matrix as derived from ClpMatrixBase. This is so you can do ClpPdco but may come in useful elsewhere. It just has dimensions but no data */ class ClpDummyMatrix : public ClpMatrixBase { public: /**@name Useful methods */ //@{ /// Return a complete CoinPackedMatrix virtual CoinPackedMatrix * getPackedMatrix() const; /** Whether the packed matrix is column major ordered or not. */ virtual bool isColOrdered() const { return true; } /** Number of entries in the packed matrix. */ virtual CoinBigIndex getNumElements() const { return numberElements_; } /** Number of columns. */ virtual int getNumCols() const { return numberColumns_; } /** Number of rows. */ virtual int getNumRows() const { return numberRows_; } /** A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const double * getElements() const; /** A vector containing the minor indices of the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const int * getIndices() const; virtual const CoinBigIndex * getVectorStarts() const; /** The lengths of the major-dimension vectors. */ virtual const int * getVectorLengths() const; /** Delete the columns whose indices are listed in indDel. */ virtual void deleteCols(const int numDel, const int * indDel); /** Delete the rows whose indices are listed in indDel. */ virtual void deleteRows(const int numDel, const int * indDel); /** Returns a new matrix in reverse order without gaps */ virtual ClpMatrixBase * reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis(const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const ; /** Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const ; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const; /// Allow any parts of a created CoinMatrix to be deleted /// Allow any parts of a created CoinPackedMatrix to be deleted virtual void releasePackedMatrix() const {} //@} /**@name Matrix times vector methods */ //@{ /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /// And for scaling virtual void times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ virtual void transposeTimes(double scalar, const double * x, double * y) const; /// And for scaling virtual void transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; using ClpMatrixBase::transposeTimes ; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x *A in z but just for indices in y. Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const; //@} /**@name Other */ //@{ //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpDummyMatrix(); /// Constructor with data ClpDummyMatrix(int numberColumns, int numberRows, int numberElements); /** Destructor */ virtual ~ClpDummyMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpDummyMatrix(const ClpDummyMatrix&); /** The copy constructor from an CoinDummyMatrix. */ ClpDummyMatrix(const CoinPackedMatrix&); ClpDummyMatrix& operator=(const ClpDummyMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Number of rows int numberRows_; /// Number of columns int numberColumns_; /// Number of elements int numberElements_; //@} }; #endif Clp-1.15.10/src/ClpSimplexPrimal.hpp0000644000076600007660000002164411510657452015615 0ustar coincoin/* $Id: ClpSimplexPrimal.hpp 1665 2011-01-04 17:55:54Z 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). /* Authors John Forrest */ #ifndef ClpSimplexPrimal_H #define ClpSimplexPrimal_H #include "ClpSimplex.hpp" /** This solves LPs using the primal simplex method It inherits from ClpSimplex. It has no data of its own and is never created - only cast from a ClpSimplex object at algorithm time. */ class ClpSimplexPrimal : public ClpSimplex { public: /**@name Description of algorithm */ //@{ /** Primal algorithm Method It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of infeasibilityCost_ being given to getting primal feasible. In this version I have tried to be clever in a stupid way. The idea of fake bounds in dual seems to work so the primal analogue would be that of getting bounds on reduced costs (by a presolve approach) and using these for being above or below feasible region. I decided to waste memory and keep these explicitly. This allows for non-linear costs! I have not tested non-linear costs but will be glad to do something if a reasonable example is provided. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find incoming variable for Dantzig row choice. For steepest edge we keep an updated list of dual infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. This method has not been coded. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure whether we will also need explicit perturbation. The flow of primal is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by changing bounds so primal feasible. If looks finished check fake primal bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot column (incoming variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot column in tableau Choose outgoing row. If we don't find one then we look primal unbounded so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find outgoing row, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve changing bounds on variables to stay primal feasible. } } TODO's (or maybe not) At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot in option. May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. for use of exotic parameter startFinishoptions see Clpsimplex.hpp */ int primal(int ifValuesPass = 0, int startFinishOptions = 0); //@} /**@name For advanced users */ //@{ /// Do not change infeasibility cost and always say optimal void alwaysOptimal(bool onOff); bool alwaysOptimal() const; /** Normally outgoing variables can go out to slightly negative values (but within tolerance) - this is to help stability and and degeneracy. This can be switched off */ void exactOutgoing(bool onOff); bool exactOutgoing() const; //@} /**@name Functions used in primal */ //@{ /** This has the flow between re-factorizations Returns a code to say where decision to exit was made Problem status set to: -2 re-factorize -4 Looks optimal/infeasible -5 Looks unbounded +3 max iterations valuesOption has original value of valuesPass */ int whileIterating(int valuesOption); /** Do last half of an iteration. This is split out so people can force incoming variable. If solveType_ is 2 then this may re-factorize while normally it would exit to re-factorize. Return codes Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done) With solveType_ ==2 this should Pivot in a variable and choose an outgoing one. Assumes primal feasible - will not go through a bound. Returns step length in theta Returns ray in ray_ */ int pivotResult(int ifValuesPass = 0); /** The primals are updated by the given array. Returns number of infeasibilities. After rowArray will have cost changes for use next iteration */ int updatePrimalsInPrimal(CoinIndexedVector * rowArray, double theta, double & objectiveChange, int valuesPass); /** Row array has pivot column This chooses pivot row. Rhs array is used for distance to next bound (for speed) For speed, we may need to go to a bucket approach when many variables go through bounds If valuesPass non-zero then compute dj for direction */ void primalRow(CoinIndexedVector * rowArray, CoinIndexedVector * rhsArray, CoinIndexedVector * spareArray, int valuesPass); /** Chooses primal pivot column updateArray has cost updates (also use pivotRow_ from last iteration) Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first columns we look at */ void primalColumn(CoinIndexedVector * updateArray, CoinIndexedVector * spareRow1, CoinIndexedVector * spareRow2, CoinIndexedVector * spareColumn1, CoinIndexedVector * spareColumn2); /** Checks if tentative optimal actually means unbounded in primal Returns -3 if not, 2 if is unbounded */ int checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, double changeCost); /** Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place. type - 0 initial so set up save arrays etc - 1 normal -if good update save - 2 restoring from saved saveModel is normally NULL but may not be if doing Sprint */ void statusOfProblemInPrimal(int & lastCleaned, int type, ClpSimplexProgress * progress, bool doFactorization, int ifValuesPass, ClpSimplex * saveModel = NULL); /// Perturbs problem (method depends on perturbation()) void perturb(int type); /// Take off effect of perturbation and say whether to try dual bool unPerturb(); /// Unflag all variables and return number unflagged int unflag(); /** Get next superbasic -1 if none, Normal type is 1 If type is 3 then initializes sorted list if 2 uses list. */ int nextSuperBasic(int superBasicType, CoinIndexedVector * columnArray); /// Create primal ray void primalRay(CoinIndexedVector * rowArray); /// Clears all bits and clears rowArray[1] etc void clearAll(); /// Sort of lexicographic resolve int lexSolve(); //@} }; #endif Clp-1.15.10/src/ClpConstraint.hpp0000644000076600007660000000724111510657452015150 0ustar coincoin/* $Id: ClpConstraint.hpp 1665 2011-01-04 17:55:54Z 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). #ifndef ClpConstraint_H #define ClpConstraint_H //############################################################################# class ClpSimplex; class ClpModel; /** Constraint Abstract Base Class Abstract Base Class for describing a constraint or objective function */ class ClpConstraint { public: ///@name Stuff //@{ /** Fills gradient. If Linear 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 undefined 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 = 0; /// Constraint function value virtual double functionValue (const ClpSimplex * model, const double * solution, bool useScaling = false, bool refresh = true) const ; /// Resize constraint virtual void resize(int newNumberColumns) = 0; /// Delete columns in constraint virtual void deleteSome(int numberToDelete, const int * which) = 0; /// Scale constraint virtual void reallyScale(const double * columnScale) = 0; /** Given a zeroed array sets nonlinear columns to 1. Returns number of nonlinear columns */ virtual int markNonlinear(char * which) const = 0; /** Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ virtual int markNonzero(char * which) const = 0; //@} ///@name Constructors and destructors //@{ /// Default Constructor ClpConstraint(); /// Copy constructor ClpConstraint(const ClpConstraint &); /// Assignment operator ClpConstraint & operator=(const ClpConstraint& rhs); /// Destructor virtual ~ClpConstraint (); /// Clone virtual ClpConstraint * clone() const = 0; //@} ///@name Other //@{ /// Returns type, 0 linear, 1 nonlinear inline int type() { return type_; } /// Row number (-1 is objective) inline int rowNumber() const { return rowNumber_; } /// Number of possible coefficients in gradient virtual int numberCoefficients() const = 0; /// Stored constraint function value inline double functionValue () const { return functionValue_; } /// Constraint offset inline double offset () const { return offset_; } /// Say we have new primal solution - so may need to recompute virtual void newXValues() {} //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Gradient at last evaluation mutable double * lastGradient_; /// Value of non-linear part of constraint mutable double functionValue_; /// Value of offset for constraint mutable double offset_; /// Type of constraint - linear is 1 int type_; /// Row number (-1 is objective) int rowNumber_; //@} }; #endif Clp-1.15.10/src/CoinAbcBaseFactorization2.cpp0000644000076600007660000013140712101105055017252 0ustar coincoin/* $Id: CoinAbcBaseFactorization2.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -2 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinFinite.hpp" // factorSparse. Does sparse phase of factorization //return code is <0 error, 0= finished CoinSimplexInt CoinAbcTypeFactorization::factorSparse ( ) { CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinSimplexInt * COIN_RESTRICT indexColumn = indexColumnUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; workArea_.conditionalNew(numberRows_); workAreaAddress_=workArea_.array(); CoinFactorizationDouble * COIN_RESTRICT workArea = workAreaAddress_; double initialLargest = preProcess3(); // adjust for test initialLargest=1.0e-10/initialLargest; #if ABC_NORMAL_DEBUG>0 double largestPivot=1.0; double smallestPivot=1.0; #endif CoinSimplexInt status = 0; //do slacks first CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; //CoinSimplexInt * numberInColumnPlus = numberInColumnPlusAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; //CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; CoinZeroN ( workArea, numberRows_ ); CoinSimplexInt * COIN_RESTRICT nextCount = this->nextCountAddress_; CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCountAddress_; CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; CoinBigIndex * COIN_RESTRICT startColumn = startColumnU; #if 0 { int checkEls=0; for (CoinSimplexInt iColumn=0;iColumn1 CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif //#define PRINT_INVERT_STATS #ifdef PRINT_INVERT_STATS int numberGoodUX=numberGoodU_; int numberTakenOutOfUSpace=0; #endif CoinSimplexInt look = firstCount[1]; while (look>=0) { checkLinks(1); CoinSimplexInt iPivotRow; CoinSimplexInt iPivotColumn=-1; #ifdef SMALL_PERMUTE int realPivotRow; int realPivotColumn=-1; #endif CoinFactorizationDouble pivotMultiplier=0.0; if ( look < numberRows_ ) { assert (numberInRow[look]==1); iPivotRow = look; CoinBigIndex start = startRow[iPivotRow]; iPivotColumn = indexColumn[start]; #ifdef SMALL_PERMUTE realPivotRow=fromSmallToBigRow_[iPivotRow]; realPivotColumn=fromSmallToBigColumn_[iPivotColumn]; //printf("singleton row realPivotRow %d realPivotColumn %d\n", // realPivotRow,realPivotColumn); #endif assert (numberInColumn[iPivotColumn]>0); CoinBigIndex startC = startColumn[iPivotColumn]; double minimumValue = fabs(element[startC]*tolerance ); #if CONVERTROW<2 CoinBigIndex where = startC; while ( indexRow[where] != iPivotRow ) { where++; } #else CoinBigIndex where = convertRowToColumn[start]; #endif assert ( where < startC+numberInColumn[iPivotColumn]); CoinFactorizationDouble value = element[where]; // size shouldn't matter as would be taken if matrix flipped but ... if ( fabs(value) > minimumValue ) { CoinSimplexInt numberDoColumn=numberInColumn[iPivotColumn]; totalElements_ -= numberDoColumn; // L is always big enough here //store column in L, compress in U and take column out CoinBigIndex l = lengthL_; lengthL_ += numberDoColumn-1; pivotMultiplier = 1.0/value; CoinBigIndex endC = startC + numberDoColumn; for (CoinBigIndex i = startC; i < endC; i++ ) { if (i!=where) { CoinSimplexInt iRow = indexRow[i]; #ifdef SMALL_PERMUTE indexRowL[l] = fromSmallToBigRow_[iRow]; #else indexRowL[l] = iRow; #endif elementL[l] = element[i] * pivotMultiplier; l++; //take out of row list CoinBigIndex startR = startRow[iRow]; CoinSimplexInt iNumberInRow = numberInRow[iRow]; CoinBigIndex endR = startR + iNumberInRow; #if CONVERTROW<2 CoinBigIndex whereRow = startR; while ( indexColumn[whereRow] != iPivotColumn ) whereRow++; assert ( whereRow < endR ); #else CoinBigIndex whereRow = convertColumnToRow[i]; #endif int iColumn = indexColumn[endR-1]; indexColumn[whereRow] = iColumn; #if CONVERTROW>1 CoinBigIndex whereColumnEntry = convertRowToColumn[endR-1]; convertRowToColumn[whereRow] = whereColumnEntry; convertColumnToRow[whereColumnEntry] = whereRow; #endif iNumberInRow--; numberInRow[iRow] = iNumberInRow; modifyLink ( iRow, iNumberInRow ); checkLinks(); } } } else { //printf("Rejecting as element %g largest %g\n",value,element[startC]); } } else { iPivotColumn = look - numberRows_; assert ( numberInColumn[iPivotColumn] == 1 ); { CoinBigIndex startC = startColumn[iPivotColumn]; iPivotRow = indexRow[startC]; #ifdef SMALL_PERMUTE realPivotRow=fromSmallToBigRow_[iPivotRow]; realPivotColumn=fromSmallToBigColumn_[iPivotColumn]; int realPivotRow; realPivotRow=fromSmallToBigRow_[iPivotRow]; indexRow[startC]=realPivotRow; //printf("singleton column realPivotRow %d realPivotColumn %d\n", // realPivotRow,realPivotColumn); #endif //store pivot columns (so can easily compress) assert (numberInColumn[iPivotColumn]==1); CoinSimplexInt numberDoRow = numberInRow[iPivotRow]; int numberDoColumn = numberInColumn[iPivotColumn] - 1; totalElements_ -= ( numberDoRow + numberDoColumn ); CoinBigIndex startR = startRow[iPivotRow]; CoinBigIndex endR = startR + numberDoRow ; //clean up counts pivotMultiplier = 1.0/element[startC]; // would I be better off doing other way first?? for (CoinBigIndex i = startR; i < endR; i++ ) { CoinSimplexInt iColumn = indexColumn[i]; if (iColumn==iPivotColumn) continue; assert ( numberInColumn[iColumn] ); CoinSimplexInt number = numberInColumn[iColumn] - 1; //modify linked list modifyLink ( iColumn + numberRows_, number ); CoinBigIndex start = startColumn[iColumn]; //move pivot row element if ( number ) { #if CONVERTROW<2 CoinBigIndex pivot = start; CoinSimplexInt iRow = indexRow[pivot]; while ( iRow != iPivotRow ) { pivot++; iRow = indexRow[pivot]; } #else CoinBigIndex pivot= convertRowToColumn[i]; #endif assert (pivot < startColumn[iColumn] + numberInColumn[iColumn]); if ( pivot != start ) { //move largest one up CoinFactorizationDouble value = element[start]; int iRow = indexRow[start]; element[start] = element[pivot]; indexRow[start] = indexRow[pivot]; element[pivot] = element[start + 1]; indexRow[pivot] = indexRow[start + 1]; #if CONVERTROW>1 CoinBigIndex whereRowEntry = convertColumnToRow[start+1]; CoinBigIndex whereRowEntry2 = convertColumnToRow[start]; convertRowToColumn[whereRowEntry] = pivot; convertColumnToRow[pivot] = whereRowEntry; convertRowToColumn[whereRowEntry2] = start+1; convertColumnToRow[start+1] = whereRowEntry2; #endif element[start + 1] = value; indexRow[start + 1] = iRow; } else { //find new largest element CoinSimplexInt iRowSave = indexRow[start + 1]; CoinFactorizationDouble valueSave = element[start + 1]; CoinFactorizationDouble valueLargest = fabs ( valueSave ); CoinBigIndex end = start + numberInColumn[iColumn]; CoinBigIndex largest = start + 1; for (CoinBigIndex k = start + 2; k < end; k++ ) { CoinFactorizationDouble value = element[k]; CoinFactorizationDouble valueAbs = fabs ( value ); if ( valueAbs > valueLargest ) { valueLargest = valueAbs; largest = k; } } indexRow[start + 1] = indexRow[largest]; element[start + 1] = element[largest]; #if CONVERTROW>1 CoinBigIndex whereRowEntry = convertColumnToRow[largest]; CoinBigIndex whereRowEntry2 = convertColumnToRow[start+1]; convertRowToColumn[whereRowEntry] = start+1; convertColumnToRow[start+1] = whereRowEntry; convertRowToColumn[whereRowEntry2] = largest; convertColumnToRow[largest] = whereRowEntry2; #endif indexRow[largest] = iRowSave; element[largest] = valueSave; } } //clean up counts numberInColumn[iColumn]--; numberInColumnPlus[iColumn]++; #ifdef SMALL_PERMUTE indexRow[start]=realPivotRow; #endif startColumn[iColumn]++; } } } if (pivotMultiplier) { numberGoodL_++; startColumnL[numberGoodL_] = lengthL_; //take out this bit of indexColumnU CoinSimplexInt next = nextRow[iPivotRow]; CoinSimplexInt last = lastRow[iPivotRow]; nextRow[last] = next; lastRow[next] = last; lastRow[iPivotRow] =-2; //mark #ifdef SMALL_PERMUTE // mark fromSmallToBigRow_[iPivotRow]=-1; fromSmallToBigColumn_[iPivotColumn]=-1; permuteAddress_[realPivotRow]=numberGoodU_; #else permuteAddress_[iPivotRow]=numberGoodU_; #endif #ifdef ABC_USE_FUNCTION_POINTERS int number = numberInColumnPlus[iPivotColumn]; #ifdef SMALL_PERMUTE #if ABC_USE_FUNCTION_POINTERS if (number<9) { scatter[realPivotRow].functionPointer=AbcScatterLowSubtract[number]; } else { scatter[realPivotRow].functionPointer=AbcScatterHighSubtract[number&3]; } #endif scatter[realPivotRow].offset=lastEntryByColumnUPlus_; scatter[realPivotRow].number=number; #else #if ABC_USE_FUNCTION_POINTERS if (number<9) { scatter[iPivotRow].functionPointer=AbcScatterLowSubtract[number]; } else { scatter[iPivotRow].functionPointer=AbcScatterHighSubtract[number&3]; } #endif scatter[iPivotRow].offset=lastEntryByColumnUPlus_; scatter[iPivotRow].number=number; #endif CoinBigIndex startC = startColumn[iPivotColumn]-number; for (int i=startC;i(elementUColumnPlus+lastEntryByColumnUPlus_),indexRow+startC,number); lastEntryByColumnUPlus_ += (number+1)>>1; #endif numberInColumn[iPivotColumn] = 0; numberInRow[iPivotRow] = 0; //modify linked list for pivots deleteLink ( iPivotRow ); deleteLink ( iPivotColumn + numberRows_ ); checkLinks(); #ifdef SMALL_PERMUTE assert (permuteAddress_[realPivotRow]==numberGoodU_); pivotColumn[numberGoodU_] = realPivotColumn; #else assert (permuteAddress_[iPivotRow]==numberGoodU_); pivotColumn[numberGoodU_] = iPivotColumn; #endif pivotRegion[numberGoodU_] = pivotMultiplier; numberGoodU_++; } else { //take out for moment modifyLink ( iPivotRow, numberRows_ + 1 ); } look=-1; //nextCount[look]; if (look<0) { // start again look = firstCount[1]; } assert (iPivotColumn>=0); #ifdef ABC_USE_FUNCTION_POINTERS if (!numberInColumn[iPivotColumn]) { int iNext=nextColumn[iPivotColumn]; int iLast=lastColumn[iPivotColumn]; assert (iLast>=0); #ifdef PRINT_INVERT_STATS numberTakenOutOfUSpace++; #endif lastColumn[iNext]=iLast; nextColumn[iLast]=iNext; } #endif } // put back all rejected look = firstCount[numberRows_+1]; while (look>=0) { #ifndef NDEBUG if ( look < numberRows_ ) { assert (numberInRow[look]==1); } else { int iColumn = look - numberRows_; assert ( numberInColumn[iColumn] == 1 ); } #endif int nextLook=nextCount[look]; modifyLink ( look, 1 ); look=nextLook; } #ifdef SMALL_PERMUTE if (numberGoodU_numberSlacks_+(numberRows_>>3)) { CoinSimplexInt * COIN_RESTRICT fromBigToSmallRow=reinterpret_cast(workArea_.array()); CoinSimplexInt * COIN_RESTRICT fromBigToSmallColumn=fromBigToSmallRow+numberRows_; int nSmall=0; for (int i=0;i=0&&bigRow=0&&bigColumnlastCountAddress_; CoinAbcMemcpy(temp,nextCount,numberRows_+numberRowsSmall_); for (int iCount=0;iCount<=nSmall;iCount++) { CoinSimplexInt nextBig=firstCount[iCount]; if (nextBig>=0) { //CoinSimplexInt next=firstCount[iCount]; CoinSimplexInt nextSmall; if (nextBig=0) { CoinSimplexInt thisSmall=nextSmall; nextBig=temp[nextBig]; if (nextBig>=0) { if (nextBig=0); // fill in odd one *where=iCount-numberRows_-2; } } //printf("%d rows small1 %d small2 %d\n",numberRows_,numberRowsSmall_,nSmall); numberRowsSmall_=nSmall; //exit(0); } #endif // Put .hpp functions in separate file for profiling #ifdef PRINT_INVERT_STATS int numberGoodUY=numberGoodU_; int numberElsLeftX=0; for (int i=0;i=0) { if (look2==numberRows_+1919) { printf("*** 1919 on list of count %d\n",count); abort(); } look2 = nextCount[look2]; } } #endif //printf("At count %d look %d\n",count,look); CoinSimplexInt trials = 0; //CoinSimplexInt * COIN_RESTRICT pivotColumn = pivotColumnAddress_; while ( look >= 0 ) { checkLinks(1); if ( look < numberRows_ ) { CoinSimplexInt iRow = look; look = nextCount[look]; bool rejected = false; CoinBigIndex start = startRow[iRow]; CoinBigIndex end = start + count; CoinBigIndex i; for ( i = start; i < end; i++ ) { CoinSimplexInt iColumn = indexColumn[i]; assert (numberInColumn[iColumn]>0); CoinFactorizationDouble cost = ( count - 1 ) * numberInColumn[iColumn] + 0.1; if ( cost < minimumCost ) { CoinBigIndex where = startColumn[iColumn]; double minimumValue = element[where]; minimumValue = fabs ( minimumValue ) * pivotTolerance; if (count==1) minimumValue=CoinMin(minimumValue,0.999999); while ( indexRow[where] != iRow ) { where++; } /* endwhile */ assert ( where < startColumn[iColumn] + numberInColumn[iColumn]); CoinFactorizationDouble value = element[where]; value = fabs ( value ); if ( value >= minimumValue ) { minimumCost = cost; minimumCount = numberInColumn[iColumn]; iPivotRow = iRow; pivotRowPosition = -1; iPivotColumn = iColumn; assert (iPivotRow>=0&&iPivotColumn>=0); pivotColumnPosition = i; rejected=false; } else if ( iPivotRow == -1 && count > 1) { rejected = true; } } } trials++; if ( iPivotRow >= 0 && (trials >= numberTrials||minimumCount= minimumValue ) { CoinSimplexInt iRow = indexRow[i]; CoinSimplexInt nInRow = numberInRow[iRow]; assert (nInRow>0); CoinFactorizationDouble cost = ( count - 1 ) * nInRow; if ( cost < minimumCost ) { minimumCost = cost; minimumCount = nInRow; iPivotRow = iRow; pivotRowPosition = i; iPivotColumn = iColumn; assert (iPivotRow>=0&&iPivotColumn>=0); pivotColumnPosition = -1; } } } trials++; if ( iPivotRow >= 0 && (trials >= numberTrials||minimumCount=0) { assert (iPivotRow5887) { int start=startRow[1181]; int end=start+numberInRow[1181]; for (int i=start;i 0 ) { if ( numberDoRow > 0 ) { if ( numberDoColumn > 1 ) { // if (1) { //need to adjust more for cache and SMP //allow at least 4 extra CoinSimplexInt increment = numberDoColumn + 1 + 4; if ( increment & 15 ) { increment = increment & ( ~15 ); increment += 16; } CoinSimplexInt increment2 = ( increment + COINFACTORIZATION_BITS_PER_INT - 1 ) >> COINFACTORIZATION_SHIFT_PER_INT; CoinBigIndex size = increment2 * numberDoRow; if ( size > workSize ) { workSize = size; workArea2_.conditionalNew(workSize); workArea2Address_=workArea2_.array(); workArea2 = workArea2Address_; } //branch out to best pivot routine #define ABC_PARALLEL_PIVOT #ifndef ABC_USE_FUNCTION_POINTERS #undef ABC_PARALLEL_PIVOT #endif #ifdef ABC_PARALLEL_PIVOT //if (numberRowsSmall_==7202&&numberGoodU_==15609) { //printf("NumberGoodU %d\n",numberGoodU_); //} if (numberDoRow<20) status = pivot ( iPivotRow, iPivotColumn, pivotRowPosition, pivotColumnPosition, workArea, workArea2, increment2, markRow ); else status = pivot ( iPivotRow, iPivotColumn, pivotRowPosition, pivotColumnPosition, markRow ); #else status = pivot ( iPivotRow, iPivotColumn, pivotRowPosition, pivotColumnPosition, workArea, workArea2, increment2, markRow ); #endif #if 0 for (int i=0;ilargestU) { iU=i; jU=j; largestU=fabs(element[j]); } } } printf("%d largest el %g at i=%d,j=%d start %d end %d count %d\n",numberGoodU_,element[jU], iU,jU,startColumn[iU],startColumn[iU]+numberInColumn[iU],count); } #endif #undef CHECK_SIZE checkLinks(); if ( status < 0) { count=numberRows_+1; break; } } else { if ( !pivotOneOtherRow ( iPivotRow, iPivotColumn ) ) { status = -99; count=numberRows_+1; break; } #ifdef CHECK_SIZE { double largestU=0.0; int iU=-1; int jU=-1; for (int i=0;ilargestU) { iU=i; jU=j; largestU=fabs(element[j]); } } } printf("B%d largest el %g at i=%d,j=%d\n",numberGoodU_,element[jU], iU,jU); } #endif checkLinks(); } } else { assert (!numberDoRow); checkLinks(); if ( !pivotRowSingleton ( iPivotRow, iPivotColumn ) ) { status = -99; count=numberRows_+1; break; } #ifdef CHECK_SIZE { double largestU=0.0; int iU=-1; int jU=-1; for (int i=0;ilargestU) { iU=i; jU=j; largestU=fabs(element[j]); } } } printf("C%d largest el %g at i=%d,j=%d\n",numberGoodU_,element[jU], iU,jU); } #endif checkLinks(); } } else { assert (!numberDoColumn); pivotColumnSingleton ( iPivotRow, iPivotColumn ); #ifdef CHECK_SIZE { double largestU=0.0; int iU=-1; int jU=-1; for (int i=0;ilargestU) { iU=i; jU=j; largestU=fabs(element[j]); } } } printf("D%d largest el %g at i=%d,j=%d\n",numberGoodU_,element[jU], iU,jU); } #endif checkLinks(); } double pivotValue=fabs(pivotRegion[numberGoodU_]); #if ABC_NORMAL_DEBUG>0 largestPivot=CoinMax(largestPivot,pivotValue); smallestPivot=CoinMin(smallestPivot,pivotValue); #endif if (pivotValue0 printf("PPPivot value of %g increasing pivot tolerance to %g\n", pivotValue,pivotTolerance_); #endif status=-97; break; } } afterPivot(iPivotRow,iPivotColumn); assert (numberGoodU_<=numberRows_); assert(startRow[numberRows_]==lengthAreaU_); #if 0 static int ixxxxxx=0; { int nLeft=0; for (int i=0;i=2744) { printf("Bad column %d at %d\n",iColumn,i); bad=true; } else if (cols[iColumn]>=0) { printf("Duplicate column %d at %d was at %d\n",iColumn,i,cols[iColumn]); bad=true; } else { cols[iColumn]=i; } } #else { int n=numberInRow[1160]; int start = startRow[1160]; int end=start+n; for (int i=start;inumberRows_-numberGoodU_) { printf("numberGoodU %d nrow-ngood %d\n",numberGoodU_,numberRows_-numberGoodU_); abort(); } if (ixxxxxx==2198||ixxxxxx==1347) { printf("Trouble ahead\n"); } #else if (ixxxxxx==1756) { printf("Trouble ahead\n"); } #endif } #endif #if ABC_DENSE_CODE if (!status) { status=wantToGoDense(); } #endif if (status) break; // start at 1 again count = 1; } else { //end of this - onto next count++; } } /* endwhile */ #if ABC_NORMAL_DEBUG>0 #if ABC_SMALL<2 int lenU=2*(lastEntryByColumnUPlus_/3); printf("largest initial element %g, smallestPivot %g largest %g (%d dense rows) - %d in L, %d in U\n", 1.0e-10/initialLargest,smallestPivot,largestPivot,numberRows_-numberGoodU_, lengthL_,lenU); #endif #endif workArea2_.conditionalDelete() ; workArea2Address_=NULL; #ifdef PRINT_INVERT_STATS int numberDense=numberRows_-numberGoodU_; printf("XX %d rows, %d in bump (%d slacks,%d triangular), % d dense - startels %d (%d) now %d - taken out of uspace (triang) %d\n", numberRows_,numberRows_-numberGoodUY,numberGoodUX,numberGoodUY-numberGoodUX, numberDense,numberElsLeftX,saveN1X,totalElements_,numberTakenOutOfUSpace); #endif return status; } #if ABC_DENSE_CODE //:method factorDense. Does dense phase of factorization //return code is <0 error, 0= finished CoinSimplexInt CoinAbcTypeFactorization::factorDense() { CoinSimplexInt status=0; numberDense_=numberRows_-numberGoodU_; if (sizeof(CoinBigIndex)==4&&numberDense_>=(2<<15)) { abort(); } CoinBigIndex full; full = numberDense_*numberDense_; totalElements_=full; // Add coding to align an object #if ABC_DENSE_CODE==1 leadingDimension_=((numberDense_>>4)+1)<<4; #else leadingDimension_=numberDense_; #endif CoinBigIndex newSize=(leadingDimension_+FACTOR_CPU)*numberDense_; newSize += (numberDense_+1)/(sizeof(CoinFactorizationDouble)/sizeof(CoinSimplexInt)); #if 1 newSize += 2*((numberDense_+3)/(sizeof(CoinFactorizationDouble)/sizeof(short))); newSize += ((numberRows_+3)/(sizeof(CoinFactorizationDouble)/sizeof(short))); // so we can align on 256 byte newSize+=32; //newSize += (numberDense_+1)/(sizeof(CoinFactorizationDouble)/sizeof(CoinSimplexInt)); #endif #ifdef SMALL_PERMUTE // densePermute has fromSmallToBig!!! CoinSimplexInt * COIN_RESTRICT fromSmallToBigRow=reinterpret_cast(workArea_.array()); CoinSimplexInt * COIN_RESTRICT fromSmallToBigColumn = fromSmallToBigRow+numberRowsSmall_; CoinAbcMemcpy(fromSmallToBigRow,fromSmallToBigRow_,numberRowsSmall_); CoinAbcMemcpy(fromSmallToBigColumn,fromSmallToBigColumn_,numberRowsSmall_); #endif denseArea_.conditionalDelete(); denseArea_.conditionalNew( newSize ); denseAreaAddress_=denseArea_.array(); CoinInt64 xx = reinterpret_cast(denseAreaAddress_); int iBottom = static_cast(xx & 63); int offset = (256-iBottom)>>3; denseAreaAddress_ += offset; CoinFactorizationDouble * COIN_RESTRICT denseArea = denseAreaAddress_; CoinZeroN(denseArea,newSize-32); CoinSimplexInt * COIN_RESTRICT densePermute= reinterpret_cast(denseArea+(leadingDimension_+FACTOR_CPU)*numberDense_); #if ABC_DENSE_CODE<0 CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif //mark row lookup using lastRow CoinSimplexInt i; CoinSimplexInt * COIN_RESTRICT lastRow = lastRowAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; #if 0 char xxx[17000]; assert (numberRows_<=17000); memset(xxx,0,numberRows_); int nLeft=0; for (i=0;i=0) { xxx[i]=1; } else { nLeft++; } } printf("%d rows left\n",nLeft); bool bad=false; for (i=0;i=0) { lastRow[i]=0; printf("dense row %d translates to %d permute %d\n",i,iBigRow,permuteAddress_[iBigRow]); } else { if (permuteAddress_[iBigRow]<0) printf("sparse row %d translates to %d permute %d\n",i,iBigRow,permuteAddress_[iBigRow]); if (xxx[iBigRow]!=1) bad=true; xxx[iBigRow]=0; } } if (bad) abort(); #else for (i=0;i=0) { lastRow[i]=0; } } #endif CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt which=0; for (i=0;i0) abort(); //} //for L part CoinBigIndex * COIN_RESTRICT startColumnL = startColumnLAddress_; #if ABC_DENSE_CODE<0 CoinFactorizationDouble * COIN_RESTRICT elementL = elementLAddress_; CoinSimplexInt * COIN_RESTRICT indexRowL = indexRowLAddress_; #endif CoinBigIndex endL=startColumnL[numberGoodL_]; //take out of U CoinFactorizationDouble * COIN_RESTRICT column = denseArea; CoinSimplexInt rowsDone=0; CoinSimplexInt iColumn=0; CoinSimplexInt * COIN_RESTRICT pivotColumn = pivotColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinBigIndex * startColumnU = startColumnUAddress_; #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; #endif CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif #if ABC_DENSE_CODE==2 int nDense=0; #endif for (iColumn=0;iColumn=0&&iRow>3; #elif BLOCKING8==4 int iBlock=iRow>>2; #elif BLOCKING8==2 int iBlock=iRow>>1; #else abort(); #endif iRow=iRow&(BLOCKING8-1); column[iRow+BLOCKING8X8*iBlock]=element[i]; #endif } /* endfor */ #if ABC_DENSE_CODE!=2 column+=leadingDimension_; #else if ((nDense&(BLOCKING8-1))!=0) column += BLOCKING8; else column += leadingDimension_*BLOCKING8-(BLOCKING8-1)*BLOCKING8; #endif while (lastRow[rowsDone]<0) { rowsDone++; } /* endwhile */ #ifdef ABC_USE_FUNCTION_POINTERS int numberIn = numberInColumnPlus[iColumn]; #ifdef SMALL_PERMUTE int realRowsDone=fromSmallToBigRow[rowsDone]; #if ABC_USE_FUNCTION_POINTERS if (numberIn<9) { scatter[realRowsDone].functionPointer=AbcScatterLowSubtract[numberIn]; } else { scatter[realRowsDone].functionPointer=AbcScatterHighSubtract[numberIn&3]; } #endif scatter[realRowsDone].offset=lastEntryByColumnUPlus_; scatter[realRowsDone].number=numberIn; #else #if ABC_USE_FUNCTION_POINTERS if (numberIn<9) { scatter[rowsDone].functionPointer=AbcScatterLowSubtract[numberIn]; } else { scatter[rowsDone].functionPointer=AbcScatterHighSubtract[numberIn&3]; } #endif scatter[rowsDone].offset=lastEntryByColumnUPlus_; scatter[rowsDone].number=numberIn; #endif CoinBigIndex startC = start-numberIn; for (int i=startC;i(elementUColumnPlus+lastEntryByColumnUPlus_),indexRow+startC,numberIn); lastEntryByColumnUPlus_ += (numberIn+1)>>1; #endif #ifdef SMALL_PERMUTE permuteAddress_[realRowsDone]=numberGoodU_; pivotColumn[numberGoodU_]=fromSmallToBigColumn[iColumn]; #else permuteAddress_[rowsDone]=numberGoodU_; pivotColumn[numberGoodU_]=iColumn; #endif rowsDone++; startColumnL[numberGoodU_+1]=endL; numberInColumn[iColumn]=0; pivotRegion[numberGoodU_]=1.0; numberGoodU_++; } } #if ABC_DENSE_CODE>0 //printf("Going dense at %d\n",numberDense_); if (denseThreshold_>0) { if(numberGoodU_!=numberRows_) return -1; // something odd numberGoodL_=numberRows_; //now factorize //dgef(denseArea,&numberDense_,&numberDense_,densePermute); #if ABC_DENSE_CODE!=2 #ifndef CLAPACK CoinSimplexInt info; F77_FUNC(dgetrf,DGETRF)(&numberDense_,&numberDense_,denseArea,&leadingDimension_,densePermute, &info); // need to check size of pivots if(info) status = -1; #else status = clapack_dgetrf(CblasColMajor, numberDense_,numberDense_, denseArea, leadingDimension_,densePermute); assert (!status); #endif #else status=CoinAbcDgetrf(numberDense_,numberDense_,denseArea,numberDense_,densePermute #if ABC_PARALLEL==2 ,parallelMode_ #endif ); if (status) { status=-1; printf("singular in dense\n"); } #endif return status; } #else numberGoodU_ = numberRows_-numberDense_; CoinSimplexInt base = numberGoodU_; CoinSimplexInt iDense; CoinSimplexInt numberToDo=numberDense_; denseThreshold_=-abs(denseThreshold_); //0; CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; const CoinSimplexInt * COIN_RESTRICT pivotColumnConst = pivotColumnAddress_; // make sure we have enough space in L and U for (iDense=0;iDense space ) { //getColumnSpace also moves fixed part if ( !getColumnSpace ( iColumn, numberInPivotColumn ) ) { return -99; } } // set so further moves will work numberInColumn[iColumn]=numberInPivotColumn; } // Fill in ? for (iColumn=numberGoodU_+numberToDo;iColumn lengthAreaL_ ) { //need more memory if ((messageLevel_&4)!=0) std::cout << "more memory needed in middle of invert" << std::endl; return -99; } CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinSimplexInt * COIN_RESTRICT ipiv = densePermute-numberDense_; int returnCode=CoinAbcDgetrf(numberDense_,numberDense_,denseArea,numberDense_,ipiv); if (!returnCode) { CoinSimplexDouble * COIN_RESTRICT element = denseArea; for (int iDense=0;iDensenextCountAddress_; CoinSimplexInt * COIN_RESTRICT firstCount = this->firstCountAddress_; CoinSimplexInt * COIN_RESTRICT lastCount = this->lastCountAddress_; CoinSimplexInt next = firstCount[count]; CoinSimplexInt firstRow=-1; CoinSimplexInt firstColumn=-1; CoinSimplexInt lastRow=-1; CoinSimplexInt lastColumn=-1; while(next>=0) { CoinSimplexInt next2=nextCount[next]; if (next>=numberRows_) { nextCount[next]=-1; // Column if (firstColumn>=0) { lastCount[next]=lastColumn; nextCount[lastColumn]=next; } else { lastCount[next]= -2 - count; firstColumn=next; } lastColumn=next; } else { // Row if (firstRow>=0) { lastCount[next]=lastRow; nextCount[lastRow]=next; } else { lastCount[next]= -2 - count; firstRow=next; } lastRow=next; } next=next2; } if (firstRow>=0) { firstCount[count]=firstRow; nextCount[lastRow]=firstColumn; if (firstColumn>=0) lastCount[firstColumn]=lastRow; } else if (firstRow<0) { firstCount[count]=firstColumn; } else if (firstColumn>=0) { firstCount[count]=firstColumn; nextCount[lastColumn]=firstRow; if (firstRow>=0) lastCount[firstRow]=lastColumn; } } #endif #endif Clp-1.15.10/src/ClpCholeskyMumps.hpp0000644000076600007660000000417511534475515015636 0ustar coincoin/* $Id: ClpCholeskyMumps.hpp 1692 2011-03-05 18:05:01Z stefan $ */ // 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 ClpCholeskyMumps_H #define ClpCholeskyMumps_H #include "ClpCholeskyBase.hpp" class ClpMatrixBase; class ClpCholeskyDense; // unfortunately, DMUMPS_STRUC_C is an anonymous struct in MUMPS, so we define it to void for everyone outside ClpCholeskyMumps // if this file is included by ClpCholeskyMumps.cpp, then after dmumps_c.h has been included, which defines MUMPS_VERSION #ifndef MUMPS_VERSION typedef void DMUMPS_STRUC_C; #endif /** Mumps class for Clp Cholesky factorization */ class ClpCholeskyMumps : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ //@{ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /** Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const double * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (double * region) ; //@} /**@name Constructors, destructor */ //@{ /** Constructor which has dense columns activated. Default is off. */ ClpCholeskyMumps(int denseThreshold = -1); /** Destructor */ virtual ~ClpCholeskyMumps(); /// Clone virtual ClpCholeskyBase * clone() const ; //@} private: // Mumps structure DMUMPS_STRUC_C* mumps_; // Copy ClpCholeskyMumps(const ClpCholeskyMumps&); // Assignment ClpCholeskyMumps& operator=(const ClpCholeskyMumps&); }; #endif Clp-1.15.10/src/ClpCholeskyWssmp.cpp0000644000076600007660000006236111552601036015627 0ustar coincoin/* $Id: ClpCholeskyWssmp.cpp 1723 2011-04-17 15:07:10Z forrest $ */ // 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). #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpCholeskyWssmp.hpp" #include "ClpCholeskyDense.hpp" #include "ClpMessage.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpCholeskyWssmp::ClpCholeskyWssmp (int denseThreshold) : ClpCholeskyBase(denseThreshold) { type_ = 12; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyWssmp::ClpCholeskyWssmp (const ClpCholeskyWssmp & rhs) : ClpCholeskyBase(rhs) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpCholeskyWssmp::~ClpCholeskyWssmp () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyWssmp & ClpCholeskyWssmp::operator=(const ClpCholeskyWssmp& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpCholeskyBase * ClpCholeskyWssmp::clone() const { return new ClpCholeskyWssmp(*this); } // At present I can't get wssmp to work as my libraries seem to be out of sync // so I have linked in ekkwssmp which is an older version #ifndef USE_EKKWSSMP extern "C" { void F77_FUNC(wsetmaxthrds,WSETMAXTHRDS)(const int* NTHREADS); void F77_FUNC(wssmp,WSSMP)(const int* N, const int* IA, const int* JA, const double* AVALS, double* DIAG, int* PERM, int* INVP, double* B, const int* LDB, const int* NRHS, double* AUX, const int* NAUX, int* MRP, int* IPARM, double* DPARM); void F77_FUNC_(wsmp_clear,WSMP_CLEAR)(void); } #else /* minimum needed for user */ typedef struct EKKModel EKKModel; typedef struct EKKContext EKKContext; extern "C" { EKKContext * ekk_initializeContext(); void ekk_endContext(EKKContext * context); EKKModel * ekk_newModel(EKKContext * env, const char * name); int ekk_deleteModel(EKKModel * model); } static EKKModel * model = NULL; static EKKContext * context = NULL; extern "C" void ekkwssmp(EKKModel *, int * n, int * columnStart , int * rowIndex , double * element, double * diagonal , int * perm , int * invp , double * rhs , int * ldb , int * nrhs , double * aux , int * naux , int * mrp , int * iparm , double * dparm); static void F77_FUNC(wssmp,WSSMP)( int *n, int *ia, int *ja, double *avals, double *diag, int *perm, int *invp, double *b, int *ldb, int *nrhs, double *aux, int * naux, int *mrp, int *iparm, double *dparm) { if (!context) { /* initialize OSL environment */ context = ekk_initializeContext(); model = ekk_newModel(context, ""); } ekkwssmp(model, n, ia, ja, avals, diag, perm, invp, b, ldb, nrhs, aux, naux, mrp, iparm, dparm); //ekk_deleteModel(model); //ekk_endContext(context); } #endif /* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyWssmp::order(ClpInterior * model) { numberRows_ = model->numberRows(); rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopy_ = model->clpMatrix()->reverseOrderedCopy(); // Space for starts choleskyStart_ = new CoinBigIndex[numberRows_+1]; const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_+1]; CoinZeroN(used, numberRows_); int iRow; sizeFactor_ = 0; int numberColumns = model->numberColumns(); int numberDense = 0; if (denseThreshold_ > 0) { delete [] whichDense_; delete [] denseColumn_; delete dense_; whichDense_ = new char[numberColumns]; int iColumn; used[numberRows_] = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int length = columnLength[iColumn]; used[length] += 1; } int nLong = 0; int stop = CoinMax(denseThreshold_ / 2, 100); for (iRow = numberRows_; iRow >= stop; iRow--) { if (used[iRow]) COIN_DETAIL_PRINT(printf("%d columns are of length %d\n", used[iRow], iRow)); nLong += used[iRow]; if (nLong > 50 || nLong > (numberColumns >> 2)) break; } CoinZeroN(used, numberRows_); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnLength[iColumn] < denseThreshold_) { whichDense_[iColumn] = 0; } else { whichDense_[iColumn] = 1; numberDense++; } } if (!numberDense || numberDense > 100) { // free delete [] whichDense_; whichDense_ = NULL; denseColumn_ = NULL; dense_ = NULL; } else { // space for dense columns denseColumn_ = new double [numberDense*numberRows_]; // dense cholesky dense_ = new ClpCholeskyDense(); dense_->reserveSpace(NULL, numberDense); COIN_DETAIL_PRINT(printf("Taking %d columns as dense\n", numberDense)); } } for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in try { choleskyRow_ = new int [sizeFactor_]; } catch (...) { // no memory delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } try { sparseFactor_ = new double[sizeFactor_]; } catch (...) { // no memory delete [] choleskyRow_; choleskyRow_ = NULL; delete [] choleskyStart_; choleskyStart_ = NULL; return -1; } sizeFactor_ = 0; which = choleskyRow_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStart_[iRow] = sizeFactor_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } } sizeFactor_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStart_[numberRows_] = sizeFactor_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; integerParameters_[0] = 0; int i0 = 0; int i1 = 1; #ifndef USE_EKKWSSMP int i2 = 1; if (model->numberThreads() <= 0) i2 = 1; else i2 = model->numberThreads(); F77_FUNC(wsetmaxthrds,WSETMAXTHRDS)(&i2); #endif F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, 0, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); integerParameters_[1] = 1; //order and symbolic integerParameters_[2] = 2; integerParameters_[3] = 0; //CSR integerParameters_[4] = 0; //C style integerParameters_[13] = 1; //reuse initial factorization space integerParameters_[15+0] = 1; //ordering integerParameters_[15+1] = 0; integerParameters_[15+2] = 1; integerParameters_[15+3] = 0; integerParameters_[15+4] = 1; doubleParameters_[10] = 1.0e-20; doubleParameters_[11] = 1.0e-15; F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); //std::cout<<"Ordering and symbolic factorization took "<gamma() && !model->delta()) { model->setGamma(5.0e-5); model->setDelta(5.0e-5); } std::cout << integerParameters_[23] << " elements in sparse Cholesky" << std::endl; if (!integerParameters_[23]) { for (int iRow = 0; iRow < numberRows_; iRow++) { permuteInverse_[iRow] = iRow; permute_[iRow] = iRow; } std::cout << "wssmp says no elements - fully dense? - switching to dense" << std::endl; integerParameters_[1] = 2; integerParameters_[2] = 2; integerParameters_[7] = 1; // no permute F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); std::cout << integerParameters_[23] << " elements in dense Cholesky" << std::endl; } return 0; } /* Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ int ClpCholeskyWssmp::symbolic() { return 0; } /* Factorize - filling in rowsDropped and returning number dropped */ int ClpCholeskyWssmp::factorize(const double * diagonal, int * rowsDropped) { const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const double * element = model_->clpMatrix()->getElements(); const CoinBigIndex * rowStart = rowCopy_->getVectorStarts(); const int * rowLength = rowCopy_->getVectorLengths(); const int * column = rowCopy_->getIndices(); const double * elementByRow = rowCopy_->getElements(); int numberColumns = model_->clpMatrix()->getNumCols(); int iRow; double * work = new double[numberRows_]; CoinZeroN(work, numberRows_); const double * diagonalSlack = diagonal + numberColumns; int newDropped = 0; double largest; double smallest; int numberDense = 0; if (dense_) numberDense = dense_->numberRows(); //perturbation double perturbation = model_->diagonalPerturbation() * model_->diagonalNorm(); perturbation = perturbation * perturbation; if (perturbation > 1.0) { #ifdef COIN_DEVELOP //if (model_->model()->logLevel()&4) std::cout << "large perturbation " << perturbation << std::endl; #endif perturbation = sqrt(perturbation);; perturbation = 1.0; } if (whichDense_) { double * denseDiagonal = dense_->diagonal(); double * dense = denseColumn_; int iDense = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (whichDense_[iColumn]) { denseDiagonal[iDense++] = 1.0 / diagonal[iColumn]; CoinZeroN(dense, numberRows_); CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; dense[jRow] = element[j]; } dense += numberRows_; } } } double delta2 = model_->delta(); // add delta*delta to diagonal delta2 *= delta2; for (iRow = 0; iRow < numberRows_; iRow++) { double * put = sparseFactor_ + choleskyStart_[iRow]; int * which = choleskyRow_ + choleskyStart_[iRow]; int number = choleskyStart_[iRow+1] - choleskyStart_[iRow]; if (!rowLength[iRow]) rowsDropped_[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; work[iRow] = diagonalSlack[iRow] + delta2; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; if (!whichDense_ || !whichDense_[iColumn]) { CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; double multiplier = diagonal[iColumn] * elementByRow[k]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { double value = element[j] * multiplier; work[jRow] += value; } } } } int j; for (j = 0; j < number; j++) { int jRow = which[j]; put[j] = work[jRow]; work[jRow] = 0.0; } } else { // dropped int j; for (j = 1; j < number; j++) { put[j] = 0.0; } put[0] = 1.0; } } //check sizes double largest2 = maximumAbsElement(sparseFactor_, sizeFactor_); largest2 *= 1.0e-20; largest = CoinMin(largest2, 1.0e-11); int numberDroppedBefore = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int dropped = rowsDropped_[iRow]; // Move to int array rowsDropped[iRow] = dropped; if (!dropped) { CoinBigIndex start = choleskyStart_[iRow]; double diagonal = sparseFactor_[start]; if (diagonal > largest2) { sparseFactor_[start] = diagonal + perturbation; } else { sparseFactor_[start] = diagonal + perturbation; rowsDropped[iRow] = 2; numberDroppedBefore++; } } } int i1 = 1; int i0 = 0; integerParameters_[1] = 3; integerParameters_[2] = 3; integerParameters_[10] = 2; //integerParameters_[11]=1; integerParameters_[12] = 2; doubleParameters_[10] = CoinMax(1.0e-20, largest); if (doubleParameters_[10] > 1.0e-3) integerParameters_[9] = 1; else integerParameters_[9] = 0; F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, NULL, &numberRows_, &i1, NULL, &i0, rowsDropped, integerParameters_, doubleParameters_); //std::cout<<"factorization took "<messageHandler()->logLevel() > 1) std::cout << "Cholesky - largest " << largest << " smallest " << smallest << std::endl; choleskyCondition_ = largest / smallest; if (integerParameters_[63] < 0) return -1; // out of memory if (whichDense_) { // Update dense columns (just L) // Zero out dropped rows int i; for (i = 0; i < numberDense; i++) { double * a = denseColumn_ + i * numberRows_; for (int j = 0; j < numberRows_; j++) { if (rowsDropped[j]) a[j] = 0.0; } } integerParameters_[29] = 1; int i0 = 0; integerParameters_[1] = 4; integerParameters_[2] = 4; F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, denseColumn_, &numberRows_, &numberDense, NULL, &i0, NULL, integerParameters_, doubleParameters_); integerParameters_[29] = 0; dense_->resetRowsDropped(); longDouble * denseBlob = dense_->aMatrix(); double * denseDiagonal = dense_->diagonal(); // Update dense matrix for (i = 0; i < numberDense; i++) { const double * a = denseColumn_ + i * numberRows_; // do diagonal double value = denseDiagonal[i]; const double * b = denseColumn_ + i * numberRows_; for (int k = 0; k < numberRows_; k++) value += a[k] * b[k]; denseDiagonal[i] = value; for (int j = i + 1; j < numberDense; j++) { double value = 0.0; const double * b = denseColumn_ + j * numberRows_; for (int k = 0; k < numberRows_; k++) value += a[k] * b[k]; *denseBlob = value; denseBlob++; } } // dense cholesky (? long double) int * dropped = new int [numberDense]; dense_->factorizePart2(dropped); delete [] dropped; } bool cleanCholesky; if (model_->numberIterations() < 2000) cleanCholesky = true; else cleanCholesky = false; if (cleanCholesky) { //drop fresh makes some formADAT easier //int oldDropped=numberRowsDropped_; if (newDropped || numberRowsDropped_) { //std::cout <<"Rank "<oldDropped) //std::cout<<" ( "<(rowsDropped[i]); rowsDropped_[i] = dropped; rowsDropped_[i] = 0; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 0; } } numberRowsDropped_ = newDropped; newDropped = -(2 + newDropped); } } else { if (newDropped) { newDropped = 0; for (int i = 0; i < numberRows_; i++) { char dropped = static_cast(rowsDropped[i]); rowsDropped_[i] = dropped; if (dropped == 2) { //dropped this time rowsDropped[newDropped++] = i; rowsDropped_[i] = 1; } } } numberRowsDropped_ += newDropped; if (numberRowsDropped_ && 0) { std::cout << "Rank " << numberRows_ - numberRowsDropped_ << " ( " << numberRowsDropped_ << " dropped)"; if (newDropped) { std::cout << " ( " << newDropped << " dropped this time)"; } std::cout << std::endl; } } status_ = 0; return newDropped; } /* Uses factorization to solve. */ void ClpCholeskyWssmp::solve (double * region) { int i1 = 1; int i0 = 0; integerParameters_[1] = 4; integerParameters_[2] = 4; #if 1 integerParameters_[5] = 3; doubleParameters_[5] = 1.0e-10; integerParameters_[6] = 6; #endif if (!whichDense_) { F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, region, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); } else { // dense columns integerParameters_[29] = 1; F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, region, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); // do change; int numberDense = dense_->numberRows(); double * change = new double[numberDense]; int i; for (i = 0; i < numberDense; i++) { const double * a = denseColumn_ + i * numberRows_; double value = 0.0; for (int iRow = 0; iRow < numberRows_; iRow++) value += a[iRow] * region[iRow]; change[i] = value; } // solve dense_->solve(change); for (i = 0; i < numberDense; i++) { const double * a = denseColumn_ + i * numberRows_; double value = change[i]; for (int iRow = 0; iRow < numberRows_; iRow++) region[iRow] -= value * a[iRow]; } delete [] change; // and finish off integerParameters_[29] = 2; integerParameters_[1] = 4; F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, region, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); integerParameters_[29] = 0; } #if 0 if (integerParameters_[5]) { std::cout << integerParameters_[5] << " refinements "; } std::cout << doubleParameters_[6] << std::endl; #endif } Clp-1.15.10/src/CoinAbcFactorization5.cpp0000644000076600007660000000102012101105055016445 0ustar coincoin/* $Id: CoinAbcFactorization5.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #include "CoinAbcBaseFactorization5.cpp" #endif Clp-1.15.10/src/ClpDynamicExampleMatrix.cpp0000644000076600007660000007150712131314313017074 0ustar coincoin/* $Id: ClpDynamicExampleMatrix.cpp 1941 2013-04-10 16:52:27Z 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 "CoinPragma.hpp" #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpFactorization.hpp" #include "ClpQuadraticObjective.hpp" #include "ClpNonLinearCost.hpp" // at end to get min/max! #include "ClpDynamicExampleMatrix.hpp" #include "ClpMessage.hpp" //#define CLP_DEBUG //#define CLP_DEBUG_PRINT //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpDynamicExampleMatrix::ClpDynamicExampleMatrix () : ClpDynamicMatrix(), numberColumns_(0), startColumnGen_(NULL), rowGen_(NULL), elementGen_(NULL), costGen_(NULL), fullStartGen_(NULL), dynamicStatusGen_(NULL), idGen_(NULL), columnLowerGen_(NULL), columnUpperGen_(NULL) { setType(25); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpDynamicExampleMatrix::ClpDynamicExampleMatrix (const ClpDynamicExampleMatrix & rhs) : ClpDynamicMatrix(rhs) { numberColumns_ = rhs.numberColumns_; startColumnGen_ = ClpCopyOfArray(rhs.startColumnGen_, numberColumns_ + 1); CoinBigIndex numberElements = startColumnGen_[numberColumns_]; rowGen_ = ClpCopyOfArray(rhs.rowGen_, numberElements);; elementGen_ = ClpCopyOfArray(rhs.elementGen_, numberElements);; costGen_ = ClpCopyOfArray(rhs.costGen_, numberColumns_); fullStartGen_ = ClpCopyOfArray(rhs.fullStartGen_, numberSets_ + 1); dynamicStatusGen_ = ClpCopyOfArray(rhs.dynamicStatusGen_, numberColumns_); idGen_ = ClpCopyOfArray(rhs.idGen_, maximumGubColumns_); columnLowerGen_ = ClpCopyOfArray(rhs.columnLowerGen_, numberColumns_); columnUpperGen_ = ClpCopyOfArray(rhs.columnUpperGen_, numberColumns_); } /* This is the real constructor*/ ClpDynamicExampleMatrix::ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * columnLower, const double * columnUpper, const unsigned char * status, const unsigned char * dynamicStatus, int numberIds, const int *ids) : ClpDynamicMatrix(model, numberSets, 0, NULL, lower, upper, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) { setType(25); numberColumns_ = numberGubColumns; // start with safe values - then experiment maximumGubColumns_ = numberColumns_; maximumElements_ = startColumn[numberColumns_]; // delete odd stuff created by ClpDynamicMatrix constructor delete [] startSet_; startSet_ = new int [numberSets_]; delete [] next_; next_ = new int [maximumGubColumns_]; delete [] row_; delete [] element_; delete [] startColumn_; delete [] cost_; delete [] columnLower_; delete [] columnUpper_; delete [] dynamicStatus_; delete [] status_; delete [] id_; // and size correctly row_ = new int [maximumElements_]; element_ = new double [maximumElements_]; startColumn_ = new CoinBigIndex [maximumGubColumns_+1]; // say no columns yet numberGubColumns_ = 0; startColumn_[0] = 0; cost_ = new double[maximumGubColumns_]; dynamicStatus_ = new unsigned char [2*maximumGubColumns_]; memset(dynamicStatus_, 0, maximumGubColumns_); id_ = new int[maximumGubColumns_]; if (columnLower) columnLower_ = new double[maximumGubColumns_]; else columnLower_ = NULL; if (columnUpper) columnUpper_ = new double[maximumGubColumns_]; else columnUpper_ = NULL; // space for ids idGen_ = new int [maximumGubColumns_]; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) startSet_[iSet] = -1; // This starts code specific to this storage method CoinBigIndex i; fullStartGen_ = ClpCopyOfArray(starts, numberSets_ + 1); startColumnGen_ = ClpCopyOfArray(startColumn, numberColumns_ + 1); CoinBigIndex numberElements = startColumnGen_[numberColumns_]; rowGen_ = ClpCopyOfArray(row, numberElements); elementGen_ = new double[numberElements]; for (i = 0; i < numberElements; i++) elementGen_[i] = element[i]; costGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) { costGen_[i] = cost[i]; // I don't think I need sorted but ... CoinSort_2(rowGen_ + startColumnGen_[i], rowGen_ + startColumnGen_[i+1], elementGen_ + startColumnGen_[i]); } if (columnLower) { columnLowerGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) { columnLowerGen_[i] = columnLower[i]; if (columnLowerGen_[i]) { printf("Non-zero lower bounds not allowed - subtract from model\n"); abort(); } } } else { columnLowerGen_ = NULL; } if (columnUpper) { columnUpperGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) columnUpperGen_[i] = columnUpper[i]; } else { columnUpperGen_ = NULL; } // end specific coding if (columnUpper_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i = firstDynamic_; i < lastDynamic_; i++) columnUpper[i] = 1.0e10; } status_ = new unsigned char [2*numberSets_+4]; if (status) { memcpy(status_,status, numberSets_ * sizeof(char)); assert (dynamicStatus); CoinMemcpyN(dynamicStatus, numberIds, dynamicStatus_); assert (numberIds); } else { assert (!numberIds); memset(status_, 0, numberSets_); for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } } dynamicStatusGen_ = new unsigned char [numberColumns_]; memset(dynamicStatusGen_, 0, numberColumns_); // for clarity for (i = 0; i < numberColumns_; i++) setDynamicStatusGen(i, atLowerBound); // Populate with enough columns if (!numberIds) { // This could be made more sophisticated for (iSet = 0; iSet < numberSets_; iSet++) { int sequence = fullStartGen_[iSet]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, iSet, getDynamicStatusGen(sequence)); idGen_[iSet] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } } else { // put back old ones int * set = new int[numberColumns_]; for (iSet = 0; iSet < numberSets_; iSet++) { for (CoinBigIndex j = fullStartGen_[iSet]; j < fullStartGen_[iSet+1]; j++) set[j] = iSet; } for (int i = 0; i < numberIds; i++) { int sequence = ids[i]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, set[sequence], getDynamicStatus(i)); idGen_[iSet] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } delete [] set; } if (!status) { gubCrash(); } else { initialProblem(); } } #if 0 // This constructor just takes over ownership ClpDynamicExampleMatrix::ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, int * starts, const double * lower, const double * upper, int * startColumn, int * row, double * element, double * cost, double * columnLower, double * columnUpper, const unsigned char * status, const unsigned char * dynamicStatus, int numberIds, const int *ids) : ClpDynamicMatrix(model, numberSets, 0, NULL, lower, upper, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) { setType(25); numberColumns_ = numberGubColumns; // start with safe values - then experiment maximumGubColumns_ = numberColumns_; maximumElements_ = startColumn[numberColumns_]; // delete odd stuff created by ClpDynamicMatrix constructor delete [] startSet_; startSet_ = new int [numberSets_]; delete [] next_; next_ = new int [maximumGubColumns_]; delete [] row_; delete [] element_; delete [] startColumn_; delete [] cost_; delete [] columnLower_; delete [] columnUpper_; delete [] dynamicStatus_; delete [] status_; delete [] id_; // and size correctly row_ = new int [maximumElements_]; element_ = new double [maximumElements_]; startColumn_ = new CoinBigIndex [maximumGubColumns_+1]; // say no columns yet numberGubColumns_ = 0; startColumn_[0] = 0; cost_ = new double[maximumGubColumns_]; dynamicStatus_ = new unsigned char [2*maximumGubColumns_]; memset(dynamicStatus_, 0, maximumGubColumns_); id_ = new int[maximumGubColumns_]; if (columnLower) columnLower_ = new double[maximumGubColumns_]; else columnLower_ = NULL; if (columnUpper) columnUpper_ = new double[maximumGubColumns_]; else columnUpper_ = NULL; // space for ids idGen_ = new int [maximumGubColumns_]; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) startSet_[iSet] = -1; // This starts code specific to this storage method CoinBigIndex i; fullStartGen_ = starts; startColumnGen_ = startColumn; rowGen_ = row; elementGen_ = element; costGen_ = cost; for (i = 0; i < numberColumns_; i++) { // I don't think I need sorted but ... CoinSort_2(rowGen_ + startColumnGen_[i], rowGen_ + startColumnGen_[i+1], elementGen_ + startColumnGen_[i]); } if (columnLower) { columnLowerGen_ = columnLower; for (i = 0; i < numberColumns_; i++) { if (columnLowerGen_[i]) { printf("Non-zero lower bounds not allowed - subtract from model\n"); abort(); } } } else { columnLowerGen_ = NULL; } if (columnUpper) { columnUpperGen_ = columnUpper; } else { columnUpperGen_ = NULL; } // end specific coding if (columnUpper_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i = firstDynamic_; i < lastDynamic_; i++) columnUpper[i] = 1.0e10; } status_ = new unsigned char [2*numberSets_+4]; if (status) { memcpy(status_,status, numberSets_ * sizeof(char)); assert (dynamicStatus); CoinMemcpyN(dynamicStatus, numberIds, dynamicStatus_); assert (numberIds); } else { assert (!numberIds); memset(status_, 0, numberSets_); for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } } dynamicStatusGen_ = new unsigned char [numberColumns_]; memset(dynamicStatusGen_, 0, numberColumns_); // for clarity for (i = 0; i < numberColumns_; i++) setDynamicStatusGen(i, atLowerBound); // Populate with enough columns if (!numberIds) { // This could be made more sophisticated for (iSet = 0; iSet < numberSets_; iSet++) { int sequence = fullStartGen_[iSet]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, iSet, getDynamicStatusGen(sequence)); idGen_[iSet] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } } else { // put back old ones int * set = new int[numberColumns_]; for (iSet = 0; iSet < numberSets_; iSet++) { for (CoinBigIndex j = fullStartGen_[iSet]; j < fullStartGen_[iSet+1]; j++) set[j] = iSet; } for (int i = 0; i < numberIds; i++) { int sequence = ids[i]; int iSet = set[sequence]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, iSet, getDynamicStatus(i)); idGen_[i] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } delete [] set; } if (!status) { gubCrash(); } else { initialProblem(); } } #endif //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpDynamicExampleMatrix::~ClpDynamicExampleMatrix () { delete [] startColumnGen_; delete [] rowGen_; delete [] elementGen_; delete [] costGen_; delete [] fullStartGen_; delete [] dynamicStatusGen_; delete [] idGen_; delete [] columnLowerGen_; delete [] columnUpperGen_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpDynamicExampleMatrix & ClpDynamicExampleMatrix::operator=(const ClpDynamicExampleMatrix& rhs) { if (this != &rhs) { ClpDynamicMatrix::operator=(rhs); numberColumns_ = rhs.numberColumns_; delete [] startColumnGen_; delete [] rowGen_; delete [] elementGen_; delete [] costGen_; delete [] fullStartGen_; delete [] dynamicStatusGen_; delete [] idGen_; delete [] columnLowerGen_; delete [] columnUpperGen_; startColumnGen_ = ClpCopyOfArray(rhs.startColumnGen_, numberColumns_ + 1); CoinBigIndex numberElements = startColumnGen_[numberColumns_]; rowGen_ = ClpCopyOfArray(rhs.rowGen_, numberElements);; elementGen_ = ClpCopyOfArray(rhs.elementGen_, numberElements);; costGen_ = ClpCopyOfArray(rhs.costGen_, numberColumns_); fullStartGen_ = ClpCopyOfArray(rhs.fullStartGen_, numberSets_ + 1); dynamicStatusGen_ = ClpCopyOfArray(rhs.dynamicStatusGen_, numberColumns_); idGen_ = ClpCopyOfArray(rhs.idGen_, maximumGubColumns_); columnLowerGen_ = ClpCopyOfArray(rhs.columnLowerGen_, numberColumns_); columnUpperGen_ = ClpCopyOfArray(rhs.columnUpperGen_, numberColumns_); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpMatrixBase * ClpDynamicExampleMatrix::clone() const { return new ClpDynamicExampleMatrix(*this); } // Partial pricing void ClpDynamicExampleMatrix::partialPricing(ClpSimplex * model, double startFraction, double endFraction, int & bestSequence, int & numberWanted) { numberWanted = currentWanted_; assert(!model->rowScale()); if (!numberSets_) { // no gub ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); } else { // and do some proportion of full set int startG2 = static_cast (startFraction * numberSets_); int endG2 = static_cast (endFraction * numberSets_ + 0.1); endG2 = CoinMin(endG2, numberSets_); //printf("gub price - set start %d end %d\n", // startG2,endG2); double tolerance = model->currentDualTolerance(); double * reducedCost = model->djRegion(); const double * duals = model->dualRowSolution(); double bestDj; int numberRows = model->numberRows(); int slackOffset = lastDynamic_ + numberRows; int structuralOffset = slackOffset + numberSets_; int structuralOffset2 = structuralOffset + maximumGubColumns_; // If nothing found yet can go all the way to end int endAll = endG2; if (bestSequence < 0 && !startG2) endAll = numberSets_; if (bestSequence >= 0) { if (bestSequence != savedBestSequence_) bestDj = fabs(reducedCost[bestSequence]); // dj from slacks or permanent else bestDj = savedBestDj_; } else { bestDj = tolerance; } int saveSequence = bestSequence; double djMod = 0.0; double bestDjMod = 0.0; //printf("iteration %d start %d end %d - wanted %d\n",model->numberIterations(), // startG2,endG2,numberWanted); int bestSet = -1; int minSet = minimumObjectsScan_ < 0 ? 5 : minimumObjectsScan_; int minNeg = minimumGoodReducedCosts_ < 0 ? 5 : minimumGoodReducedCosts_; for (int iSet = startG2; iSet < endAll; iSet++) { if (numberWanted + minNeg < originalWanted_ && iSet > startG2 + minSet) { // give up numberWanted = 0; break; } else if (iSet == endG2 && bestSequence >= 0) { break; } int gubRow = toIndex_[iSet]; if (gubRow >= 0) { djMod = duals[gubRow+numberStaticRows_]; // have I got sign right? } else { int iBasic = keyVariable_[iSet]; if (iBasic >= numberColumns_) { djMod = 0.0; // set not in } else { // get dj without djMod = 0.0; for (CoinBigIndex j = startColumn_[iBasic]; j < startColumn_[iBasic+1]; j++) { int jRow = row_[j]; djMod -= duals[jRow] * element_[j]; } djMod += cost_[iBasic]; // See if gub slack possible - dj is djMod if (getStatus(iSet) == ClpSimplex::atLowerBound) { double value = -djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = slackOffset + iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } else if (getStatus(iSet) == ClpSimplex::atUpperBound) { double value = djMod; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSet)) { bestDj = value; bestSequence = slackOffset + iSet; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; abort(); } } } } } } // do ones in small int iSequence = startSet_[iSet]; while (iSequence >= 0) { DynamicStatus status = getDynamicStatus(iSequence); if (status == atLowerBound || status == atUpperBound) { double value = cost_[iSequence] - djMod; for (CoinBigIndex j = startColumn_[iSequence]; j < startColumn_[iSequence+1]; j++) { int jRow = row_[j]; value -= duals[jRow] * element_[j]; } // change sign if at lower bound if (status == atLowerBound) value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flagged(iSequence)) { bestDj = value; bestSequence = structuralOffset + iSequence; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; } } } } iSequence = next_[iSequence]; //onto next in set } // and now get best by column generation // If no upper bounds we may not need status test for (iSequence = fullStartGen_[iSet]; iSequence < fullStartGen_[iSet+1]; iSequence++) { DynamicStatus status = getDynamicStatusGen(iSequence); assert (status != atUpperBound && status != soloKey); if (status == atLowerBound) { double value = costGen_[iSequence] - djMod; for (CoinBigIndex j = startColumnGen_[iSequence]; j < startColumnGen_[iSequence+1]; j++) { int jRow = rowGen_[j]; value -= duals[jRow] * elementGen_[j]; } // change sign as at lower bound value = -value; if (value > tolerance) { numberWanted--; if (value > bestDj) { // check flagged variable and correct dj if (!flaggedGen(iSequence)) { bestDj = value; bestSequence = structuralOffset2 + iSequence; bestDjMod = djMod; bestSet = iSet; } else { // just to make sure we don't exit before got something numberWanted++; } } } } } if (numberWanted <= 0) { numberWanted = 0; break; } } if (bestSequence != saveSequence) { savedBestGubDual_ = bestDjMod; savedBestDj_ = bestDj; savedBestSequence_ = bestSequence; savedBestSet_ = bestSet; } // Do packed part before gub // always??? // Resize so just do to gub numberActiveColumns_ = firstDynamic_; int saveMinNeg = minimumGoodReducedCosts_; if (bestSequence >= 0) minimumGoodReducedCosts_ = -2; currentWanted_ = numberWanted; ClpPackedMatrix::partialPricing(model, startFraction, endFraction, bestSequence, numberWanted); numberActiveColumns_ = matrix_->getNumCols(); minimumGoodReducedCosts_ = saveMinNeg; // See if may be finished if (!startG2 && bestSequence < 0) infeasibilityWeight_ = model_->infeasibilityCost(); else if (bestSequence >= 0) infeasibilityWeight_ = -1.0; currentWanted_ = numberWanted; } } /* Creates a variable. This is called after partial pricing and may modify matrix. May update bestSequence. */ void ClpDynamicExampleMatrix::createVariable(ClpSimplex * model, int & bestSequence) { int numberRows = model->numberRows(); int slackOffset = lastDynamic_ + numberRows; int structuralOffset = slackOffset + numberSets_; int bestSequence2 = savedBestSequence_ - structuralOffset; if (bestSequence2 >= 0) { // See if needs new if (bestSequence2 >= maximumGubColumns_) { bestSequence2 -= maximumGubColumns_; int sequence = addColumn(startColumnGen_[bestSequence2+1] - startColumnGen_[bestSequence2], rowGen_ + startColumnGen_[bestSequence2], elementGen_ + startColumnGen_[bestSequence2], costGen_[bestSequence2], columnLowerGen_ ? columnLowerGen_[bestSequence2] : 0, columnUpperGen_ ? columnUpperGen_[bestSequence2] : 1.0e30, savedBestSet_, getDynamicStatusGen(bestSequence2)); savedBestSequence_ = structuralOffset + sequence; idGen_[sequence] = bestSequence2; setDynamicStatusGen(bestSequence2, inSmall); } } ClpDynamicMatrix::createVariable(model, bestSequence/*, bestSequence2*/); // clear for next iteration savedBestSequence_ = -1; } /* If addColumn forces compression then this allows descendant to know what to do. If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. Entries at upper bound (really nonzero) never go out (at present). */ void ClpDynamicExampleMatrix::packDown(const int * in, int numberToPack) { int put = 0; for (int i = 0; i < numberToPack; i++) { int id = idGen_[i]; if (in[i] >= 0) { // stays in assert (put == in[i]); // true for now idGen_[put++] = id; } else { // out to lower bound setDynamicStatusGen(id, atLowerBound); } } assert (put == numberGubColumns_); } Clp-1.15.10/src/ClpPresolve.cpp0000644000076600007660000025147512130104455014615 0ustar coincoin/* $Id: ClpPresolve.cpp 1931 2013-04-06 20:44:29Z 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). //#define PRESOLVE_CONSISTENCY 1 //#define PRESOLVE_DEBUG 1 #include #include #include #include "CoinHelperFunctions.hpp" #include "ClpConfig.h" #ifdef CLP_HAS_ABC #include "CoinAbcCommon.hpp" #endif #include "CoinPackedMatrix.hpp" #include "ClpPackedMatrix.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #ifndef SLIM_CLP #include "ClpQuadraticObjective.hpp" #endif #include "ClpPresolve.hpp" #include "CoinPresolveMatrix.hpp" #include "CoinPresolveEmpty.hpp" #include "CoinPresolveFixed.hpp" #include "CoinPresolvePsdebug.hpp" #include "CoinPresolveSingleton.hpp" #include "CoinPresolveDoubleton.hpp" #include "CoinPresolveTripleton.hpp" #include "CoinPresolveZeros.hpp" #include "CoinPresolveSubst.hpp" #include "CoinPresolveForcing.hpp" #include "CoinPresolveDual.hpp" #include "CoinPresolveTighten.hpp" #include "CoinPresolveUseless.hpp" #include "CoinPresolveDupcol.hpp" #include "CoinPresolveImpliedFree.hpp" #include "CoinPresolveIsolated.hpp" #include "CoinMessage.hpp" ClpPresolve::ClpPresolve() : originalModel_(NULL), presolvedModel_(NULL), nonLinearValue_(0.0), originalColumn_(NULL), originalRow_(NULL), rowObjective_(NULL), paction_(0), ncols_(0), nrows_(0), nelems_(0), #ifdef ABC_INHERIT numberPasses_(20), #else numberPasses_(5), #endif substitution_(3), #ifndef CLP_NO_STD saveFile_(""), #endif presolveActions_(0) { } ClpPresolve::~ClpPresolve() { destroyPresolve(); } // Gets rid of presolve actions (e.g.when infeasible) void ClpPresolve::destroyPresolve() { const CoinPresolveAction *paction = paction_; while (paction) { const CoinPresolveAction *next = paction->next; delete paction; paction = next; } delete [] originalColumn_; delete [] originalRow_; paction_ = NULL; originalColumn_ = NULL; originalRow_ = NULL; delete [] rowObjective_; rowObjective_ = NULL; } /* This version of presolve returns a pointer to a new presolved model. NULL if infeasible */ ClpSimplex * ClpPresolve::presolvedModel(ClpSimplex & si, double feasibilityTolerance, bool keepIntegers, int numberPasses, bool dropNames, bool doRowObjective, const char * prohibitedRows, const char * prohibitedColumns) { // Check matrix int checkType = ((si.specialOptions() & 128) != 0) ? 14 : 15; if (!si.clpMatrix()->allElementsInRange(&si, si.getSmallElementValue(), 1.0e20,checkType)) return NULL; else return gutsOfPresolvedModel(&si, feasibilityTolerance, keepIntegers, numberPasses, dropNames, doRowObjective, prohibitedRows, prohibitedColumns); } #ifndef CLP_NO_STD /* This version of presolve updates model and saves original data to file. Returns non-zero if infeasible */ int ClpPresolve::presolvedModelToFile(ClpSimplex &si, std::string fileName, double feasibilityTolerance, bool keepIntegers, int numberPasses, bool dropNames, bool doRowObjective) { // Check matrix if (!si.clpMatrix()->allElementsInRange(&si, si.getSmallElementValue(), 1.0e20)) return 2; saveFile_ = fileName; si.saveModel(saveFile_.c_str()); ClpSimplex * model = gutsOfPresolvedModel(&si, feasibilityTolerance, keepIntegers, numberPasses, dropNames, doRowObjective); if (model == &si) { return 0; } else { si.restoreModel(saveFile_.c_str()); remove(saveFile_.c_str()); return 1; } } #endif // Return pointer to presolved model ClpSimplex * ClpPresolve::model() const { return presolvedModel_; } // Return pointer to original model ClpSimplex * ClpPresolve::originalModel() const { return originalModel_; } // Return presolve status (0,1,2) int ClpPresolve::presolveStatus() const { if (nelems_>=0) { // feasible (or not done yet) return 0; } else { int presolveStatus = - nelems_; // If both infeasible and unbounded - say infeasible if (presolveStatus>2) presolveStatus = 1; return presolveStatus; } } void ClpPresolve::postsolve(bool updateStatus) { // Return at once if no presolved model if (!presolvedModel_) return; // Messages CoinMessages messages = originalModel_->coinMessages(); if (!presolvedModel_->isProvenOptimal()) { presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NONOPTIMAL, messages) << CoinMessageEol; } // this is the size of the original problem const int ncols0 = ncols_; const int nrows0 = nrows_; const CoinBigIndex nelems0 = nelems_; // this is the reduced problem int ncols = presolvedModel_->getNumCols(); int nrows = presolvedModel_->getNumRows(); double * acts = NULL; double * sol = NULL; unsigned char * rowstat = NULL; unsigned char * colstat = NULL; #ifndef CLP_NO_STD if (saveFile_ == "") { #endif // reality check assert(ncols0 == originalModel_->getNumCols()); assert(nrows0 == originalModel_->getNumRows()); acts = originalModel_->primalRowSolution(); sol = originalModel_->primalColumnSolution(); if (updateStatus) { // postsolve does not know about fixed int i; for (i = 0; i < nrows + ncols; i++) { if (presolvedModel_->getColumnStatus(i) == ClpSimplex::isFixed) presolvedModel_->setColumnStatus(i, ClpSimplex::atLowerBound); } unsigned char *status = originalModel_->statusArray(); if (!status) { originalModel_->createStatus(); status = originalModel_->statusArray(); } rowstat = status + ncols0; colstat = status; CoinMemcpyN( presolvedModel_->statusArray(), ncols, colstat); CoinMemcpyN( presolvedModel_->statusArray() + ncols, nrows, rowstat); } #ifndef CLP_NO_STD } else { // from file acts = new double[nrows0]; sol = new double[ncols0]; CoinZeroN(acts, nrows0); CoinZeroN(sol, ncols0); if (updateStatus) { unsigned char *status = new unsigned char [nrows0+ncols0]; rowstat = status + ncols0; colstat = status; CoinMemcpyN( presolvedModel_->statusArray(), ncols, colstat); CoinMemcpyN( presolvedModel_->statusArray() + ncols, nrows, rowstat); } } #endif // CoinPostsolveMatrix object assumes ownership of sol, acts, colstat; // will be deleted by ~CoinPostsolveMatrix. delete[] operations below // cause duplicate free. In case where saveFile == "", as best I can see // arrays are owned by originalModel_. fix is to // clear fields in prob to avoid delete[] in ~CoinPostsolveMatrix. CoinPostsolveMatrix prob(presolvedModel_, ncols0, nrows0, nelems0, presolvedModel_->getObjSense(), // end prepost sol, acts, colstat, rowstat); postsolve(prob); #ifndef CLP_NO_STD if (saveFile_ != "") { // From file assert (originalModel_ == presolvedModel_); originalModel_->restoreModel(saveFile_.c_str()); remove(saveFile_.c_str()); CoinMemcpyN(acts, nrows0, originalModel_->primalRowSolution()); // delete [] acts; CoinMemcpyN(sol, ncols0, originalModel_->primalColumnSolution()); // delete [] sol; if (updateStatus) { CoinMemcpyN(colstat, nrows0 + ncols0, originalModel_->statusArray()); // delete [] colstat; } } else { #endif prob.sol_ = 0 ; prob.acts_ = 0 ; prob.colstat_ = 0 ; #ifndef CLP_NO_STD } #endif // put back duals CoinMemcpyN(prob.rowduals_, nrows_, originalModel_->dualRowSolution()); double maxmin = originalModel_->getObjSense(); if (maxmin < 0.0) { // swap signs int i; double * pi = originalModel_->dualRowSolution(); for (i = 0; i < nrows_; i++) pi[i] = -pi[i]; } // Now check solution double offset; CoinMemcpyN(originalModel_->objectiveAsObject()->gradient(originalModel_, originalModel_->primalColumnSolution(), offset, true), ncols_, originalModel_->dualColumnSolution()); originalModel_->clpMatrix()->transposeTimes(-1.0, originalModel_->dualRowSolution(), originalModel_->dualColumnSolution()); memset(originalModel_->primalRowSolution(), 0, nrows_ * sizeof(double)); originalModel_->clpMatrix()->times(1.0, originalModel_->primalColumnSolution(), originalModel_->primalRowSolution()); originalModel_->checkSolutionInternal(); if (originalModel_->sumDualInfeasibilities() > 1.0e-1) { // See if we can fix easily static_cast (originalModel_)->cleanupAfterPostsolve(); } // Messages presolvedModel_->messageHandler()->message(COIN_PRESOLVE_POSTSOLVE, messages) << originalModel_->objectiveValue() << originalModel_->sumDualInfeasibilities() << originalModel_->numberDualInfeasibilities() << originalModel_->sumPrimalInfeasibilities() << originalModel_->numberPrimalInfeasibilities() << CoinMessageEol; //originalModel_->objectiveValue_=objectiveValue_; originalModel_->setNumberIterations(presolvedModel_->numberIterations()); if (!presolvedModel_->status()) { if (!originalModel_->numberDualInfeasibilities() && !originalModel_->numberPrimalInfeasibilities()) { originalModel_->setProblemStatus( 0); } else { originalModel_->setProblemStatus( -1); // Say not optimal after presolve originalModel_->setSecondaryStatus(7); presolvedModel_->messageHandler()->message(COIN_PRESOLVE_NEEDS_CLEANING, messages) << CoinMessageEol; } } else { originalModel_->setProblemStatus( presolvedModel_->status()); // but not if close to feasible if( originalModel_->sumPrimalInfeasibilities()<1.0e-1) { originalModel_->setProblemStatus( -1); // Say not optimal after presolve originalModel_->setSecondaryStatus(7); } } #ifndef CLP_NO_STD if (saveFile_ != "") presolvedModel_ = NULL; #endif } // return pointer to original columns const int * ClpPresolve::originalColumns() const { return originalColumn_; } // return pointer to original rows const int * ClpPresolve::originalRows() const { return originalRow_; } // Set pointer to original model void ClpPresolve::setOriginalModel(ClpSimplex * model) { originalModel_ = model; } #if 0 // A lazy way to restrict which transformations are applied // during debugging. static int ATOI(const char *name) { return true; #if PRESOLVE_DEBUG || PRESOLVE_SUMMARY if (getenv(name)) { int val = atoi(getenv(name)); printf("%s = %d\n", name, val); return (val); } else { if (strcmp(name, "off")) return (true); else return (false); } #else return (true); #endif } #endif //#define PRESOLVE_DEBUG 1 #if PRESOLVE_DEBUG void check_sol(CoinPresolveMatrix *prob, double tol) { double *colels = prob->colels_; int *hrow = prob->hrow_; int *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; int *hinrow = prob->hinrow_; int ncols = prob->ncols_; double * csol = prob->sol_; double * acts = prob->acts_; double * clo = prob->clo_; double * cup = prob->cup_; int nrows = prob->nrows_; double * rlo = prob->rlo_; double * rup = prob->rup_; int colx; double * rsol = new double[nrows]; memset(rsol, 0, nrows * sizeof(double)); for (colx = 0; colx < ncols; ++colx) { if (1) { CoinBigIndex k = mcstrt[colx]; int nx = hincol[colx]; double solutionValue = csol[colx]; for (int i = 0; i < nx; ++i) { int row = hrow[k]; double coeff = colels[k]; k++; rsol[row] += solutionValue * coeff; } if (csol[colx] < clo[colx] - tol) { printf("low CSOL: %d - %g %g %g\n", colx, clo[colx], csol[colx], cup[colx]); } else if (csol[colx] > cup[colx] + tol) { printf("high CSOL: %d - %g %g %g\n", colx, clo[colx], csol[colx], cup[colx]); } } } int rowx; for (rowx = 0; rowx < nrows; ++rowx) { if (hinrow[rowx]) { if (fabs(rsol[rowx] - acts[rowx]) > tol) printf("inacc RSOL: %d - %g %g (acts_ %g) %g\n", rowx, rlo[rowx], rsol[rowx], acts[rowx], rup[rowx]); if (rsol[rowx] < rlo[rowx] - tol) { printf("low RSOL: %d - %g %g %g\n", rowx, rlo[rowx], rsol[rowx], rup[rowx]); } else if (rsol[rowx] > rup[rowx] + tol ) { printf("high RSOL: %d - %g %g %g\n", rowx, rlo[rowx], rsol[rowx], rup[rowx]); } } } delete [] rsol; } #endif static int tightenDoubletons2(CoinPresolveMatrix * prob) { // column-major representation const int ncols = prob->ncols_ ; const CoinBigIndex *const mcstrt = prob->mcstrt_ ; const int *const hincol = prob->hincol_ ; const int *const hrow = prob->hrow_ ; double * colels = prob->colels_ ; double * cost = prob->cost_ ; // column type, bounds, solution, and status const unsigned char *const integerType = prob->integerType_ ; double * clo = prob->clo_ ; double * cup = prob->cup_ ; // row-major representation //const int nrows = prob->nrows_ ; const CoinBigIndex *const mrstrt = prob->mrstrt_ ; const int *const hinrow = prob->hinrow_ ; const int *const hcol = prob->hcol_ ; double * rowels = prob->rowels_ ; // row bounds double *const rlo = prob->rlo_ ; double *const rup = prob->rup_ ; // tolerances //const double ekkinf2 = PRESOLVE_SMALL_INF ; //const double ekkinf = ekkinf2*1.0e8 ; //const double ztolcbarj = prob->ztoldj_ ; //const CoinRelFltEq relEq(prob->ztolzb_) ; int numberChanged=0; double bound[2]; double alpha[2]={0.0,0.0}; double offset=0.0; for (int icol=0;icol-1.0e30) { if (rup[row0]>1.0e30) { swapSigns0=true; rowUpper0=-rlo[row0]; element0=-element0; } else { // range or equality continue; } } else if (rup[row0]>1.0e30) { // free continue; } #if 0 // skip here for speed // skip if no cost (should be able to get rid of) if (!cost[icol]) { printf("should be able to get rid of %d with no cost\n",icol); continue; } // skip if negative cost for now if (cost[icol]<0.0) { printf("code for negative cost\n"); continue; } #endif double element1 = colels[start+1]; double rowUpper1=rup[row1]; bool swapSigns1=false; if (rlo[row1]>-1.0e30) { if (rup[row1]>1.0e30) { swapSigns1=true; rowUpper1=-rlo[row1]; element1=-element1; } else { // range or equality continue; } } else if (rup[row1]>1.0e30) { // free continue; } double lowerX=clo[icol]; double upperX=cup[icol]; int otherCol=-1; CoinBigIndex startRow=mrstrt[row0]; for (CoinBigIndex j=startRow;j0.0) { if (value<0.0) infLow0 =true; } else if (alpha[0]<0.0) { if (value>0.0) infLow0 =true; } if (alpha[1]>0.0) { if (value<0.0) infLow1 =true; } else if (alpha[1]<0.0) { if (value>0.0) infLow1 =true; } } /* Got sums */ double thisLowest0=-COIN_DBL_MAX; double thisHighest0=COIN_DBL_MAX; if (element0>0.0) { // upper bound unless inf&2 !=0 if (!infLow0) thisHighest0 = (rowUpper0-sum0)/element0; } else { // lower bound unless inf&2 !=0 if (!infLow0) thisLowest0 = (rowUpper0-sum0)/element0; } double thisLowest1=-COIN_DBL_MAX; double thisHighest1=COIN_DBL_MAX; if (element1>0.0) { // upper bound unless inf&2 !=0 if (!infLow1) thisHighest1 = (rowUpper1-sum1)/element1; } else { // lower bound unless inf&2 !=0 if (!infLow1) thisLowest1 = (rowUpper1-sum1)/element1; } if (thisLowest0>thisLowest1+1.0e-12) { if (thisLowest0>lowerX+1.0e-12) binding0|= 1<thisLowest0+1.0e-12) { if (thisLowest1>lowerX+1.0e-12) binding1|= 1<=0.0) { if (highestLowest=lowerX&&highestHighest<1.0e30) { highestHighest=CoinMin(highestHighest,highestLowest); } } if (cost[icol]<=0.0) { if (lowestHighest>lowerX&&lowestHighest<=upperX&&lowestHighest>-1.0e30) { lowestLowest=CoinMax(lowestLowest,lowestHighest); } } #if 1 if (lowestLowest>lowerX+1.0e-8) { #ifdef PRINT_VALUES printf("Can increase lower bound on %d from %g to %g\n", icol,lowerX,lowestLowest); #endif lowerX=lowestLowest; } if (highestHighest %g slope %g for constraint 1 ranges %g -> %g slope %g\n", costEqual,ranges0[0],ranges0[1],slope[0],ranges1[0],ranges1[1],slope[1]); #endif xValue=bound[0]; yValue0=(rowUpper0-xValue*alpha[0])/element0; yValue1=(rowUpper1-xValue*alpha[1])/element1; #ifdef PRINT_VALUES printf("value of %d is %g, value of %d is max(%g,%g) - %g\n", otherCol,xValue,icol,yValue0,yValue1,CoinMax(yValue0,yValue1)); #endif newLower=CoinMin(newLower,CoinMax(yValue0,yValue1)); // cost>0 so will be at lower //double yValueAtBound0=newLower; newUpper=CoinMax(newUpper,CoinMax(yValue0,yValue1)); xValue=bound[1]; yValue0=(rowUpper0-xValue*alpha[0])/element0; yValue1=(rowUpper1-xValue*alpha[1])/element1; #ifdef PRINT_VALUES printf("value of %d is %g, value of %d is max(%g,%g) - %g\n", otherCol,xValue,icol,yValue0,yValue1,CoinMax(yValue0,yValue1)); #endif newLower=CoinMin(newLower,CoinMax(yValue0,yValue1)); // cost>0 so will be at lower //double yValueAtBound1=newLower; newUpper=CoinMax(newUpper,CoinMax(yValue0,yValue1)); lowerX=CoinMax(lowerX,newLower-1.0e-12*fabs(newLower)); upperX=CoinMin(upperX,newUpper+1.0e-12*fabs(newUpper)); // Now make duplicate row // keep row 0 so need to adjust costs so same #ifdef PRINT_VALUES printf("Costs for x %g,%g,%g are %g,%g,%g\n", xValueEqual-1.0,xValueEqual,xValueEqual+1.0, costEqual-slope[0],costEqual,costEqual+slope[1]); #endif double costOther=cost[otherCol]+slope[1]; double costThis=cost[icol]+slope[1]*(element0/alpha[0]); xValue=xValueEqual; yValue0=CoinMax((rowUpper0-xValue*alpha[0])/element0,lowerX); double thisOffset=costEqual-(costOther*xValue+costThis*yValue0); offset += thisOffset; #ifdef PRINT_VALUES printf("new cost at equal %g\n",costOther*xValue+costThis*yValue0+thisOffset); #endif xValue=xValueEqual-1.0; yValue0=CoinMax((rowUpper0-xValue*alpha[0])/element0,lowerX); #ifdef PRINT_VALUES printf("new cost at -1 %g\n",costOther*xValue+costThis*yValue0+thisOffset); #endif assert(fabs((costOther*xValue+costThis*yValue0+thisOffset)-(costEqual-slope[0]))<1.0e-5); xValue=xValueEqual+1.0; yValue0=CoinMax((rowUpper0-xValue*alpha[0])/element0,lowerX); #ifdef PRINT_VALUES printf("new cost at +1 %g\n",costOther*xValue+costThis*yValue0+thisOffset); #endif assert(fabs((costOther*xValue+costThis*yValue0+thisOffset)-(costEqual+slope[1]))<1.0e-5); numberChanged++; // continue; cost[otherCol] = costOther; cost[icol] = costThis; clo[icol]=lowerX; cup[icol]=upperX; int startCol[2]; int endCol[2]; startCol[0]=mcstrt[icol]; endCol[0]=startCol[0]+2; startCol[1]=mcstrt[otherCol]; endCol[1]=startCol[1]+hincol[otherCol]; double values[2]={0.0,0.0}; for (int k=0;k<2;k++) { for (CoinBigIndex i=startCol[k];i0 if (offset) printf("Cost offset %g\n",offset); #endif return numberChanged; } //#define COIN_PRESOLVE_BUG #ifdef COIN_PRESOLVE_BUG static int counter=1000000; static int startEmptyRows=0; static int startEmptyColumns=0; static bool break2(CoinPresolveMatrix *prob) { int droppedRows = prob->countEmptyRows() - startEmptyRows ; int droppedColumns = prob->countEmptyCols() - startEmptyColumns; startEmptyRows=prob->countEmptyRows(); startEmptyColumns=prob->countEmptyCols(); printf("Dropped %d rows and %d columns - current empty %d, %d\n",droppedRows, droppedColumns,startEmptyRows,startEmptyColumns); counter--; if (!counter) { printf("skipping next and all\n"); } return (counter<=0); } #define possibleBreak if (break2(prob)) break #define possibleSkip if (!break2(prob)) #else #define possibleBreak #define possibleSkip #endif #define SOME_PRESOLVE_DETAIL #ifndef SOME_PRESOLVE_DETAIL #define printProgress(x,y) {} #else #define printProgress(x,y) {if ((presolveActions_ & 0x80000000) != 0) \ printf("%c loop %d %d empty rows, %d empty columns\n",x,y,prob->countEmptyRows(), \ prob->countEmptyCols());} #endif // This is the presolve loop. // It is a separate virtual function so that it can be easily // customized by subclassing CoinPresolve. const CoinPresolveAction *ClpPresolve::presolve(CoinPresolveMatrix *prob) { // Messages CoinMessages messages = CoinMessage(prob->messages().language()); paction_ = 0; prob->maxSubstLevel_ = 3 ; #ifndef PRESOLVE_DETAIL if (prob->tuning_) { #endif int numberEmptyRows=0; for ( int i=0;inrows_;i++) { if (!prob->hinrow_[i]) { PRESOLVE_DETAIL_PRINT(printf("pre_empty row %d\n",i)); //printf("pre_empty row %d\n",i); numberEmptyRows++; } } int numberEmptyCols=0; for ( int i=0;incols_;i++) { if (!prob->hincol_[i]) { PRESOLVE_DETAIL_PRINT(printf("pre_empty col %d\n",i)); //printf("pre_empty col %d\n",i); numberEmptyCols++; } } printf("CoinPresolve initial state %d empty rows and %d empty columns\n", numberEmptyRows,numberEmptyCols); #ifndef PRESOLVE_DETAIL } #endif prob->status_ = 0; // say feasible printProgress('A',0); paction_ = make_fixed(prob, paction_); paction_ = testRedundant(prob,paction_) ; printProgress('B',0); // if integers then switch off dual stuff // later just do individually bool doDualStuff = (presolvedModel_->integerInformation() == NULL); // but allow in some cases if ((presolveActions_ & 512) != 0) doDualStuff = true; if (prob->anyProhibited()) doDualStuff = false; if (!doDual()) doDualStuff = false; #if PRESOLVE_CONSISTENCY // presolve_links_ok(prob->rlink_, prob->mrstrt_, prob->hinrow_, prob->nrows_); presolve_links_ok(prob, false, true) ; #endif if (!prob->status_) { bool slackSingleton = doSingletonColumn(); slackSingleton = true; const bool slackd = doSingleton(); const bool doubleton = doDoubleton(); const bool tripleton = doTripleton(); //#define NO_FORCING #ifndef NO_FORCING const bool forcing = doForcing(); #endif const bool ifree = doImpliedFree(); const bool zerocost = doTighten(); const bool dupcol = doDupcol(); const bool duprow = doDuprow(); const bool dual = doDualStuff; // some things are expensive so just do once (normally) int i; // say look at all if (!prob->anyProhibited()) { for (i = 0; i < nrows_; i++) prob->rowsToDo_[i] = i; prob->numberRowsToDo_ = nrows_; for (i = 0; i < ncols_; i++) prob->colsToDo_[i] = i; prob->numberColsToDo_ = ncols_; } else { // some stuff must be left alone prob->numberRowsToDo_ = 0; for (i = 0; i < nrows_; i++) if (!prob->rowProhibited(i)) prob->rowsToDo_[prob->numberRowsToDo_++] = i; prob->numberColsToDo_ = 0; for (i = 0; i < ncols_; i++) if (!prob->colProhibited(i)) prob->colsToDo_[prob->numberColsToDo_++] = i; } // transfer costs (may want to do it in OsiPresolve) // need a transfer back at end of postsolve transferCosts(prob); int iLoop; #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif if (dupcol) { // maybe allow integer columns to be checked if ((presolveActions_ & 512) != 0) prob->setPresolveOptions(prob->presolveOptions() | 1); possibleSkip; paction_ = dupcol_action::presolve(prob, paction_); printProgress('C',0); } #ifdef ABC_INHERIT if (doTwoxTwo()) { possibleSkip; paction_ = twoxtwo_action::presolve(prob, paction_); } #endif if (duprow) { possibleSkip; if (doTwoxTwo()) { int nTightened=tightenDoubletons2(prob); if (nTightened) PRESOLVE_DETAIL_PRINT(printf("%d doubletons tightened\n", nTightened)); } paction_ = duprow_action::presolve(prob, paction_); printProgress('D',0); } if (doGubrow()) { possibleSkip; paction_ = gubrow_action::presolve(prob, paction_); printProgress('E',0); } if ((presolveActions_ & 16384) != 0) prob->setPresolveOptions(prob->presolveOptions() | 16384); // For inaccurate data in implied free if ((presolveActions_ & 1024) != 0) prob->setPresolveOptions(prob->presolveOptions() | 0x20000); // Check number rows dropped int lastDropped = 0; prob->pass_ = 0; #ifdef ABC_INHERIT int numberRowsStart=nrows_-prob->countEmptyRows(); int numberColumnsStart=ncols_-prob->countEmptyCols(); int numberRowsLeft=numberRowsStart; int numberColumnsLeft=numberColumnsStart; bool lastPassWasGood=true; #if ABC_NORMAL_DEBUG printf("Original rows,columns %d,%d starting first pass with %d,%d\n", nrows_,ncols_,numberRowsLeft,numberColumnsLeft); #endif #endif if (numberPasses_<=5) prob->presolveOptions_ |= 0x10000; // say more lightweight for (iLoop = 0; iLoop < numberPasses_; iLoop++) { // See if we want statistics if ((presolveActions_ & 0x80000000) != 0) printf("Starting major pass %d after %g seconds with %d rows, %d columns\n", iLoop + 1, CoinCpuTime() - prob->startTime_, nrows_-prob->countEmptyRows(), ncols_-prob->countEmptyCols()); #ifdef PRESOLVE_SUMMARY printf("Starting major pass %d\n", iLoop + 1); #endif const CoinPresolveAction * const paction0 = paction_; // look for substitutions with no fill //#define IMPLIED 3 #ifdef IMPLIED int fill_level = 3; #define IMPLIED2 99 #if IMPLIED!=3 #if IMPLIED>2&&IMPLIED<11 fill_level = IMPLIED; COIN_DETAIL_PRINT(printf("** fill_level == %d !\n", fill_level)); #endif #if IMPLIED>11&&IMPLIED<21 fill_level = -(IMPLIED - 10); COIN_DETAIL_PRINT(printf("** fill_level == %d !\n", fill_level)); #endif #endif #else int fill_level = prob->maxSubstLevel_; #endif int whichPass = 0; while (1) { whichPass++; prob->pass_++; const CoinPresolveAction * const paction1 = paction_; if (slackd) { bool notFinished = true; while (notFinished) { possibleBreak; paction_ = slack_doubleton_action::presolve(prob, paction_, notFinished); } printProgress('F',iLoop+1); if (prob->status_) break; } if (dual && whichPass == 1) { // this can also make E rows so do one bit here possibleBreak; paction_ = remove_dual_action::presolve(prob, paction_); if (prob->status_) break; printProgress('G',iLoop+1); } if (doubleton) { possibleBreak; paction_ = doubleton_action::presolve(prob, paction_); if (prob->status_) break; printProgress('H',iLoop+1); } if (tripleton) { possibleBreak; paction_ = tripleton_action::presolve(prob, paction_); if (prob->status_) break; printProgress('I',iLoop+1); } if (zerocost) { possibleBreak; paction_ = do_tighten_action::presolve(prob, paction_); if (prob->status_) break; printProgress('J',iLoop+1); } #ifndef NO_FORCING if (forcing) { possibleBreak; paction_ = forcing_constraint_action::presolve(prob, paction_); if (prob->status_) break; printProgress('K',iLoop+1); } #endif if (ifree && (whichPass % 5) == 1) { possibleBreak; paction_ = implied_free_action::presolve(prob, paction_, fill_level); if (prob->status_) break; printProgress('L',iLoop+1); } #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif #if PRESOLVE_CONSISTENCY // presolve_links_ok(prob->rlink_, prob->mrstrt_, prob->hinrow_, // prob->nrows_); presolve_links_ok(prob, false, true) ; #endif //#if PRESOLVE_DEBUG // presolve_no_zeros(prob->mcstrt_, prob->colels_, prob->hincol_, // prob->ncols_); //#endif //#if PRESOLVE_CONSISTENCY // prob->consistent(); //#endif #if PRESOLVE_CONSISTENCY presolve_no_zeros(prob, true, false) ; presolve_consistent(prob, true) ; #endif { // set up for next pass // later do faster if many changes i.e. memset and memcpy const int * count = prob->hinrow_; const int * nextToDo = prob->nextRowsToDo_; int * toDo = prob->rowsToDo_; int nNext = prob->numberNextRowsToDo_; int n = 0; for (int i = 0; i < nNext; i++) { int index = nextToDo[i]; prob->unsetRowChanged(index); if (count[index]) toDo[n++] = index; } prob->numberRowsToDo_ = n; prob->numberNextRowsToDo_ = 0; count = prob->hincol_; nextToDo = prob->nextColsToDo_; toDo = prob->colsToDo_; nNext = prob->numberNextColsToDo_; n = 0; for (int i = 0; i < nNext; i++) { int index = nextToDo[i]; prob->unsetColChanged(index); if (count[index]) toDo[n++] = index; } prob->numberColsToDo_ = n; prob->numberNextColsToDo_ = 0; } if (paction_ == paction1 && fill_level > 0) break; } // say look at all int i; if (!prob->anyProhibited()) { const int * count = prob->hinrow_; int * toDo = prob->rowsToDo_; int n = 0; for (int i = 0; i < nrows_; i++) { prob->unsetRowChanged(i); if (count[i]) toDo[n++] = i; } prob->numberRowsToDo_ = n; prob->numberNextRowsToDo_ = 0; count = prob->hincol_; toDo = prob->colsToDo_; n = 0; for (int i = 0; i < ncols_; i++) { prob->unsetColChanged(i); if (count[i]) toDo[n++] = i; } prob->numberColsToDo_ = n; prob->numberNextColsToDo_ = 0; } else { // some stuff must be left alone prob->numberRowsToDo_ = 0; for (i = 0; i < nrows_; i++) if (!prob->rowProhibited(i)) prob->rowsToDo_[prob->numberRowsToDo_++] = i; prob->numberColsToDo_ = 0; for (i = 0; i < ncols_; i++) if (!prob->colProhibited(i)) prob->colsToDo_[prob->numberColsToDo_++] = i; } // now expensive things // this caused world.mps to run into numerical difficulties #ifdef PRESOLVE_SUMMARY printf("Starting expensive\n"); #endif if (dual) { int itry; for (itry = 0; itry < 5; itry++) { possibleBreak; paction_ = remove_dual_action::presolve(prob, paction_); if (prob->status_) break; printProgress('M',iLoop+1); const CoinPresolveAction * const paction2 = paction_; if (ifree) { #ifdef IMPLIED #if IMPLIED2 ==0 int fill_level = 0; // switches off substitution #elif IMPLIED2!=99 int fill_level = IMPLIED2; #endif #endif if ((itry & 1) == 0) { possibleBreak; paction_ = implied_free_action::presolve(prob, paction_, fill_level); } if (prob->status_) break; printProgress('N',iLoop+1); } if (paction_ == paction2) break; } } else if (ifree) { // just free #ifdef IMPLIED #if IMPLIED2 ==0 int fill_level = 0; // switches off substitution #elif IMPLIED2!=99 int fill_level = IMPLIED2; #endif #endif possibleBreak; paction_ = implied_free_action::presolve(prob, paction_, fill_level); if (prob->status_) break; printProgress('O',iLoop+1); } #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif if (dupcol) { // maybe allow integer columns to be checked if ((presolveActions_ & 512) != 0) prob->setPresolveOptions(prob->presolveOptions() | 1); possibleBreak; paction_ = dupcol_action::presolve(prob, paction_); if (prob->status_) break; printProgress('P',iLoop+1); } #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif if (duprow) { possibleBreak; paction_ = duprow_action::presolve(prob, paction_); if (prob->status_) break; printProgress('Q',iLoop+1); } // Marginally slower on netlib if this call is enabled. // paction_ = testRedundant(prob,paction_) ; #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif bool stopLoop = false; { int * hinrow = prob->hinrow_; int numberDropped = 0; for (i = 0; i < nrows_; i++) if (!hinrow[i]) numberDropped++; prob->messageHandler()->message(COIN_PRESOLVE_PASS, messages) << numberDropped << iLoop + 1 << CoinMessageEol; //printf("%d rows dropped after pass %d\n",numberDropped, // iLoop+1); if (numberDropped == lastDropped) stopLoop = true; else lastDropped = numberDropped; } // Do this here as not very loopy if (slackSingleton) { // On most passes do not touch costed slacks if (paction_ != paction0 && !stopLoop) { possibleBreak; paction_ = slack_singleton_action::presolve(prob, paction_, NULL); } else { // do costed if Clp (at end as ruins rest of presolve) possibleBreak; paction_ = slack_singleton_action::presolve(prob, paction_, rowObjective_); stopLoop = true; } printProgress('R',iLoop+1); } #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif if (paction_ == paction0 || stopLoop) break; #ifdef ABC_INHERIT // see whether to stop anyway int numberRowsNow=nrows_-prob->countEmptyRows(); int numberColumnsNow=ncols_-prob->countEmptyCols(); #if ABC_NORMAL_DEBUG printf("Original rows,columns %d,%d - last %d,%d end of pass %d has %d,%d\n", nrows_,ncols_,numberRowsLeft,numberColumnsLeft,iLoop+1,numberRowsNow, numberColumnsNow); #endif int rowsDeleted=numberRowsLeft-numberRowsNow; int columnsDeleted=numberColumnsLeft-numberColumnsNow; if (iLoop>15) { if (rowsDeleted*100presolveOptions_ &= ~0x10000; if (!prob->status_) { paction_ = drop_zero_coefficients(prob, paction_); #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif paction_ = drop_empty_cols_action::presolve(prob, paction_); paction_ = drop_empty_rows_action::presolve(prob, paction_); #if PRESOLVE_DEBUG check_sol(prob, 1.0e0); #endif } if (prob->status_) { if (prob->status_ == 1) prob->messageHandler()->message(COIN_PRESOLVE_INFEAS, messages) << prob->feasibilityTolerance_ << CoinMessageEol; else if (prob->status_ == 2) prob->messageHandler()->message(COIN_PRESOLVE_UNBOUND, messages) << CoinMessageEol; else prob->messageHandler()->message(COIN_PRESOLVE_INFEASUNBOUND, messages) << CoinMessageEol; // get rid of data destroyPresolve(); } return (paction_); } void check_djs(CoinPostsolveMatrix *prob); // We could have implemented this by having each postsolve routine // directly call the next one, but this may make it easier to add debugging checks. void ClpPresolve::postsolve(CoinPostsolveMatrix &prob) { { // Check activities double *colels = prob.colels_; int *hrow = prob.hrow_; CoinBigIndex *mcstrt = prob.mcstrt_; int *hincol = prob.hincol_; int *link = prob.link_; int ncols = prob.ncols_; char *cdone = prob.cdone_; double * csol = prob.sol_; int nrows = prob.nrows_; int colx; double * rsol = prob.acts_; memset(rsol, 0, nrows * sizeof(double)); for (colx = 0; colx < ncols; ++colx) { if (cdone[colx]) { CoinBigIndex k = mcstrt[colx]; int nx = hincol[colx]; double solutionValue = csol[colx]; for (int i = 0; i < nx; ++i) { int row = hrow[k]; double coeff = colels[k]; k = link[k]; rsol[row] += solutionValue * coeff; } } } } if (prob.maxmin_<0) { //for (int i=0;inumberRows();i++) //prob.rowduals_[i]=-prob.rowduals_[i]; for (int i=0;iname()); #endif paction->postsolve(&prob); #if PRESOLVE_DEBUG # if 0 /* This check fails (on exmip1 (!) in osiUnitTest) because clp enters postsolve with a solution that seems to have incorrect status for a logical. You can see similar behaviour with column status --- incorrect entering postsolve. -- lh, 111207 -- */ { int nr = 0; int i; for (i = 0; i < prob.nrows_; i++) { if ((prob.rowstat_[i] & 7) == 1) { nr++; } else if ((prob.rowstat_[i] & 7) == 2) { // at ub assert (prob.acts_[i] > prob.rup_[i] - 1.0e-6); } else if ((prob.rowstat_[i] & 7) == 3) { // at lb assert (prob.acts_[i] < prob.rlo_[i] + 1.0e-6); } } int nc = 0; for (i = 0; i < prob.ncols_; i++) { if ((prob.colstat_[i] & 7) == 1) nc++; } printf("%d rows (%d basic), %d cols (%d basic)\n", prob.nrows_, nr, prob.ncols_, nc); } # endif // if 0 checkit++; if (prob.colstat_ && checkit > 0) { presolve_check_nbasic(&prob) ; presolve_check_sol(&prob, 2, 2, 1) ; } #endif paction = paction->next; #if PRESOLVE_DEBUG // check_djs(&prob); if (checkit > 0) presolve_check_reduced_costs(&prob) ; #endif } #if PRESOLVE_DEBUG if (prob.colstat_) { presolve_check_nbasic(&prob) ; presolve_check_sol(&prob, 2, 2, 1) ; } #endif #undef PRESOLVE_DEBUG #if 0 && PRESOLVE_DEBUG for (i = 0; i < ncols0; i++) { if (!cdone[i]) { printf("!cdone[%d]\n", i); abort(); } } for (i = 0; i < nrows0; i++) { if (!rdone[i]) { printf("!rdone[%d]\n", i); abort(); } } for (i = 0; i < ncols0; i++) { if (sol[i] < -1e10 || sol[i] > 1e10) printf("!!!%d %g\n", i, sol[i]); } #endif #if 0 && PRESOLVE_DEBUG // debug check: make sure we ended up with same original matrix { int identical = 1; for (int i = 0; i < ncols0; i++) { PRESOLVEASSERT(hincol[i] == &prob->mcstrt0[i+1] - &prob->mcstrt0[i]); CoinBigIndex kcs0 = &prob->mcstrt0[i]; CoinBigIndex kcs = mcstrt[i]; int n = hincol[i]; for (int k = 0; k < n; k++) { CoinBigIndex k1 = presolve_find_row1(&prob->hrow0[kcs0+k], kcs, kcs + n, hrow); if (k1 == kcs + n) { printf("ROW %d NOT IN COL %d\n", &prob->hrow0[kcs0+k], i); abort(); } if (colels[k1] != &prob->dels0[kcs0+k]) printf("BAD COLEL[%d %d %d]: %g\n", k1, i, &prob->hrow0[kcs0+k], colels[k1] - &prob->dels0[kcs0+k]); if (kcs0 + k != k1) identical = 0; } } printf("identical? %d\n", identical); } #endif } static inline double getTolerance(const ClpSimplex *si, ClpDblParam key) { double tol; if (! si->getDblParam(key, tol)) { CoinPresolveAction::throwCoinError("getDblParam failed", "CoinPrePostsolveMatrix::CoinPrePostsolveMatrix"); } return (tol); } // Assumptions: // 1. nrows>=m.getNumRows() // 2. ncols>=m.getNumCols() // // In presolve, these values are equal. // In postsolve, they may be inequal, since the reduced problem // may be smaller, but we need room for the large problem. // ncols may be larger than si.getNumCols() in postsolve, // this at that point si will be the reduced problem, // but we need to reserve enough space for the original problem. CoinPrePostsolveMatrix::CoinPrePostsolveMatrix(const ClpSimplex * si, int ncols_in, int nrows_in, CoinBigIndex nelems_in, double bulkRatio) : ncols_(si->getNumCols()), nrows_(si->getNumRows()), nelems_(si->getNumElements()), ncols0_(ncols_in), nrows0_(nrows_in), bulkRatio_(bulkRatio), mcstrt_(new CoinBigIndex[ncols_in+1]), hincol_(new int[ncols_in+1]), cost_(new double[ncols_in]), clo_(new double[ncols_in]), cup_(new double[ncols_in]), rlo_(new double[nrows_in]), rup_(new double[nrows_in]), originalColumn_(new int[ncols_in]), originalRow_(new int[nrows_in]), ztolzb_(getTolerance(si, ClpPrimalTolerance)), ztoldj_(getTolerance(si, ClpDualTolerance)), maxmin_(si->getObjSense()), sol_(NULL), rowduals_(NULL), acts_(NULL), rcosts_(NULL), colstat_(NULL), rowstat_(NULL), handler_(NULL), defaultHandler_(false), messages_() { bulk0_ = static_cast (bulkRatio_ * nelems_in); hrow_ = new int [bulk0_]; colels_ = new double[bulk0_]; si->getDblParam(ClpObjOffset, originalOffset_); int ncols = si->getNumCols(); int nrows = si->getNumRows(); setMessageHandler(si->messageHandler()) ; ClpDisjointCopyN(si->getColLower(), ncols, clo_); ClpDisjointCopyN(si->getColUpper(), ncols, cup_); //ClpDisjointCopyN(si->getObjCoefficients(), ncols, cost_); double offset; ClpDisjointCopyN(si->objectiveAsObject()->gradient(si, si->getColSolution(), offset, true), ncols, cost_); ClpDisjointCopyN(si->getRowLower(), nrows, rlo_); ClpDisjointCopyN(si->getRowUpper(), nrows, rup_); int i; for (i = 0; i < ncols_in; i++) originalColumn_[i] = i; for (i = 0; i < nrows_in; i++) originalRow_[i] = i; sol_ = NULL; rowduals_ = NULL; acts_ = NULL; rcosts_ = NULL; colstat_ = NULL; rowstat_ = NULL; } // I am not familiar enough with CoinPackedMatrix to be confident // that I will implement a row-ordered version of toColumnOrderedGapFree // properly. static bool isGapFree(const CoinPackedMatrix& matrix) { const CoinBigIndex * start = matrix.getVectorStarts(); const int * length = matrix.getVectorLengths(); int i = matrix.getSizeVectorLengths() - 1; // Quick check if (matrix.getNumElements() == start[i]) { return true; } else { for (i = matrix.getSizeVectorLengths() - 1; i >= 0; --i) { if (start[i+1] - start[i] != length[i]) break; } return (! (i >= 0)); } } #if PRESOLVE_DEBUG static void matrix_bounds_ok(const double *lo, const double *up, int n) { int i; for (i = 0; i < n; i++) { PRESOLVEASSERT(lo[i] <= up[i]); PRESOLVEASSERT(lo[i] < PRESOLVE_INF); PRESOLVEASSERT(-PRESOLVE_INF < up[i]); } } #endif CoinPresolveMatrix::CoinPresolveMatrix(int ncols0_in, double /*maxmin*/, // end prepost members ClpSimplex * si, // rowrep int nrows_in, CoinBigIndex nelems_in, bool doStatus, double nonLinearValue, double bulkRatio) : CoinPrePostsolveMatrix(si, ncols0_in, nrows_in, nelems_in, bulkRatio), clink_(new presolvehlink[ncols0_in+1]), rlink_(new presolvehlink[nrows_in+1]), dobias_(0.0), // temporary init integerType_(new unsigned char[ncols0_in]), tuning_(false), startTime_(0.0), feasibilityTolerance_(0.0), status_(-1), colsToDo_(new int [ncols0_in]), numberColsToDo_(0), nextColsToDo_(new int[ncols0_in]), numberNextColsToDo_(0), rowsToDo_(new int [nrows_in]), numberRowsToDo_(0), nextRowsToDo_(new int[nrows_in]), numberNextRowsToDo_(0), presolveOptions_(0) { const int bufsize = bulk0_; nrows_ = si->getNumRows() ; // Set up change bits etc rowChanged_ = new unsigned char[nrows_]; memset(rowChanged_, 0, nrows_); colChanged_ = new unsigned char[ncols_]; memset(colChanged_, 0, ncols_); CoinPackedMatrix * m = si->matrix(); // The coefficient matrix is a big hunk of stuff. // Do the copy here to try to avoid running out of memory. const CoinBigIndex * start = m->getVectorStarts(); const int * row = m->getIndices(); const double * element = m->getElements(); int icol, nel = 0; mcstrt_[0] = 0; ClpDisjointCopyN(m->getVectorLengths(), ncols_, hincol_); if (si->getObjSense() < 0.0) { for (int i=0;i ZTOLDP) colels_[nel++] = element[j]; } mcstrt_[icol+1] = nel; hincol_[icol] = nel - mcstrt_[icol]; } // same thing for row rep CoinPackedMatrix * mRow = new CoinPackedMatrix(); mRow->setExtraGap(0.0); mRow->setExtraMajor(0.0); mRow->reverseOrderedCopyOf(*m); //mRow->removeGaps(); //mRow->setExtraGap(0.0); // Now get rid of matrix si->createEmptyMatrix(); double * el = mRow->getMutableElements(); int * ind = mRow->getMutableIndices(); CoinBigIndex * strt = mRow->getMutableVectorStarts(); int * len = mRow->getMutableVectorLengths(); // Do carefully to save memory rowels_ = new double[bulk0_]; ClpDisjointCopyN(el, nelems_, rowels_); mRow->nullElementArray(); delete [] el; hcol_ = new int[bulk0_]; ClpDisjointCopyN(ind, nelems_, hcol_); mRow->nullIndexArray(); delete [] ind; mrstrt_ = new CoinBigIndex[nrows_in+1]; ClpDisjointCopyN(strt, nrows_, mrstrt_); mRow->nullStartArray(); mrstrt_[nrows_] = nelems_; delete [] strt; hinrow_ = new int[nrows_in+1]; ClpDisjointCopyN(len, nrows_, hinrow_); if (nelems_ > nel) { nelems_ = nel; // Clean any small elements int irow; nel = 0; CoinBigIndex start = 0; for (irow = 0; irow < nrows_; irow++) { CoinBigIndex j; for (j = start; j < start + hinrow_[irow]; j++) { hcol_[nel] = hcol_[j]; if (fabs(rowels_[j]) > ZTOLDP) rowels_[nel++] = rowels_[j]; } start = mrstrt_[irow+1]; mrstrt_[irow+1] = nel; hinrow_[irow] = nel - mrstrt_[irow]; } } delete mRow; if (si->integerInformation()) { CoinMemcpyN(reinterpret_cast (si->integerInformation()), ncols_, integerType_); } else { ClpFillN(integerType_, ncols_, static_cast (0)); } #ifndef SLIM_CLP #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(si->objectiveAsObject())); #else ClpQuadraticObjective * quadraticObj = NULL; if (si->objectiveAsObject()->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(si->objectiveAsObject())); #endif #endif // Set up prohibited bits if needed if (nonLinearValue) { anyProhibited_ = true; for (icol = 0; icol < ncols_; icol++) { int j; bool nonLinearColumn = false; if (cost_[icol] == nonLinearValue) nonLinearColumn = true; for (j = mcstrt_[icol]; j < mcstrt_[icol+1]; j++) { if (colels_[j] == nonLinearValue) { nonLinearColumn = true; setRowProhibited(hrow_[j]); } } if (nonLinearColumn) setColProhibited(icol); } #ifndef SLIM_CLP } else if (quadraticObj) { CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); //const int * columnQuadratic = quadratic->getIndices(); //const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); //double * quadraticElement = quadratic->getMutableElements(); int numberColumns = quadratic->getNumCols(); anyProhibited_ = true; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnQuadraticLength[iColumn]) { setColProhibited(iColumn); //printf("%d prohib\n",iColumn); } } #endif } else { anyProhibited_ = false; } if (doStatus) { // allow for status and solution sol_ = new double[ncols_]; CoinMemcpyN(si->primalColumnSolution(), ncols_, sol_);; acts_ = new double [nrows_]; CoinMemcpyN(si->primalRowSolution(), nrows_, acts_); if (!si->statusArray()) si->createStatus(); colstat_ = new unsigned char [nrows_+ncols_]; CoinMemcpyN(si->statusArray(), (nrows_ + ncols_), colstat_); rowstat_ = colstat_ + ncols_; } // the original model's fields are now unneeded - free them si->resize(0, 0); #if PRESOLVE_DEBUG matrix_bounds_ok(rlo_, rup_, nrows_); matrix_bounds_ok(clo_, cup_, ncols_); #endif #if 0 for (i = 0; i < nrows; ++i) printf("NR: %6d\n", hinrow[i]); for (int i = 0; i < ncols; ++i) printf("NC: %6d\n", hincol[i]); #endif presolve_make_memlists(/*mcstrt_,*/ hincol_, clink_, ncols_); presolve_make_memlists(/*mrstrt_,*/ hinrow_, rlink_, nrows_); // this allows last col/row to expand up to bufsize-1 (22); // this must come after the calls to presolve_prefix mcstrt_[ncols_] = bufsize - 1; mrstrt_[nrows_] = bufsize - 1; // Allocate useful arrays initializeStuff(); #if PRESOLVE_CONSISTENCY //consistent(false); presolve_consistent(this, false) ; #endif } // avoid compiler warnings #if PRESOLVE_SUMMARY > 0 void CoinPresolveMatrix::update_model(ClpSimplex * si, int nrows0, int ncols0, CoinBigIndex nelems0) #else void CoinPresolveMatrix::update_model(ClpSimplex * si, int /*nrows0*/, int /*ncols0*/, CoinBigIndex /*nelems0*/) #endif { if (si->getObjSense() < 0.0) { for (int i=0;iloadProblem(ncols_, nrows_, mcstrt_, hrow_, colels_, hincol_, clo_, cup_, cost_, rlo_, rup_); //delete [] si->integerInformation(); int numberIntegers = 0; for (int i = 0; i < ncols_; i++) { if (integerType_[i]) numberIntegers++; } if (numberIntegers) si->copyInIntegerInformation(reinterpret_cast (integerType_)); else si->copyInIntegerInformation(NULL); #if PRESOLVE_SUMMARY printf("NEW NCOL/NROW/NELS: %d(-%d) %d(-%d) %d(-%d)\n", ncols_, ncols0 - ncols_, nrows_, nrows0 - nrows_, si->getNumElements(), nelems0 - si->getNumElements()); #endif si->setDblParam(ClpObjOffset, originalOffset_ - dobias_); if (si->getObjSense() < 0.0) { // put back for (int i=0;igetNumRows() ; ncols_ = si->getNumCols() ; sol_ = sol_in; rowduals_ = NULL; acts_ = acts_in; rcosts_ = NULL; colstat_ = colstat_in; rowstat_ = rowstat_in; // this is the *reduced* model, which is probably smaller int ncols1 = ncols_ ; int nrows1 = nrows_ ; const CoinPackedMatrix * m = si->matrix(); const CoinBigIndex nelemsr = m->getNumElements(); if (m->getNumElements() && !isGapFree(*m)) { // Odd - gaps CoinPackedMatrix mm(*m); mm.removeGaps(); mm.setExtraGap(0.0); ClpDisjointCopyN(mm.getVectorStarts(), ncols1, mcstrt_); CoinZeroN(mcstrt_ + ncols1, ncols0_ - ncols1); mcstrt_[ncols1] = nelems0; // ?? (should point to end of bulk store -- lh --) ClpDisjointCopyN(mm.getVectorLengths(), ncols1, hincol_); ClpDisjointCopyN(mm.getIndices(), nelemsr, hrow_); ClpDisjointCopyN(mm.getElements(), nelemsr, colels_); } else { // No gaps ClpDisjointCopyN(m->getVectorStarts(), ncols1, mcstrt_); CoinZeroN(mcstrt_ + ncols1, ncols0_ - ncols1); mcstrt_[ncols1] = nelems0; // ?? (should point to end of bulk store -- lh --) ClpDisjointCopyN(m->getVectorLengths(), ncols1, hincol_); ClpDisjointCopyN(m->getIndices(), nelemsr, hrow_); ClpDisjointCopyN(m->getElements(), nelemsr, colels_); } #if 0 && PRESOLVE_DEBUG presolve_check_costs(model, &colcopy); #endif // This determines the size of the data structure that contains // the matrix being postsolved. Links are taken from the free_list // to recreate matrix entries that were presolved away, // and links are added to the free_list when entries created during // presolve are discarded. There is never a need to gc this list. // Naturally, it should contain // exactly nelems0 entries "in use" when postsolving is done, // but I don't know whether the matrix could temporarily get // larger during postsolving. Substitution into more than two // rows could do that, in principle. I am being very conservative // here by reserving much more than the amount of space I probably need. // If this guess is wrong, check_free_list may be called. // int bufsize = 2*nelems0; memset(cdone_, -1, ncols0_); memset(rdone_, -1, nrows0_); rowduals_ = new double[nrows0_]; ClpDisjointCopyN(si->getRowPrice(), nrows1, rowduals_); rcosts_ = new double[ncols0_]; ClpDisjointCopyN(si->getReducedCost(), ncols1, rcosts_); if (maxmin < 0.0) { // change so will look as if minimize int i; for (i = 0; i < nrows1; i++) rowduals_[i] = - rowduals_[i]; for (i = 0; i < ncols1; i++) { rcosts_[i] = - rcosts_[i]; } } //ClpDisjointCopyN(si->getRowUpper(), nrows1, rup_); //ClpDisjointCopyN(si->getRowLower(), nrows1, rlo_); ClpDisjointCopyN(si->getColSolution(), ncols1, sol_); si->setDblParam(ClpObjOffset, originalOffset_); for (int j = 0; j < ncols1; j++) { #ifdef COIN_SLOW_PRESOLVE if (hincol_[j]) { #endif CoinBigIndex kcs = mcstrt_[j]; CoinBigIndex kce = kcs + hincol_[j]; for (CoinBigIndex k = kcs; k < kce; ++k) { link_[k] = k + 1; } link_[kce-1] = NO_LINK ; #ifdef COIN_SLOW_PRESOLVE } #endif } { int ml = maxlink_; for (CoinBigIndex k = nelemsr; k < ml; ++k) link_[k] = k + 1; if (ml) link_[ml-1] = NO_LINK; } free_list_ = nelemsr; # if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY /* These are used to track the action of postsolve transforms during debugging. */ CoinFillN(cdone_, ncols1, PRESENT_IN_REDUCED) ; CoinZeroN(cdone_ + ncols1, ncols0_in - ncols1) ; CoinFillN(rdone_, nrows1, PRESENT_IN_REDUCED) ; CoinZeroN(rdone_ + nrows1, nrows0_in - nrows1) ; # endif } /* This is main part of Presolve */ ClpSimplex * ClpPresolve::gutsOfPresolvedModel(ClpSimplex * originalModel, double feasibilityTolerance, bool keepIntegers, int numberPasses, bool dropNames, bool doRowObjective, const char * prohibitedRows, const char * prohibitedColumns) { ncols_ = originalModel->getNumCols(); nrows_ = originalModel->getNumRows(); nelems_ = originalModel->getNumElements(); numberPasses_ = numberPasses; double maxmin = originalModel->getObjSense(); originalModel_ = originalModel; delete [] originalColumn_; originalColumn_ = new int[ncols_]; delete [] originalRow_; originalRow_ = new int[nrows_]; // and fill in case returns early int i; for (i = 0; i < ncols_; i++) originalColumn_[i] = i; for (i = 0; i < nrows_; i++) originalRow_[i] = i; delete [] rowObjective_; if (doRowObjective) { rowObjective_ = new double [nrows_]; memset(rowObjective_, 0, nrows_ * sizeof(double)); } else { rowObjective_ = NULL; } // result is 0 - okay, 1 infeasible, -1 go round again, 2 - original model int result = -1; // User may have deleted - its their responsibility presolvedModel_ = NULL; // Messages CoinMessages messages = originalModel->coinMessages(); // Only go round 100 times even if integer preprocessing int totalPasses = 100; while (result == -1) { #ifndef CLP_NO_STD // make new copy if (saveFile_ == "") { #endif delete presolvedModel_; #ifndef CLP_NO_STD // So won't get names int lengthNames = originalModel->lengthNames(); originalModel->setLengthNames(0); #endif presolvedModel_ = new ClpSimplex(*originalModel); #ifndef CLP_NO_STD originalModel->setLengthNames(lengthNames); presolvedModel_->dropNames(); } else { presolvedModel_ = originalModel; if (dropNames) presolvedModel_->dropNames(); } #endif // drop integer information if wanted if (!keepIntegers) presolvedModel_->deleteIntegerInformation(); totalPasses--; double ratio = 2.0; if (substitution_ > 3) ratio = substitution_; else if (substitution_ == 2) ratio = 1.5; CoinPresolveMatrix prob(ncols_, maxmin, presolvedModel_, nrows_, nelems_, true, nonLinearValue_, ratio); if (prohibitedRows) { prob.setAnyProhibited(); for (int i=0;iprimalColumnSolution()); CoinMemcpyN( prob.acts_, prob.nrows_, presolvedModel_->primalRowSolution()); CoinMemcpyN( prob.colstat_, prob.ncols_, presolvedModel_->statusArray()); CoinMemcpyN( prob.rowstat_, prob.nrows_, presolvedModel_->statusArray() + prob.ncols_); if (fixInfeasibility && hasSolution) { // Looks feasible but double check to see if anything slipped through int n = prob.ncols_; double * lo = prob.clo_; double * up = prob.cup_; double * rsol = prob.acts_; //memset(prob.acts_,0,prob.nrows_*sizeof(double)); presolvedModel_->matrix()->times(prob.sol_,rsol); int i; for (i = 0; i < n; i++) { double gap=up[i]-lo[i]; if (rsol[i]up[i]+feasibilityTolerance&&fabs(rsol[i]-up[i])<1.0e-3) { up[i]=rsol[i]; if (gap<1.0e5) lo[i]=up[i]-gap; } if (up[i] < lo[i]) { up[i] = lo[i]; } } } int n = prob.nrows_; double * lo = prob.rlo_; double * up = prob.rup_; for (i = 0; i < n; i++) { if (up[i] < lo[i]) { if (up[i] < lo[i] - feasibilityTolerance && !fixInfeasibility) { // infeasible prob.status_ = 1; } else { up[i] = lo[i]; } } } delete [] prob.sol_; delete [] prob.acts_; delete [] prob.colstat_; prob.sol_ = NULL; prob.acts_ = NULL; prob.colstat_ = NULL; int ncolsNow = presolvedModel_->getNumCols(); CoinMemcpyN(prob.originalColumn_, ncolsNow, originalColumn_); #ifndef SLIM_CLP #ifndef NO_RTTI ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(originalModel->objectiveAsObject())); #else ClpQuadraticObjective * quadraticObj = NULL; if (originalModel->objectiveAsObject()->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective*>(originalModel->objectiveAsObject())); #endif if (quadraticObj) { // set up for subset char * mark = new char [ncols_]; memset(mark, 0, ncols_); CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective(); //const int * columnQuadratic = quadratic->getIndices(); //const CoinBigIndex * columnQuadraticStart = quadratic->getVectorStarts(); const int * columnQuadraticLength = quadratic->getVectorLengths(); //double * quadraticElement = quadratic->getMutableElements(); int numberColumns = quadratic->getNumCols(); ClpQuadraticObjective * newObj = new ClpQuadraticObjective(*quadraticObj, ncolsNow, originalColumn_); // and modify linear and check double * linear = newObj->linearObjective(); CoinMemcpyN(presolvedModel_->objective(), ncolsNow, linear); int iColumn; for ( iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnQuadraticLength[iColumn]) mark[iColumn] = 1; } // and new quadratic = newObj->quadraticObjective(); columnQuadraticLength = quadratic->getVectorLengths(); int numberColumns2 = quadratic->getNumCols(); for ( iColumn = 0; iColumn < numberColumns2; iColumn++) { if (columnQuadraticLength[iColumn]) mark[originalColumn_[iColumn]] = 0; } presolvedModel_->setObjective(newObj); delete newObj; // final check for ( iColumn = 0; iColumn < numberColumns; iColumn++) if (mark[iColumn]) printf("Quadratic column %d modified - may be okay\n", iColumn); delete [] mark; } #endif delete [] prob.originalColumn_; prob.originalColumn_ = NULL; int nrowsNow = presolvedModel_->getNumRows(); CoinMemcpyN(prob.originalRow_, nrowsNow, originalRow_); delete [] prob.originalRow_; prob.originalRow_ = NULL; #ifndef CLP_NO_STD if (!dropNames && originalModel->lengthNames()) { // Redo names int iRow; std::vector rowNames; rowNames.reserve(nrowsNow); for (iRow = 0; iRow < nrowsNow; iRow++) { int kRow = originalRow_[iRow]; rowNames.push_back(originalModel->rowName(kRow)); } int iColumn; std::vector columnNames; columnNames.reserve(ncolsNow); for (iColumn = 0; iColumn < ncolsNow; iColumn++) { int kColumn = originalColumn_[iColumn]; columnNames.push_back(originalModel->columnName(kColumn)); } presolvedModel_->copyNames(rowNames, columnNames); } else { presolvedModel_->setLengthNames(0); } #endif if (rowObjective_) { int iRow; #ifndef NDEBUG int k = -1; #endif int nObj = 0; for (iRow = 0; iRow < nrowsNow; iRow++) { int kRow = originalRow_[iRow]; #ifndef NDEBUG assert (kRow > k); k = kRow; #endif rowObjective_[iRow] = rowObjective_[kRow]; if (rowObjective_[iRow]) nObj++; } if (nObj) { printf("%d costed slacks\n", nObj); presolvedModel_->setRowObjective(rowObjective_); } } /* now clean up integer variables. This can modify original Don't do if dupcol added columns together */ int i; const char * information = presolvedModel_->integerInformation(); if ((prob.presolveOptions_ & 0x80000000) == 0 && information) { int numberChanges = 0; double * lower0 = originalModel_->columnLower(); double * upper0 = originalModel_->columnUpper(); double * lower = presolvedModel_->columnLower(); double * upper = presolvedModel_->columnUpper(); for (i = 0; i < ncolsNow; i++) { if (!information[i]) continue; int iOriginal = originalColumn_[i]; double lowerValue0 = lower0[iOriginal]; double upperValue0 = upper0[iOriginal]; double lowerValue = ceil(lower[i] - 1.0e-5); double upperValue = floor(upper[i] + 1.0e-5); lower[i] = lowerValue; upper[i] = upperValue; if (lowerValue > upperValue) { numberChanges++; presolvedModel_->messageHandler()->message(COIN_PRESOLVE_COLINFEAS, messages) << iOriginal << lowerValue << upperValue << CoinMessageEol; result = 1; } else { if (lowerValue > lowerValue0 + 1.0e-8) { lower0[iOriginal] = lowerValue; numberChanges++; } if (upperValue < upperValue0 - 1.0e-8) { upper0[iOriginal] = upperValue; numberChanges++; } } } if (numberChanges) { presolvedModel_->messageHandler()->message(COIN_PRESOLVE_INTEGERMODS, messages) << numberChanges << CoinMessageEol; if (!result && totalPasses > 0) { result = -1; // round again const CoinPresolveAction *paction = paction_; while (paction) { const CoinPresolveAction *next = paction->next; delete paction; paction = next; } paction_ = NULL; } } } } else if (prob.status_) { // infeasible or unbounded result = 1; // Put status in nelems_! nelems_ = - prob.status_; originalModel->setProblemStatus(prob.status_); } else { // no changes - model needs restoring after Lou's changes #ifndef CLP_NO_STD if (saveFile_ == "") { #endif delete presolvedModel_; presolvedModel_ = new ClpSimplex(*originalModel); // but we need to remove gaps ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(presolvedModel_->clpMatrix()); if (clpMatrix) { clpMatrix->getPackedMatrix()->removeGaps(); } #ifndef CLP_NO_STD } else { presolvedModel_ = originalModel; } presolvedModel_->dropNames(); #endif // drop integer information if wanted if (!keepIntegers) presolvedModel_->deleteIntegerInformation(); result = 2; } } if (result == 0 || result == 2) { int nrowsAfter = presolvedModel_->getNumRows(); int ncolsAfter = presolvedModel_->getNumCols(); CoinBigIndex nelsAfter = presolvedModel_->getNumElements(); presolvedModel_->messageHandler()->message(COIN_PRESOLVE_STATS, messages) << nrowsAfter << -(nrows_ - nrowsAfter) << ncolsAfter << -(ncols_ - ncolsAfter) << nelsAfter << -(nelems_ - nelsAfter) << CoinMessageEol; } else { destroyPresolve(); if (presolvedModel_ != originalModel_) delete presolvedModel_; presolvedModel_ = NULL; } return presolvedModel_; } Clp-1.15.10/src/MyMessageHandler.hpp0000644000076600007660000000433511510657452015556 0ustar coincoin/* $Id: MyMessageHandler.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 MyMessageHandler_H #define MyMessageHandler_H #include #include "CoinPragma.hpp" #include #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. In practice you might have */ class ClpSimplex; typedef std::vector StdVectorDouble; class MyMessageHandler : public CoinMessageHandler { public: /**@name Overrides */ //@{ virtual int print(); //@} /**@name set and get */ //@{ /// Model const ClpSimplex * model() const; void setModel(ClpSimplex * model); /// Get queue of feasible extreme points const std::deque & getFeasibleExtremePoints() const; /// Empty queue of feasible extreme points void clearFeasibleExtremePoints(); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ MyMessageHandler(); /// Constructor with pointer to model MyMessageHandler(ClpSimplex * model, FILE * userPointer = NULL); /** Destructor */ virtual ~MyMessageHandler(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ MyMessageHandler(const MyMessageHandler&); /** The copy constructor from an CoinSimplexMessageHandler. */ MyMessageHandler(const CoinMessageHandler&); MyMessageHandler& operator=(const MyMessageHandler&); /// Clone virtual CoinMessageHandler * clone() const ; //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Pointer back to model ClpSimplex * model_; /// Saved extreme points std::deque feasibleExtremePoints_; /// Iteration number so won't do same one twice int iterationNumber_; //@} }; #endif Clp-1.15.10/src/CoinAbcHelperFunctions.cpp0000644000076600007660000020221612240211604016670 0ustar coincoin/* $Id: CoinAbcHelperFunctions.cpp 1989 2013-11-11 17:27:32Z forrest $ */ // Copyright (C) 2003, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include #include #include #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #include "CoinTypes.hpp" #include "CoinFinite.hpp" #include "CoinAbcCommon.hpp" //#define AVX2 1 #if AVX2==1 #define set_const_v2df(bb,b) {double * temp=reinterpret_cast(&bb);temp[0]=b;temp[1]=b;} #endif #if INLINE_SCATTER==0 void CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL_SCATTER==0 for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL_SCATTER==1 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL_SCATTER==2 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } if ((number&2)!=0) { CoinSimplexInt iRow0 = thisIndex[number-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble value0 = thisElement[number-1]; CoinSimplexInt iRow1 = thisIndex[number-2]; CoinFactorizationDouble regionValue1 = region[iRow1]; CoinFactorizationDouble value1 = thisElement[number-2]; region[iRow0] = regionValue0 - value0 * pivotValue; region[iRow1] = regionValue1 - value1 * pivotValue; number-=2; } for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; CoinSimplexInt iRow2 = thisIndex[j-2]; CoinSimplexInt iRow3 = thisIndex[j-3]; CoinFactorizationDouble regionValue2 = region[iRow2]; CoinFactorizationDouble regionValue3 = region[iRow3]; region[iRow2] = regionValue2 - thisElement[j-2] * pivotValue; region[iRow3] = regionValue3 - thisElement[j-3] * pivotValue; } #elif UNROLL_SCATTER==3 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(static_cast(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } #endif #if INLINE_GATHER==0 CoinFactorizationDouble CoinAbcGatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL_GATHER==0 CoinFactorizationDouble pivotValue=0.0; for (CoinBigIndex j = 0; j < number; j ++ ) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; #else #error code #endif } #endif #if INLINE_MULTIPLY_ADD==0 void CoinAbcMultiplyIndexed(int number, const CoinFactorizationDouble * COIN_RESTRICT multiplier, const int * COIN_RESTRICT thisIndex, CoinSimplexDouble * COIN_RESTRICT region) { #ifndef INTEL_COMPILER // was #pragma simd #endif #if UNROLL_MULTIPLY_ADD==0 for (CoinSimplexInt i = 0; i < number; i ++ ) { CoinSimplexInt iRow = thisIndex[i]; CoinSimplexDouble value = region[iRow]; value *= multiplier[iRow]; region[iRow] = value; } #else #error code #endif } void CoinAbcMultiplyIndexed(int number, const long double * COIN_RESTRICT multiplier, const int * COIN_RESTRICT thisIndex, long double * COIN_RESTRICT region) { #ifndef INTEL_COMPILER // was #pragma simd #endif #if UNROLL_MULTIPLY_ADD==0 for (CoinSimplexInt i = 0; i < number; i ++ ) { CoinSimplexInt iRow = thisIndex[i]; long double value = region[iRow]; value *= multiplier[iRow]; region[iRow] = value; } #else #error code #endif } #endif double CoinAbcMaximumAbsElement(const double * region, int sizeIn) { int size=sizeIn; double maxValue = 0.0; //printf("a\n"); #ifndef INTEL_COMPILER // was #pragma simd #endif /*cilk_*/ for (int i = 0; i < size; i++) maxValue = CoinMax(maxValue, fabs(region[i])); return maxValue; } void CoinAbcMinMaxAbsElement(const double * region, int sizeIn,double & minimum , double & maximum) { double minValue=minimum; double maxValue=maximum; int size=sizeIn; //printf("b\n"); #ifndef INTEL_COMPILER // was #pragma simd #endif /*cilk_*/ for (int i=0;iNORMAL_LOW_VALUE&&valuekillIfLessThanThis) { if (value!=COIN_DBL_MAX) { value *= multiplier; if (value>killIfLessThanThis) region[i] *= multiplier; else region[i]=0.0; } } else { region[i]=0.0; } } } // maximum fabs(region[i]) and then region[i]*=multiplier double CoinAbcMaximumAbsElementAndScale(double * region, double multiplier,int sizeIn) { double maxValue=0.0; int size=sizeIn; //printf("f\n"); #ifndef INTEL_COMPILER // was #pragma simd #endif /*cilk_*/ for (int i=0;i=0); memmove(array,arrayFrom,size*sizeof(double)); double * endArray = array+size; double * endArrayFrom = arrayFrom+size; double * startZero = CoinMax(arrayFrom,endArray); memset(startZero,0,(endArrayFrom-startZero)*sizeof(double)); } // This compacts several sections and zeroes out end int CoinAbcCompact(int numberSections,int alreadyDone,double * array,const int * starts, const int * lengths) { int totalLength=alreadyDone; for (int i=0;itotalLength) { start=CoinMax(start,totalLength); memset(array+start,0,(end-start)*sizeof(double)); } alreadyDone += length; } return totalLength; } // This compacts several sections int CoinAbcCompact(int numberSections,int alreadyDone,int * array,const int * starts, const int * lengths) { for (int i=0;i=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; iRow0 = thisIndex[j-2]; iRow1 = thisIndex[j-3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j-2] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-3] * pivotValue; } } void CoinAbcScatterUpdate4NPlus1(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((number&3)==1); int iRow0 = thisIndex[number-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[number-1] * pivotValue; number -= 1; for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; iRow0 = thisIndex[j-2]; iRow1 = thisIndex[j-3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j-2] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-3] * pivotValue; } } void CoinAbcScatterUpdate4NPlus2(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((number&3)==2); int iRow0 = thisIndex[number-1]; int iRow1 = thisIndex[number-2]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[number-1] * pivotValue; region[iRow1] = regionValue1 - thisElement[number-2] * pivotValue; number -= 2; for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; iRow0 = thisIndex[j-2]; iRow1 = thisIndex[j-3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j-2] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-3] * pivotValue; } } void CoinAbcScatterUpdate4NPlus3(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((number&3)==3); int iRow0 = thisIndex[number-1]; int iRow1 = thisIndex[number-2]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[number-1] * pivotValue; region[iRow1] = regionValue1 - thisElement[number-2] * pivotValue; iRow0 = thisIndex[number-3]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[number-3] * pivotValue; number -= 3; for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; iRow0 = thisIndex[j-2]; iRow1 = thisIndex[j-3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j-2] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-3] * pivotValue; } } void CoinAbcScatterUpdate0(int numberIn, CoinFactorizationDouble /*multiplier*/, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT /*region*/) { #ifndef NDEBUG assert (numberIn==0); #endif } // start alternatives #if 0 void CoinAbcScatterUpdate1(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==1); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; } void CoinAbcScatterUpdate2(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==2); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); #if NEW_CHUNK_SIZE==2 int nFull=2&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #endif #if NEW_CHUNK_SIZE==4 element++; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; region[iColumn0]=value0; region[iColumn1]=value1; #endif } void CoinAbcScatterUpdate3(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==3); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); #if NEW_CHUNK_SIZE==2 int nFull=3&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #endif #if NEW_CHUNK_SIZE==2 element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; #else element+=2; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; int iColumn2=thisColumn[2]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; CoinFactorizationDouble value2=region[iColumn2]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; value2 += multiplier*element[2]; region[iColumn0]=value0; region[iColumn1]=value1; region[iColumn2]=value2; #endif } void CoinAbcScatterUpdate4(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==4); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=4&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } } void CoinAbcScatterUpdate5(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==5); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=5&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; } void CoinAbcScatterUpdate6(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==6); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=6&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #if NEW_CHUNK_SIZE==4 element++; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; region[iColumn0]=value0; region[iColumn1]=value1; #endif } void CoinAbcScatterUpdate7(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==7); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=7&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #if NEW_CHUNK_SIZE==2 element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; #else element+=2; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; int iColumn2=thisColumn[2]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; CoinFactorizationDouble value2=region[iColumn2]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; value2 += multiplier*element[2]; region[iColumn0]=value0; region[iColumn1]=value1; region[iColumn2]=value2; #endif } void CoinAbcScatterUpdate8(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==8); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=8&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } } void CoinAbcScatterUpdate4N(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((numberIn&3)==0); const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } } void CoinAbcScatterUpdate4NPlus1(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((numberIn&3)==1); const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; } void CoinAbcScatterUpdate4NPlus2(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((numberIn&3)==2); const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #if NEW_CHUNK_SIZE==4 element++; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; region[iColumn0]=value0; region[iColumn1]=value1; #endif } void CoinAbcScatterUpdate4NPlus3(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { assert ((numberIn&3)==3); const int * COIN_RESTRICT thisColumn = reinterpret_cast(element); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #if NEW_CHUNK_SIZE==2 element++; int iColumn0=thisColumn[0]; CoinFactorizationDouble value0=region[iColumn0]; value0 += multiplier*element[0]; region[iColumn0]=value0; #else element+=2; int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; int iColumn2=thisColumn[2]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; CoinFactorizationDouble value2=region[iColumn2]; value0 += multiplier*element[0]; value1 += multiplier*element[1]; value2 += multiplier*element[2]; region[iColumn0]=value0; region[iColumn1]=value1; region[iColumn2]=value2; #endif } #else // alternative #define CACHE_LINE_SIZE 16 #define OPERATION += #define functionName(zname) CoinAbc##zname #define ABC_CREATE_SCATTER_FUNCTION 1 #include "CoinAbcHelperFunctions.hpp" #undef OPERATION #undef functionName #define OPERATION -= #define functionName(zname) CoinAbc##zname##Subtract #include "CoinAbcHelperFunctions.hpp" #undef OPERATION #undef functionName #define OPERATION += #define functionName(zname) CoinAbc##zname##Add #include "CoinAbcHelperFunctions.hpp" scatterUpdate AbcScatterLow[]={ &CoinAbcScatterUpdate0, &CoinAbcScatterUpdate1, &CoinAbcScatterUpdate2, &CoinAbcScatterUpdate3, &CoinAbcScatterUpdate4, &CoinAbcScatterUpdate5, &CoinAbcScatterUpdate6, &CoinAbcScatterUpdate7, &CoinAbcScatterUpdate8}; scatterUpdate AbcScatterHigh[]={ &CoinAbcScatterUpdate4N, &CoinAbcScatterUpdate4NPlus1, &CoinAbcScatterUpdate4NPlus2, &CoinAbcScatterUpdate4NPlus3}; scatterUpdate AbcScatterLowSubtract[]={ &CoinAbcScatterUpdate0, &CoinAbcScatterUpdate1Subtract, &CoinAbcScatterUpdate2Subtract, &CoinAbcScatterUpdate3Subtract, &CoinAbcScatterUpdate4Subtract, &CoinAbcScatterUpdate5Subtract, &CoinAbcScatterUpdate6Subtract, &CoinAbcScatterUpdate7Subtract, &CoinAbcScatterUpdate8Subtract}; scatterUpdate AbcScatterHighSubtract[]={ &CoinAbcScatterUpdate4NSubtract, &CoinAbcScatterUpdate4NPlus1Subtract, &CoinAbcScatterUpdate4NPlus2Subtract, &CoinAbcScatterUpdate4NPlus3Subtract}; scatterUpdate AbcScatterLowAdd[]={ &CoinAbcScatterUpdate0, &CoinAbcScatterUpdate1Add, &CoinAbcScatterUpdate2Add, &CoinAbcScatterUpdate3Add, &CoinAbcScatterUpdate4Add, &CoinAbcScatterUpdate5Add, &CoinAbcScatterUpdate6Add, &CoinAbcScatterUpdate7Add, &CoinAbcScatterUpdate8Add}; scatterUpdate AbcScatterHighAdd[]={ &CoinAbcScatterUpdate4NAdd, &CoinAbcScatterUpdate4NPlus1Add, &CoinAbcScatterUpdate4NPlus2Add, &CoinAbcScatterUpdate4NPlus3Add}; #endif #include "CoinPragma.hpp" #include #include #include #include #include #include #include "CoinAbcCommonFactorization.hpp" #if 1 #if AVX2==1 #include "emmintrin.h" #elif AVX2==2 #include #elif AVX2==3 #include "avx2intrin.h" #endif #endif // cilk seems a bit fragile #define CILK_FRAGILE 0 #if CILK_FRAGILE>1 #undef cilk_spawn #undef cilk_sync #define cilk_spawn #define cilk_sync #define ONWARD 0 #elif CILK_FRAGILE==1 #define ONWARD 0 #else #define ONWARD 1 #endif #define BLOCKING1 8 // factorization strip #define BLOCKING2 8 // dgemm recursive #define BLOCKING3 32 // dgemm parallel void CoinAbcDgemm(int m, int n, int k, double * COIN_RESTRICT a,int lda, double * COIN_RESTRICT b,double * COIN_RESTRICT c #if ABC_PARALLEL==2 ,int parallelMode #endif ) { assert ((m&(BLOCKING8-1))==0&&(n&(BLOCKING8-1))==0&&(k&(BLOCKING8-1))==0); /* entry for column j and row i (when multiple of BLOCKING8) is at aBlocked+j*m+i*BLOCKING8 */ // k is always smallish if (m<=BLOCKING8&&n<=BLOCKING8) { assert (m==BLOCKING8&&n==BLOCKING8&&k==BLOCKING8); double * COIN_RESTRICT aBase2=a; double * COIN_RESTRICT bBase2=b; double * COIN_RESTRICT cBase2=c; for (int j=0;j(cBase2); //__m256d c1=_mm256_load_pd(cBase2+4); __m256d c1=*reinterpret_cast<__m256d *>(cBase2+4); for (int l=0;l (__builtin_ia32_vbroadcastsd256 (bBase2+l)); //__m256d a0 = _mm256_load_pd(aBase); __m256d a0=*reinterpret_cast<__m256d *>(aBase); //__m256d a1 = _mm256_load_pd(aBase+4); __m256d a1=*reinterpret_cast<__m256d *>(aBase+4); c0 -= bb*a0; c1 -= bb*a1; aBase += BLOCKING8; } //_mm256_store_pd (cBase2, c0); *reinterpret_cast<__m256d *>(cBase2)=c0; //_mm256_store_pd (cBase2+4, c1); *reinterpret_cast<__m256d *>(cBase2+4)=c1; #endif bBase2 += BLOCKING8; cBase2 += BLOCKING8; } } else if (m>n) { // make sure mNew1 multiple of BLOCKING8 #if BLOCKING8==8 int mNew1=((m+15)>>4)<<3; #elif BLOCKING8==4 int mNew1=((m+7)>>3)<<2; #elif BLOCKING8==2 int mNew1=((m+3)>>2)<<1; #else abort(); #endif assert (mNew1>0&&m-mNew1>0); #if ABC_PARALLEL==2 if (mNew1<=BLOCKING3||!parallelMode) { #endif //printf("splitMa mNew1 %d\n",mNew1); CoinAbcDgemm(mNew1,n,k,a,lda,b,c #if ABC_PARALLEL==2 ,0 #endif ); //printf("splitMb mNew1 %d\n",mNew1); CoinAbcDgemm(m-mNew1,n,k,a+mNew1*BLOCKING8,lda,b,c+mNew1*BLOCKING8 #if ABC_PARALLEL==2 ,0 #endif ); #if ABC_PARALLEL==2 } else { //printf("splitMa mNew1 %d\n",mNew1); cilk_spawn CoinAbcDgemm(mNew1,n,k,a,lda,b,c,ONWARD); //printf("splitMb mNew1 %d\n",mNew1); CoinAbcDgemm(m-mNew1,n,k,a+mNew1*BLOCKING8,lda,b,c+mNew1*BLOCKING8,ONWARD); cilk_sync; } #endif } else { // make sure nNew1 multiple of BLOCKING8 #if BLOCKING8==8 int nNew1=((n+15)>>4)<<3; #elif BLOCKING8==4 int nNew1=((n+7)>>3)<<2; #elif BLOCKING8==2 int nNew1=((n+3)>>2)<<1; #else abort(); #endif assert (nNew1>0&&n-nNew1>0); #if ABC_PARALLEL==2 if (nNew1<=BLOCKING3||!parallelMode) { #endif //printf("splitNa nNew1 %d\n",nNew1); CoinAbcDgemm(m,nNew1,k,a,lda,b,c #if ABC_PARALLEL==2 ,0 #endif ); //printf("splitNb nNew1 %d\n",nNew1); CoinAbcDgemm(m,n-nNew1,k,a,lda,b+lda*nNew1,c+lda*nNew1 #if ABC_PARALLEL==2 ,0 #endif ); #if ABC_PARALLEL==2 } else { //printf("splitNa nNew1 %d\n",nNew1); cilk_spawn CoinAbcDgemm(m,nNew1,k,a,lda,b,c,ONWARD); //printf("splitNb nNew1 %d\n",nNew1); CoinAbcDgemm(m,n-nNew1,k,a,lda,b+lda*nNew1,c+lda*nNew1,ONWARD); cilk_sync; } #endif } } #ifdef ABC_LONG_FACTORIZATION // Start long double version void CoinAbcDgemm(int m, int n, int k, long double * COIN_RESTRICT a,int lda, long double * COIN_RESTRICT b,long double * COIN_RESTRICT c #if ABC_PARALLEL==2 ,int parallelMode #endif ) { assert ((m&(BLOCKING8-1))==0&&(n&(BLOCKING8-1))==0&&(k&(BLOCKING8-1))==0); /* entry for column j and row i (when multiple of BLOCKING8) is at aBlocked+j*m+i*BLOCKING8 */ // k is always smallish if (m<=BLOCKING8&&n<=BLOCKING8) { assert (m==BLOCKING8&&n==BLOCKING8&&k==BLOCKING8); long double * COIN_RESTRICT aBase2=a; long double * COIN_RESTRICT bBase2=b; long double * COIN_RESTRICT cBase2=c; for (int j=0;j(cBase2); //__m256d c1=_mm256_load_pd(cBase2+4); __m256d c1=*reinterpret_cast<__m256d *>(cBase2+4); for (int l=0;l (__builtin_ia32_vbroadcastsd256 (bBase2+l)); //__m256d a0 = _mm256_load_pd(aBase); __m256d a0=*reinterpret_cast<__m256d *>(aBase); //__m256d a1 = _mm256_load_pd(aBase+4); __m256d a1=*reinterpret_cast<__m256d *>(aBase+4); c0 -= bb*a0; c1 -= bb*a1; aBase += BLOCKING8; } //_mm256_store_pd (cBase2, c0); *reinterpret_cast<__m256d *>(cBase2)=c0; //_mm256_store_pd (cBase2+4, c1); *reinterpret_cast<__m256d *>(cBase2+4)=c1; #endif bBase2 += BLOCKING8; cBase2 += BLOCKING8; } } else if (m>n) { // make sure mNew1 multiple of BLOCKING8 #if BLOCKING8==8 int mNew1=((m+15)>>4)<<3; #elif BLOCKING8==4 int mNew1=((m+7)>>3)<<2; #elif BLOCKING8==2 int mNew1=((m+3)>>2)<<1; #else abort(); #endif assert (mNew1>0&&m-mNew1>0); #if ABC_PARALLEL==2 if (mNew1<=BLOCKING3||!parallelMode) { #endif //printf("splitMa mNew1 %d\n",mNew1); CoinAbcDgemm(mNew1,n,k,a,lda,b,c #if ABC_PARALLEL==2 ,0 #endif ); //printf("splitMb mNew1 %d\n",mNew1); CoinAbcDgemm(m-mNew1,n,k,a+mNew1*BLOCKING8,lda,b,c+mNew1*BLOCKING8 #if ABC_PARALLEL==2 ,0 #endif ); #if ABC_PARALLEL==2 } else { //printf("splitMa mNew1 %d\n",mNew1); cilk_spawn CoinAbcDgemm(mNew1,n,k,a,lda,b,c,ONWARD); //printf("splitMb mNew1 %d\n",mNew1); CoinAbcDgemm(m-mNew1,n,k,a+mNew1*BLOCKING8,lda,b,c+mNew1*BLOCKING8,ONWARD); cilk_sync; } #endif } else { // make sure nNew1 multiple of BLOCKING8 #if BLOCKING8==8 int nNew1=((n+15)>>4)<<3; #elif BLOCKING8==4 int nNew1=((n+7)>>3)<<2; #elif BLOCKING8==2 int nNew1=((n+3)>>2)<<1; #else abort(); #endif assert (nNew1>0&&n-nNew1>0); #if ABC_PARALLEL==2 if (nNew1<=BLOCKING3||!parallelMode) { #endif //printf("splitNa nNew1 %d\n",nNew1); CoinAbcDgemm(m,nNew1,k,a,lda,b,c #if ABC_PARALLEL==2 ,0 #endif ); //printf("splitNb nNew1 %d\n",nNew1); CoinAbcDgemm(m,n-nNew1,k,a,lda,b+lda*nNew1,c+lda*nNew1 #if ABC_PARALLEL==2 ,0 #endif ); #if ABC_PARALLEL==2 } else { //printf("splitNa nNew1 %d\n",nNew1); cilk_spawn CoinAbcDgemm(m,nNew1,k,a,lda,b,c,ONWARD); //printf("splitNb nNew1 %d\n",nNew1); CoinAbcDgemm(m,n-nNew1,k,a,lda,b+lda*nNew1,c+lda*nNew1,ONWARD); cilk_sync; } #endif } } #endif // From Intel site // get AVX intrinsics #include // get CPUID capability //#include #define cpuid(func,ax,bx,cx,dx)\ __asm__ __volatile__ ("cpuid":\ "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func)); // written for clarity, not conciseness #define OSXSAVEFlag (1UL<<27) #define AVXFlag ((1UL<<28)|OSXSAVEFlag) #define VAESFlag ((1UL<<25)|AVXFlag|OSXSAVEFlag) #define FMAFlag ((1UL<<12)|AVXFlag|OSXSAVEFlag) #define CLMULFlag ((1UL<< 1)|AVXFlag|OSXSAVEFlag) bool DetectFeature(unsigned int feature) { int CPUInfo[4]; //, InfoType=1, ECX = 1; //__cpuidex(CPUInfo, 1, 1); // read the desired CPUID format cpuid(1,CPUInfo[0],CPUInfo[1],CPUInfo[2],CPUInfo[3]); unsigned int ECX = CPUInfo[2]; // the output of CPUID in the ECX register. if ((ECX & feature) != feature) // Missing feature return false; #if 0 long int val = _xgetbv(0); // read XFEATURE_ENABLED_MASK register if ((val&6) != 6) // check OS has enabled both XMM and YMM support. return false; #endif return true; } Clp-1.15.10/src/ClpPlusMinusOneMatrix.hpp0000644000076600007660000003141311510657452016610 0ustar coincoin/* $Id: ClpPlusMinusOneMatrix.hpp 1665 2011-01-04 17:55:54Z lou $ */ // 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 ClpPlusMinusOneMatrix_H #define ClpPlusMinusOneMatrix_H #include "CoinPragma.hpp" #include "ClpMatrixBase.hpp" /** This implements a simple +- one matrix as derived from ClpMatrixBase. */ class ClpPlusMinusOneMatrix : public ClpMatrixBase { public: /**@name Useful methods */ //@{ /// Return a complete CoinPackedMatrix virtual CoinPackedMatrix * getPackedMatrix() const; /** Whether the packed matrix is column major ordered or not. */ virtual bool isColOrdered() const ; /** Number of entries in the packed matrix. */ virtual CoinBigIndex getNumElements() const; /** Number of columns. */ virtual int getNumCols() const { return numberColumns_; } /** Number of rows. */ virtual int getNumRows() const { return numberRows_; } /** A vector containing the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const double * getElements() const; /** A vector containing the minor indices of the elements in the packed matrix. Note that there might be gaps in this list, entries that do not belong to any major-dimension vector. To get the actual elements one should look at this vector together with vectorStarts and vectorLengths. */ virtual const int * getIndices() const { return indices_; } // and for advanced use int * getMutableIndices() const { return indices_; } virtual const CoinBigIndex * getVectorStarts() const; /** The lengths of the major-dimension vectors. */ virtual const int * getVectorLengths() const; /** Delete the columns whose indices are listed in indDel. */ virtual void deleteCols(const int numDel, const int * indDel); /** Delete the rows whose indices are listed in indDel. */ virtual void deleteRows(const int numDel, const int * indDel); /// Append Columns virtual void appendCols(int number, const CoinPackedVectorBase * const * columns); /// Append Rows virtual void appendRows(int number, const CoinPackedVectorBase * const * rows); #ifndef SLIM_CLP /** Append a set of rows/columns to the end of the matrix. Returns number of errors i.e. if any of the new rows/columns contain an index that's larger than the number of columns-1/rows-1 (if numberOther>0) or duplicates If 0 then rows, 1 if columns */ virtual int appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther = -1); #endif /** Returns a new matrix in reverse order without gaps */ virtual ClpMatrixBase * reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual CoinBigIndex countBasis( const int * whichColumn, int & numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex * model, const int * whichColumn, int & numberColumnBasic, int * row, int * start, int * rowCount, int * columnCount, CoinFactorizationDouble * element); /** Given positive integer weights for each row fills in sum of weights for each column (and slack). Returns weights vector */ virtual CoinBigIndex * dubiousWeights(const ClpSimplex * model, int * inputWeights) const; /** Returns largest and smallest elements of both signs. Largest refers to largest absolute value. */ virtual void rangeOfElements(double & smallestNegative, double & largestNegative, double & smallestPositive, double & largestPositive); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex * model, CoinIndexedVector * rowArray, int column) const ; /** Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex * model, CoinIndexedVector * rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex * model, CoinIndexedVector * rowArray, int column, double multiplier) const ; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex * model, double * array, int column, double multiplier) const; /// Allow any parts of a created CoinMatrix to be deleted virtual void releasePackedMatrix() const; /** Set the dimensions of the matrix. In effect, append new empty columns/rows to the matrix. A negative number for either dimension means that that dimension doesn't change. Otherwise the new dimensions MUST be at least as large as the current ones otherwise an exception is thrown. */ virtual void setDimensions(int numrows, int numcols); /// Just checks matrix valid - will say if dimensions not quite right if detail void checkValid(bool detail) const; //@} /**@name Matrix times vector methods */ //@{ /** Return y + A * scalar *x in y. @pre x must be of size numColumns() @pre y must be of size numRows() */ virtual void times(double scalar, const double * x, double * y) const; /// And for scaling virtual void times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const; /** Return y + x * scalar * A in y. @pre x must be of size numRows() @pre y must be of size numColumns() */ virtual void transposeTimes(double scalar, const double * x, double * y) const; /// And for scaling virtual void transposeTimes(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale, double * spare = NULL) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex. This version uses row copy*/ virtual void transposeTimesByRow(const ClpSimplex * model, double scalar, const CoinIndexedVector * x, CoinIndexedVector * y, CoinIndexedVector * z) const; /** Return x *A in z but just for indices in y. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex * model, const CoinIndexedVector * x, const CoinIndexedVector * y, CoinIndexedVector * z) const; /** Returns true if can combine transposeTimes and subsetTransposeTimes and if it would be faster */ virtual bool canCombine(const ClpSimplex * model, const CoinIndexedVector * pi) const; /// Updates two arrays for steepest virtual void transposeTimes2(const ClpSimplex * model, const CoinIndexedVector * pi1, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * spare, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); /// Updates second array for steepest and does devex weights virtual void subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor); //@} /**@name Other */ //@{ /// Return starts of +1s inline CoinBigIndex * startPositive() const { return startPositive_; } /// Return starts of -1s inline CoinBigIndex * startNegative() const { return startNegative_; } //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpPlusMinusOneMatrix(); /** Destructor */ virtual ~ClpPlusMinusOneMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpPlusMinusOneMatrix(const ClpPlusMinusOneMatrix&); /** The copy constructor from an CoinPlusMinusOneMatrix. If not a valid matrix then getIndices will be NULL and startPositive[0] will have number of +1, startPositive[1] will have number of -1, startPositive[2] will have number of others, */ ClpPlusMinusOneMatrix(const CoinPackedMatrix&); /// Constructor from arrays ClpPlusMinusOneMatrix(int numberRows, int numberColumns, bool columnOrdered, const int * indices, const CoinBigIndex * startPositive, const CoinBigIndex * startNegative); /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpPlusMinusOneMatrix (const ClpPlusMinusOneMatrix & wholeModel, int numberRows, const int * whichRows, int numberColumns, const int * whichColumns); ClpPlusMinusOneMatrix& operator=(const ClpPlusMinusOneMatrix&); /// Clone virtual ClpMatrixBase * clone() const ; /** Subset clone (without gaps). Duplicates are allowed and order is as given */ virtual ClpMatrixBase * subsetClone ( int numberRows, const int * whichRows, int numberColumns, const int * whichColumns) const ; /// pass in copy (object takes ownership) void passInCopy(int numberRows, int numberColumns, bool columnOrdered, int * indices, CoinBigIndex * startPositive, CoinBigIndex * startNegative); /// Says whether it can do partial pricing virtual bool canDoPartialPricing() const; /// Partial pricing virtual void partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// For fake CoinPackedMatrix mutable CoinPackedMatrix * matrix_; mutable int * lengths_; /// Start of +1's for each CoinBigIndex * startPositive_; /// Start of -1's for each CoinBigIndex * startNegative_; /// Data -1, then +1 rows in pairs (row==-1 if one entry) int * indices_; /// Number of rows int numberRows_; /// Number of columns int numberColumns_; /// True if column ordered bool columnOrdered_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyBase.hpp0000644000076600007660000002150111552534715015375 0ustar coincoin/* $Id: ClpCholeskyBase.hpp 1722 2011-04-17 09:58:37Z 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 ClpCholeskyBase_H #define ClpCholeskyBase_H #include "CoinPragma.hpp" #include "CoinTypes.hpp" //#define CLP_LONG_CHOLESKY 0 #ifndef CLP_LONG_CHOLESKY #define CLP_LONG_CHOLESKY 0 #endif /* valid combinations are CLP_LONG_CHOLESKY 0 and COIN_LONG_WORK 0 CLP_LONG_CHOLESKY 1 and COIN_LONG_WORK 1 CLP_LONG_CHOLESKY 2 and COIN_LONG_WORK 1 */ #if COIN_LONG_WORK==0 #if CLP_LONG_CHOLESKY>0 #define CHOLESKY_BAD_COMBINATION #endif #else #if CLP_LONG_CHOLESKY==0 #define CHOLESKY_BAD_COMBINATION #endif #endif #ifdef CHOLESKY_BAD_COMBINATION # warning("Bad combination of CLP_LONG_CHOLESKY and COIN_BIG_DOUBLE/COIN_LONG_WORK"); "Bad combination of CLP_LONG_CHOLESKY and COIN_LONG_WORK" #endif #if CLP_LONG_CHOLESKY>1 typedef long double longDouble; #define CHOL_SMALL_VALUE 1.0e-15 #elif CLP_LONG_CHOLESKY==1 typedef double longDouble; #define CHOL_SMALL_VALUE 1.0e-11 #else typedef double longDouble; #define CHOL_SMALL_VALUE 1.0e-11 #endif class ClpInterior; class ClpCholeskyDense; class ClpMatrixBase; /** Base class for Clp Cholesky factorization Will do better factorization. very crude ordering Derived classes may be using more sophisticated methods */ class ClpCholeskyBase { public: /**@name Virtual methods that the derived classes may provide */ //@{ /** Orders rows and saves pointer to matrix.and model. returns non-zero if not enough memory. You can use preOrder to set up ADAT If using default symbolic etc then must set sizeFactor_ to size of input matrix to order (and to symbolic). Also just permute_ and permuteInverse_ should be created */ virtual int order(ClpInterior * model); /** Does Symbolic factorization given permutation. This is called immediately after order. If user provides this then user must provide factorize and solve. Otherwise the default factorization is used returns non-zero if not enough memory */ virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const CoinWorkDouble * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (CoinWorkDouble * region) ; /** Uses factorization to solve. - given as if KKT. region1 is rows+columns, region2 is rows */ virtual void solveKKT (CoinWorkDouble * region1, CoinWorkDouble * region2, const CoinWorkDouble * diagonal, CoinWorkDouble diagonalScaleFactor); private: /// AMD ordering int orderAMD(); public: //@} /**@name Gets */ //@{ /// status. Returns status inline int status() const { return status_; } /// numberRowsDropped. Number of rows gone inline int numberRowsDropped() const { return numberRowsDropped_; } /// reset numberRowsDropped and rowsDropped. void resetRowsDropped(); /// rowsDropped - which rows are gone inline char * rowsDropped() const { return rowsDropped_; } /// choleskyCondition. inline double choleskyCondition() const { return choleskyCondition_; } /// goDense i.e. use dense factoriaztion if > this (default 0.7). inline double goDense() const { return goDense_; } /// goDense i.e. use dense factoriaztion if > this (default 0.7). inline void setGoDense(double value) { goDense_ = value; } /// rank. Returns rank inline int rank() const { return numberRows_ - numberRowsDropped_; } /// Return number of rows inline int numberRows() const { return numberRows_; } /// Return size inline CoinBigIndex size() const { return sizeFactor_; } /// Return sparseFactor inline longDouble * sparseFactor() const { return sparseFactor_; } /// Return diagonal inline longDouble * diagonal() const { return diagonal_; } /// Return workDouble inline longDouble * workDouble() const { return workDouble_; } /// If KKT on inline bool kkt() const { return doKKT_; } /// Set KKT inline void setKKT(bool yesNo) { doKKT_ = yesNo; } /// Set integer parameter inline void setIntegerParameter(int i, int value) { integerParameters_[i] = value; } /// get integer parameter inline int getIntegerParameter(int i) { return integerParameters_[i]; } /// Set double parameter inline void setDoubleParameter(int i, double value) { doubleParameters_[i] = value; } /// get double parameter inline double getDoubleParameter(int i) { return doubleParameters_[i]; } //@} public: /**@name Constructors, destructor */ //@{ /** Constructor which has dense columns activated. Default is off. */ ClpCholeskyBase(int denseThreshold = -1); /** Destructor (has to be public) */ virtual ~ClpCholeskyBase(); /// Copy ClpCholeskyBase(const ClpCholeskyBase&); /// Assignment ClpCholeskyBase& operator=(const ClpCholeskyBase&); //@} //@{ ///@name Other /// Clone virtual ClpCholeskyBase * clone() const; /// Returns type inline int type() const { if (doKKT_) return 100; else return type_; } protected: /// Sets type inline void setType(int type) { type_ = type; } /// model. inline void setModel(ClpInterior * model) { model_ = model; } //@} /**@name Symbolic, factor and solve */ //@{ /** Symbolic1 - works out size without clever stuff. Uses upper triangular as much easier. Returns size */ int symbolic1(const CoinBigIndex * Astart, const int * Arow); /** Symbolic2 - Fills in indices Uses lower triangular so can do cliques etc */ void symbolic2(const CoinBigIndex * Astart, const int * Arow); /** Factorize - filling in rowsDropped and returning number dropped in integerParam. */ void factorizePart2(int * rowsDropped) ; /** solve - 1 just first half, 2 just second half - 3 both. If 1 and 2 then diagonal has sqrt of inverse otherwise inverse */ void solve(CoinWorkDouble * region, int type); /// Forms ADAT - returns nonzero if not enough memory int preOrder(bool lowerTriangular, bool includeDiagonal, bool doKKT); /// Updates dense part (broken out for profiling) void updateDense(longDouble * d, /*longDouble * work,*/ int * first); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// type (may be useful) if > 20 do KKT int type_; /// Doing full KKT (only used if default symbolic and factorization) bool doKKT_; /// Go dense at this fraction double goDense_; /// choleskyCondition. double choleskyCondition_; /// model. ClpInterior * model_; /// numberTrials. Number of trials before rejection int numberTrials_; /// numberRows. Number of Rows in factorization int numberRows_; /// status. Status of factorization int status_; /// rowsDropped char * rowsDropped_; /// permute inverse. int * permuteInverse_; /// main permute. int * permute_; /// numberRowsDropped. Number of rows gone int numberRowsDropped_; /// sparseFactor. longDouble * sparseFactor_; /// choleskyStart - element starts CoinBigIndex * choleskyStart_; /// choleskyRow (can be shorter than sparsefactor) int * choleskyRow_; /// Index starts CoinBigIndex * indexStart_; /// Diagonal longDouble * diagonal_; /// double work array longDouble * workDouble_; /// link array int * link_; // Integer work array CoinBigIndex * workInteger_; // Clique information int * clique_; /// sizeFactor. CoinBigIndex sizeFactor_; /// Size of index array CoinBigIndex sizeIndex_; /// First dense row int firstDense_; /// integerParameters int integerParameters_[64]; /// doubleParameters; double doubleParameters_[64]; /// Row copy of matrix ClpMatrixBase * rowCopy_; /// Dense indicators char * whichDense_; /// Dense columns (updated) longDouble * denseColumn_; /// Dense cholesky ClpCholeskyDense * dense_; /// Dense threshold (for taking out of Cholesky) int denseThreshold_; //@} }; #endif Clp-1.15.10/src/ClpCholeskyTaucs.hpp0000644000076600007660000000456511510657452015613 0ustar coincoin/* $Id: ClpCholeskyTaucs.hpp 1665 2011-01-04 17:55:54Z 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 ClpCholeskyTaucs_H #define ClpCholeskyTaucs_H #include "taucs.h" #include "ClpCholeskyBase.hpp" class ClpMatrixBase; /** Taucs class for Clp Cholesky factorization If you wish to use Sivan Toledo's TAUCS code see http://www.tau.ac.il/~stoledo/taucs/ for terms of use The taucs.h file was modified to put #ifdef __cplusplus extern "C"{ #endif after line 440 (#endif) and #ifdef __cplusplus } #endif at end I also modified LAPACK dpotf2.f (two places) to change the GO TO 30 on AJJ.Lt.0.0 to IF( AJJ.LE.1.0e-20 ) THEN AJJ = 1.0e100; ELSE AJJ = SQRT( AJJ ) END IF */ class ClpCholeskyTaucs : public ClpCholeskyBase { public: /**@name Virtual methods that the derived classes provides */ //@{ /** Orders rows and saves pointer to matrix.and model. Returns non-zero if not enough memory */ virtual int order(ClpInterior * model) ; /// Dummy virtual int symbolic(); /** Factorize - filling in rowsDropped and returning number dropped. If return code negative then out of memory */ virtual int factorize(const double * diagonal, int * rowsDropped) ; /** Uses factorization to solve. */ virtual void solve (double * region) ; //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpCholeskyTaucs(); /** Destructor */ virtual ~ClpCholeskyTaucs(); // Copy ClpCholeskyTaucs(const ClpCholeskyTaucs&); // Assignment ClpCholeskyTaucs& operator=(const ClpCholeskyTaucs&); /// Clone virtual ClpCholeskyBase * clone() const ; //@} private: /**@name Data members */ //@{ /// Taucs matrix (== sparseFactor etc) taucs_ccs_matrix * matrix_; /// Taucs factor void * factorization_; /// sparseFactor. double * sparseFactorT_; /// choleskyStart CoinBigIndex * choleskyStartT_; /// choleskyRow int * choleskyRowT_; /// sizeFactor. CoinBigIndex sizeFactorT_; /// Row copy of matrix ClpMatrixBase * rowCopyT_; //@} }; #endif Clp-1.15.10/src/ClpSimplexDual.cpp0000644000076600007660000122446712252354371015260 0ustar coincoin/* $Id: ClpSimplexDual.cpp 2006 2013-12-12 15:40: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). /* Notes on implementation of dual simplex algorithm. When dual feasible: If primal feasible, we are optimal. Otherwise choose an infeasible basic variable to leave basis (normally going to nearest bound) (B). We now need to find an incoming variable which will leave problem dual feasible so we get the row of the tableau corresponding to the basic variable (with the correct sign depending if basic variable above or below feasibility region - as that affects whether reduced cost on outgoing variable has to be positive or negative). We now perform a ratio test to determine which incoming variable will preserve dual feasibility (C). If no variable found then problem is infeasible (in primal sense). If there is a variable, we then perform pivot and repeat. Trivial? ------------------------------------------- A) How do we get dual feasible? If all variables have bounds then it is trivial to get feasible by putting non-basic variables to correct bounds. OSL did not have a phase 1/phase 2 approach but instead effectively put fake bounds on variables and this is the approach here, although I had hoped to make it cleaner. If there is a weight of X on getting dual feasible: Non-basic variables with negative reduced costs are put to lesser of their upper bound and their lower bound + X. Similarly, mutatis mutandis, for positive reduced costs. Free variables should normally be in basis, otherwise I have coding which may be able to come out (and may not be correct). In OSL, this weight was changed heuristically, here at present it is only increased if problem looks finished. If problem is feasible I check for unboundedness. If not unbounded we could play with going into primal. As long as weights increase any algorithm would be finite. B) Which outgoing variable to choose is a virtual base class. For difficult problems steepest edge is preferred while for very easy (large) problems we will need partial scan. C) Sounds easy, but this is hardest part of algorithm. 1) Instead of stopping at first choice, we may be able to flip that variable to other bound and if objective still improving choose again. These mini iterations can increase speed by orders of magnitude but we may need to go to more of a bucket choice of variable rather than looking at them one by one (for speed). 2) Accuracy. Reduced costs may be of wrong sign but less than tolerance. Pivoting on these makes objective go backwards. OSL modified cost so a zero move was made, Gill et al (in primal analogue) modified so a strictly positive move was made. It is not quite as neat in dual but that is what we try and do. The two problems are that re-factorizations can change reduced costs above and below tolerances and that when finished we need to reset costs and try again. 3) Degeneracy. Gill et al helps but may not be enough. We may need more. Also it can improve speed a lot if we perturb the costs significantly. References: Forrest and Goldfarb, Steepest-edge simplex algorithms for linear programming - Mathematical Programming 1992 Forrest and Tomlin, Implementing the simplex method for the Optimization Subroutine Library - IBM Systems Journal 1992 Gill, Murray, Saunders, Wright A Practical Anti-Cycling Procedure for Linear and Nonlinear Programming SOL report 1988 TODO: a) Better recovery procedures. At present I never check on forward progress. There is checkpoint/restart with reducing re-factorization frequency, but this is only on singular factorizations. b) Fast methods for large easy problems (and also the option for the code to automatically choose which method). c) We need to be able to stop in various ways for OSI - this is fairly easy. */ #ifdef COIN_DEVELOP #undef COIN_DEVELOP #define COIN_DEVELOP 2 #endif #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpHelperFunctions.hpp" #include "ClpSimplexDual.hpp" #include "ClpEventHandler.hpp" #include "ClpFactorization.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "CoinFloatEqual.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpMessage.hpp" #include "ClpLinearObjective.hpp" #include #include #include #include #include //#define CLP_DEBUG 1 // To force to follow another run put logfile name here and define //#define FORCE_FOLLOW #ifdef FORCE_FOLLOW static FILE * fpFollow = NULL; static char * forceFile = "old.log"; static int force_in = -1; static int force_out = -1; static int force_iteration = 0; #endif //#define VUB #ifdef VUB extern int * vub; extern int * toVub; extern int * nextDescendent; #endif #ifdef NDEBUG #define NDEBUG_CLP #endif #ifndef CLP_INVESTIGATE #define NDEBUG_CLP #endif // dual /* *** Method This is a vanilla version of dual simplex. It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of dualBound_ being given to getting dual feasible. In this version I have used the idea that this weight can be thought of as a fake bound. If the distance between the lower and upper bounds on a variable is less than the feasibility weight then we are always better off flipping to other bound to make dual feasible. If the distance is greater then we make up a fake bound dualBound_ away from one bound. If we end up optimal or primal infeasible, we check to see if bounds okay. If so we have finished, if not we increase dualBound_ and continue (after checking if unbounded). I am undecided about free variables - there is coding but I am not sure about it. At present I put them in basis anyway. The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find outgoing variable. This will be changed to keep an updated list of infeasibilities (or squares if steepest edge). Also on easy problems we don't need full scan - just pick first reasonable. One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure of the exact details. The flow of dual is three while loops as follows: while (not finished) { while (not clean solution) { Factorize and/or clean up solution by flipping variables so dual feasible. If looks finished check fake dual bounds. Repeat until status is iterating (-1) or finished (0,1,2) } while (status==-1) { Iterate until no pivot in or out or time to re-factorize. Flow is: choose pivot row (outgoing variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc. Get pivot row in tableau Choose incoming column. If we don't find one then we look primal infeasible so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason) If we do find incoming column, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration (we will need to implement flagging of basic variables sometime) and break to re-factorize. If minor error re-factorize after iteration. Update everything (this may involve flipping variables to stay dual feasible. } } At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort. Needs partial scan pivot out option. Needs dantzig, uninitialized and full steepest edge options (can still use partial scan) May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations. I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance. */ #define CLEAN_FIXED 0 // Startup part of dual (may be extended to other algorithms) int ClpSimplexDual::startupSolve(int ifValuesPass, double * saveDuals, int startFinishOptions) { // If values pass then save given duals round check solution // sanity check // initialize - no values pass and algorithm_ is -1 // put in standard form (and make row copy) // create modifiable copies of model rim and do optional scaling // If problem looks okay // Do initial factorization // If user asked for perturbation - do it numberFake_ = 0; // Number of variables at fake bounds numberChanged_ = 0; // Number of variables with changed costs if (!startup(0, startFinishOptions)) { int usePrimal = 0; // looks okay // Superbasic variables not allowed // If values pass then scale pi if (ifValuesPass) { if (problemStatus_ && perturbation_ < 100) usePrimal = perturb(); int i; if (scalingFlag_ > 0) { for (i = 0; i < numberRows_; i++) { dual_[i] = saveDuals[i] * inverseRowScale_[i]; } } else { CoinMemcpyN(saveDuals, numberRows_, dual_); } // now create my duals for (i = 0; i < numberRows_; i++) { // slack double value = dual_[i]; value += rowObjectiveWork_[i]; saveDuals[i+numberColumns_] = value; } CoinMemcpyN(objectiveWork_, numberColumns_, saveDuals); transposeTimes(-1.0, dual_, saveDuals); // make reduced costs okay for (i = 0; i < numberColumns_; i++) { if (getStatus(i) == atLowerBound) { if (saveDuals[i] < 0.0) { //if (saveDuals[i]<-1.0e-3) //printf("bad dj at lb %d %g\n",i,saveDuals[i]); saveDuals[i] = 0.0; } } else if (getStatus(i) == atUpperBound) { if (saveDuals[i] > 0.0) { //if (saveDuals[i]>1.0e-3) //printf("bad dj at ub %d %g\n",i,saveDuals[i]); saveDuals[i] = 0.0; } } } CoinMemcpyN(saveDuals, (numberColumns_ + numberRows_), dj_); // set up possible ones for (i = 0; i < numberRows_ + numberColumns_; i++) clearPivoted(i); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (fabs(saveDuals[iPivot]) > dualTolerance_) { if (getStatus(iPivot) != isFree) setPivoted(iPivot); } } } else if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) { // set up possible ones for (int i = 0; i < numberRows_ + numberColumns_; i++) clearPivoted(i); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]) { setPivoted(iPivot); } } } double objectiveChange; assert (!numberFake_); assert (numberChanged_ == 0); if (!numberFake_) // if nonzero then adjust changeBounds(1, NULL, objectiveChange); if (!ifValuesPass) { // Check optimal if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_) problemStatus_ = 0; } if (problemStatus_ < 0 && perturbation_ < 100) { bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; if (!inCbcOrOther) usePrimal = perturb(); // Can't get here if values pass gutsOfSolution(NULL, NULL); #ifdef CLP_INVESTIGATE if (numberDualInfeasibilities_) printf("ZZZ %d primal %d dual - sumdinf %g\n", numberPrimalInfeasibilities_, numberDualInfeasibilities_, sumDualInfeasibilities_); #endif if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } if (inCbcOrOther) { if (numberPrimalInfeasibilities_) { usePrimal = perturb(); if (perturbation_ >= 101) { computeDuals(NULL); //gutsOfSolution(NULL,NULL); checkDualSolution(); // recompute objective } } else if (numberDualInfeasibilities_) { problemStatus_ = 10; if ((moreSpecialOptions_ & 32) != 0 && false) problemStatus_ = 0; // say optimal!! #if COIN_DEVELOP>2 printf("returning at %d\n", __LINE__); #endif return 1; // to primal } } } else if (!ifValuesPass) { gutsOfSolution(NULL, NULL); // double check if (numberDualInfeasibilities_ || numberPrimalInfeasibilities_) problemStatus_ = -1; } if (usePrimal) { problemStatus_ = 10; #if COIN_DEVELOP>2 printf("returning to use primal (no obj) at %d\n", __LINE__); #endif } return usePrimal; } else { return 1; } } void ClpSimplexDual::finishSolve(int startFinishOptions) { assert (problemStatus_ || !sumPrimalInfeasibilities_); // clean up finish(startFinishOptions); } //#define CLP_REPORT_PROGRESS #ifdef CLP_REPORT_PROGRESS static int ixxxxxx = 0; static int ixxyyyy = 90; #endif #ifdef CLP_INVESTIGATE_SERIAL static int z_reason[7] = {0, 0, 0, 0, 0, 0, 0}; static int z_thinks = -1; #endif void ClpSimplexDual::gutsOfDual(int ifValuesPass, double * & saveDuals, int initialStatus, ClpDataSave & data) { #ifdef CLP_INVESTIGATE_SERIAL z_reason[0]++; z_thinks = -1; int nPivots = 9999; #endif double largestPrimalError = 0.0; double largestDualError = 0.0; // Start can skip some things in transposeTimes specialOptions_ |= 131072; int lastCleaned = 0; // last time objective or bounds cleaned up // This says whether to restore things etc // startup will have factorized so can skip int factorType = 0; // Start check for cycles progress_.startCheck(); // Say change made on first iteration changeMade_ = 1; // Say last objective infinite //lastObjectiveValue_=-COIN_DBL_MAX; progressFlag_ = 0; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick // does not seem to work too well - do some more work if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_&1048576)==0 && initialStatus != 10) { perturb(); // Can't get here if values pass gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } // see if in Cbc etc bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; #if 0 bool gotoPrimal = false; if (inCbcOrOther && numberIterations_ > disasterArea_ + numberRows_ && numberDualInfeasibilitiesWithoutFree_ && largestDualError_ > 1.0e-1) { if (!disasterArea_) { printf("trying all slack\n"); // try all slack basis allSlackBasis(true); disasterArea_ = 2 * numberRows_; } else { printf("going to primal\n"); // go to primal gotoPrimal = true; allSlackBasis(true); } } #endif bool disaster = false; if (disasterArea_ && inCbcOrOther && disasterArea_->check()) { disasterArea_->saveInfo(); disaster = true; } // may factorize, checks if problem finished statusOfProblemInDual(lastCleaned, factorType, saveDuals, data, ifValuesPass); largestPrimalError = CoinMax(largestPrimalError, largestPrimalError_); largestDualError = CoinMax(largestDualError, largestDualError_); if (disaster) problemStatus_ = 3; // If values pass then do easy ones on first time if (ifValuesPass && progress_.lastIterationNumber(0) < 0 && saveDuals) { doEasyOnesInValuesPass(saveDuals); } // Say good factorization factorType = 1; if (data.sparseThreshold_) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } // exit if victory declared if (problemStatus_ >= 0) break; // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && !saveDuals)) { problemStatus_ = 3; break; } if (ifValuesPass && !saveDuals) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Do iterations int returnCode = whileIterating(saveDuals, ifValuesPass); if (problemStatus_ == 1 && (progressFlag_&8) != 0 && fabs(objectiveValue_) > 1.0e10 ) problemStatus_ = 10; // infeasible - but has looked feasible #ifdef CLP_INVESTIGATE_SERIAL nPivots = factorization_->pivots(); #endif if (!problemStatus_ && factorization_->pivots()) computeDuals(NULL); // need to compute duals if (returnCode == -2) factorType = 3; } #ifdef CLP_INVESTIGATE_SERIAL // NOTE - can fail if parallel if (z_thinks != -1) { assert (z_thinks < 4); if ((!factorization_->pivots() && nPivots < 20) && z_thinks >= 0 && z_thinks < 2) z_thinks += 4; z_reason[1+z_thinks]++; } if ((z_reason[0] % 1000) == 0) { printf("Reason"); for (int i = 0; i < 7; i++) printf(" %d", z_reason[i]); printf("\n"); } #endif // Stop can skip some things in transposeTimes specialOptions_ &= ~131072; largestPrimalError_ = largestPrimalError; largestDualError_ = largestDualError; } int ClpSimplexDual::dual(int ifValuesPass, int startFinishOptions) { //handler_->setLogLevel(63); //yprintf("STARTing dual %d rows\n",numberRows_); bestObjectiveValue_ = -COIN_DBL_MAX; algorithm_ = -1; moreSpecialOptions_ &= ~16; // clear check replaceColumn accuracy // save data ClpDataSave data = saveData(); double * saveDuals = NULL; int saveDont = dontFactorizePivots_; if ((specialOptions_ & 2048) == 0) dontFactorizePivots_ = 0; else if(!dontFactorizePivots_) dontFactorizePivots_ = 20; if (ifValuesPass) { saveDuals = new double [numberRows_+numberColumns_]; CoinMemcpyN(dual_, numberRows_, saveDuals); } if (alphaAccuracy_ != -1.0) alphaAccuracy_ = 1.0; int returnCode = startupSolve(ifValuesPass, saveDuals, startFinishOptions); // Save so can see if doing after primal int initialStatus = problemStatus_; if (!returnCode && !numberDualInfeasibilities_ && !numberPrimalInfeasibilities_ && perturbation_ < 101) { returnCode = 1; // to skip gutsOfDual problemStatus_ = 0; } if (!returnCode) gutsOfDual(ifValuesPass, saveDuals, initialStatus, data); if (!problemStatus_) { // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit)) { // actually infeasible on objective problemStatus_ = 1; secondaryStatus_ = 1; } } // If infeasible but primal errors - try dual if (problemStatus_==1 && numberPrimalInfeasibilities_) { bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; double factor = (!inCbcOrOther) ? 1.0 : 0.3; double averageInfeasibility = sumPrimalInfeasibilities_/ static_cast(numberPrimalInfeasibilities_); if (averageInfeasibility 0) { for (i = 0; i < numberRows_; i++) { dual_[i] = saveDuals[i] * inverseRowScale_[i]; } } else { CoinMemcpyN(saveDuals, numberRows_, dual_); } // now create my duals for (i = 0; i < numberRows_; i++) { // slack double value = dual_[i]; value += rowObjectiveWork_[i]; saveDuals[i+numberColumns_] = value; } CoinMemcpyN(objectiveWork_, numberColumns_, saveDuals); transposeTimes(-1.0, dual_, saveDuals); // make reduced costs okay for (i = 0; i < numberColumns_; i++) { if (getStatus(i) == atLowerBound) { if (saveDuals[i] < 0.0) { //if (saveDuals[i]<-1.0e-3) //printf("bad dj at lb %d %g\n",i,saveDuals[i]); saveDuals[i] = 0.0; } } else if (getStatus(i) == atUpperBound) { if (saveDuals[i] > 0.0) { //if (saveDuals[i]>1.0e-3) //printf("bad dj at ub %d %g\n",i,saveDuals[i]); saveDuals[i] = 0.0; } } } CoinMemcpyN(saveDuals, numberColumns_ + numberRows_, dj_); // set up possible ones for (i = 0; i < numberRows_ + numberColumns_; i++) clearPivoted(i); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (fabs(saveDuals[iPivot]) > dualTolerance_) { if (getStatus(iPivot) != isFree) setPivoted(iPivot); } } } else if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) { // set up possible ones for (int i = 0; i < numberRows_ + numberColumns_; i++) clearPivoted(i); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]) { setPivoted(iPivot); } } } double objectiveChange; numberFake_ = 0; // Number of variables at fake bounds numberChanged_ = 0; // Number of variables with changed costs changeBounds(1, NULL, objectiveChange); int lastCleaned = 0; // last time objective or bounds cleaned up if (!ifValuesPass) { // Check optimal if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_) problemStatus_ = 0; } if (problemStatus_ < 0 && perturbation_ < 100) { perturb(); // Can't get here if values pass gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } // This says whether to restore things etc // startup will have factorized so can skip int factorType = 0; // Start check for cycles progress_.startCheck(); // Say change made on first iteration changeMade_ = 1; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick // does not seem to work too well - do some more work if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_&1048576)==0 && initialStatus != 10) { perturb(); // Can't get here if values pass gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } // may factorize, checks if problem finished statusOfProblemInDual(lastCleaned, factorType, saveDuals, data, ifValuesPass); // If values pass then do easy ones on first time if (ifValuesPass && progress_.lastIterationNumber(0) < 0 && saveDuals) { doEasyOnesInValuesPass(saveDuals); } // Say good factorization factorType = 1; if (data.sparseThreshold_) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } // exit if victory declared if (problemStatus_ >= 0) break; // test for maximum iterations if (hitMaximumIterations() || (ifValuesPass == 2 && !saveDuals)) { problemStatus_ = 3; break; } if (ifValuesPass && !saveDuals) { // end of values pass ifValuesPass = 0; int status = eventHandler_->event(ClpEventHandler::endOfValuesPass); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfValuesPass; break; } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Do iterations whileIterating(saveDuals, ifValuesPass); } } assert (problemStatus_ || !sumPrimalInfeasibilities_); // clean up finish(startFinishOptions); delete [] saveDuals; // Restore any saved stuff restoreData(data); return problemStatus_; } #endif //#define CHECK_ACCURACY #ifdef CHECK_ACCURACY static double zzzzzz[100000]; #endif /* Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int ClpSimplexDual::whileIterating(double * & givenDuals, int ifValuesPass) { #ifdef CLP_INVESTIGATE_SERIAL z_thinks = -1; #endif #ifdef CLP_DEBUG int debugIteration = -1; #endif { int i; for (i = 0; i < 4; i++) { rowArray_[i]->clear(); } for (i = 0; i < 2; i++) { columnArray_[i]->clear(); } } #ifdef CLP_REPORT_PROGRESS double * savePSol = new double [numberRows_+numberColumns_]; double * saveDj = new double [numberRows_+numberColumns_]; double * saveCost = new double [numberRows_+numberColumns_]; unsigned char * saveStat = new unsigned char [numberRows_+numberColumns_]; #endif // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) factorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0)); else factorization_->relaxAccuracyCheck(1.0); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int returnCode = -1; double saveSumDual = sumDualInfeasibilities_; // so we know to be careful #if 0 // compute average infeasibility for backward test double averagePrimalInfeasibility = sumPrimalInfeasibilities_ / ((double ) (numberPrimalInfeasibilities_ + 1)); #endif // Get dubious weights CoinBigIndex * dubiousWeights = NULL; #ifdef DUBIOUS_WEIGHTS factorization_->getWeights(rowArray_[0]->getIndices()); dubiousWeights = matrix_->dubiousWeights(this, rowArray_[0]->getIndices()); #endif // If values pass then get list of candidates int * candidateList = NULL; int numberCandidates = 0; #ifdef CLP_DEBUG bool wasInValuesPass = (givenDuals != NULL); #endif int candidate = -1; if (givenDuals) { assert (ifValuesPass); ifValuesPass = 1; candidateList = new int[numberRows_]; // move reduced costs across CoinMemcpyN(givenDuals, numberRows_ + numberColumns_, dj_); int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (flagged(iPivot)) continue; if (fabs(dj_[iPivot]) > dualTolerance_) { // for now safer to ignore free ones if (lower_[iPivot] > -1.0e50 || upper_[iPivot] < 1.0e50) if (pivoted(iPivot)) candidateList[numberCandidates++] = iRow; } else { clearPivoted(iPivot); } } // and set first candidate if (!numberCandidates) { delete [] candidateList; delete [] givenDuals; givenDuals = NULL; candidateList = NULL; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; clearPivoted(iPivot); } } } else { assert (!ifValuesPass); } #ifdef CHECK_ACCURACY { if (numberIterations_) { int il = -1; double largest = 1.0e-1; int ilnb = -1; double largestnb = 1.0e-8; for (int i = 0; i < numberRows_ + numberColumns_; i++) { double diff = fabs(solution_[i] - zzzzzz[i]); if (diff > largest) { largest = diff; il = i; } if (getColumnStatus(i) != basic) { if (diff > largestnb) { largestnb = diff; ilnb = i; } } } if (il >= 0 && ilnb < 0) printf("largest diff of %g at %d, nonbasic %g at %d\n", largest, il, largestnb, ilnb); } } #endif while (problemStatus_ == -1) { //if (numberIterations_>=101624) //resetFakeBounds(-1); #ifdef CLP_DEBUG if (givenDuals) { double value5 = 0.0; int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (dj_[i] < -1.0e-6) if (upper_[i] < 1.0e20) value5 += dj_[i] * upper_[i]; else printf("bad dj %g on %d with large upper status %d\n", dj_[i], i, status_[i] & 7); else if (dj_[i] > 1.0e-6) if (lower_[i] > -1.0e20) value5 += dj_[i] * lower_[i]; else printf("bad dj %g on %d with large lower status %d\n", dj_[i], i, status_[i] & 7); } printf("Values objective Value %g\n", value5); } if ((handler_->logLevel() & 32) && wasInValuesPass) { double value5 = 0.0; int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (dj_[i] < -1.0e-6) if (upper_[i] < 1.0e20) value5 += dj_[i] * upper_[i]; else if (dj_[i] > 1.0e-6) if (lower_[i] > -1.0e20) value5 += dj_[i] * lower_[i]; } printf("Values objective Value %g\n", value5); { int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { int iSequence = i; double oldValue; switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case isFree: case superBasic: abort(); break; case atUpperBound: oldValue = dj_[iSequence]; //assert (oldValue<=tolerance); assert (fabs(solution_[iSequence] - upper_[iSequence]) < 1.0e-7); break; case atLowerBound: oldValue = dj_[iSequence]; //assert (oldValue>=-tolerance); assert (fabs(solution_[iSequence] - lower_[iSequence]) < 1.0e-7); break; } } } } #endif #ifdef CLP_DEBUG { int i; for (i = 0; i < 4; i++) { rowArray_[i]->checkClear(); } for (i = 0; i < 2; i++) { columnArray_[i]->checkClear(); } } #endif #if CLP_DEBUG>2 // very expensive if (numberIterations_ > 3063 && numberIterations_ < 30700) { //handler_->setLogLevel(63); double saveValue = objectiveValue_; double * saveRow1 = new double[numberRows_]; double * saveRow2 = new double[numberRows_]; CoinMemcpyN(rowReducedCost_, numberRows_, saveRow1); CoinMemcpyN(rowActivityWork_, numberRows_, saveRow2); double * saveColumn1 = new double[numberColumns_]; double * saveColumn2 = new double[numberColumns_]; CoinMemcpyN(reducedCostWork_, numberColumns_, saveColumn1); CoinMemcpyN(columnActivityWork_, numberColumns_, saveColumn2); gutsOfSolution(NULL, NULL); printf("xxx %d old obj %g, recomputed %g, sum dual inf %g\n", numberIterations_, saveValue, objectiveValue_, sumDualInfeasibilities_); if (saveValue > objectiveValue_ + 1.0e-2) printf("**bad**\n"); CoinMemcpyN(saveRow1, numberRows_, rowReducedCost_); CoinMemcpyN(saveRow2, numberRows_, rowActivityWork_); CoinMemcpyN(saveColumn1, numberColumns_, reducedCostWork_); CoinMemcpyN(saveColumn2, numberColumns_, columnActivityWork_); delete [] saveRow1; delete [] saveRow2; delete [] saveColumn1; delete [] saveColumn2; objectiveValue_ = saveValue; } #endif #if 0 // if (factorization_->pivots()){ { int iPivot; double * array = rowArray_[3]->denseVector(); int i; for (iPivot = 0; iPivot < numberRows_; iPivot++) { int iSequence = pivotVariable_[iPivot]; unpack(rowArray_[3], iSequence); factorization_->updateColumn(rowArray_[2], rowArray_[3]); assert (fabs(array[iPivot] - 1.0) < 1.0e-4); array[iPivot] = 0.0; for (i = 0; i < numberRows_; i++) assert (fabs(array[i]) < 1.0e-4); rowArray_[3]->clear(); } } #endif #ifdef CLP_DEBUG { int iSequence, number = numberRows_ + numberColumns_; for (iSequence = 0; iSequence < number; iSequence++) { double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; double value = solution_[iSequence]; if(getStatus(iSequence) != basic && getStatus(iSequence) != isFree) { assert(lowerValue > -1.0e20); assert(upperValue < 1.0e20); } switch(getStatus(iSequence)) { case basic: break; case isFree: case superBasic: break; case atUpperBound: assert (fabs(value - upperValue) <= primalTolerance_) ; break; case atLowerBound: case ClpSimplex::isFixed: assert (fabs(value - lowerValue) <= primalTolerance_) ; break; } } } if(numberIterations_ == debugIteration) { printf("dodgy iteration coming up\n"); } #endif #if 0 printf("checking nz\n"); for (int i = 0; i < 3; i++) { if (!rowArray_[i]->getNumElements()) rowArray_[i]->checkClear(); } #endif // choose row to go out // dualRow will go to virtual row pivot choice algorithm // make sure values pass off if it should be if (numberCandidates) candidate = candidateList[--numberCandidates]; else candidate = -1; dualRow(candidate); if (pivotRow_ >= 0) { // we found a pivot row if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) { handler_->message(CLP_SIMPLEX_PIVOTROW, messages_) << pivotRow_ << CoinMessageEol; } // check accuracy of weights dualRowPivot_->checkAccuracy(); // Get good size for pivot // Allow first few iterations to take tiny double acceptablePivot = 1.0e-1 * acceptablePivot_; if (numberIterations_ > 100) acceptablePivot = acceptablePivot_; if (factorization_->pivots() > 10 || (factorization_->pivots() && saveSumDual)) acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (factorization_->pivots() > 5) acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (factorization_->pivots()) acceptablePivot = acceptablePivot_; // relax // But factorizations complain if <1.0e-8 //acceptablePivot=CoinMax(acceptablePivot,1.0e-8); double bestPossiblePivot = 1.0; // get sign for finding row of tableau if (candidate < 0) { // normal iteration // create as packed double direction = directionOut_; rowArray_[0]->createPacked(1, &pivotRow_, &direction); factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]); // Allow to do dualColumn0 if (numberThreads_ < -1) spareIntArray_[0] = 1; spareDoubleArray_[0] = acceptablePivot; rowArray_[3]->clear(); sequenceIn_ = -1; // put row of tableau in rowArray[0] and columnArray[0] assert (!rowArray_[1]->getNumElements()); if (!scaledMatrix_) { if ((moreSpecialOptions_ & 8) != 0 && !rowScale_) spareIntArray_[0] = 1; matrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[1], columnArray_[0]); } else { double * saveR = rowScale_; double * saveC = columnScale_; rowScale_ = NULL; columnScale_ = NULL; if ((moreSpecialOptions_ & 8) != 0) spareIntArray_[0] = 1; scaledMatrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[1], columnArray_[0]); rowScale_ = saveR; columnScale_ = saveC; } #ifdef CLP_REPORT_PROGRESS memcpy(savePSol, solution_, (numberColumns_ + numberRows_)*sizeof(double)); memcpy(saveDj, dj_, (numberColumns_ + numberRows_)*sizeof(double)); memcpy(saveCost, cost_, (numberColumns_ + numberRows_)*sizeof(double)); memcpy(saveStat, status_, (numberColumns_ + numberRows_)*sizeof(char)); #endif // do ratio test for normal iteration bestPossiblePivot = dualColumn(rowArray_[0], columnArray_[0], rowArray_[3], columnArray_[1], acceptablePivot, dubiousWeights); #if CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)!=0) theta_=0.0; #endif } else { // Make sure direction plausible CoinAssert (upperOut_ < 1.0e50 || lowerOut_ > -1.0e50); // If in integer cleanup do direction using duals // may be wrong way round if(ifValuesPass == 2) { if (dual_[pivotRow_] > 0.0) { // this will give a -1 in pivot row (as slacks are -1.0) directionOut_ = 1; } else { directionOut_ = -1; } } if (directionOut_ < 0 && fabs(valueOut_ - upperOut_) > dualBound_ + primalTolerance_) { if (fabs(valueOut_ - upperOut_) > fabs(valueOut_ - lowerOut_)) directionOut_ = 1; } else if (directionOut_ > 0 && fabs(valueOut_ - lowerOut_) > dualBound_ + primalTolerance_) { if (fabs(valueOut_ - upperOut_) < fabs(valueOut_ - lowerOut_)) directionOut_ = -1; } double direction = directionOut_; rowArray_[0]->createPacked(1, &pivotRow_, &direction); factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]); // put row of tableau in rowArray[0] and columnArray[0] if (!scaledMatrix_) { matrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[3], columnArray_[0]); } else { double * saveR = rowScale_; double * saveC = columnScale_; rowScale_ = NULL; columnScale_ = NULL; scaledMatrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[3], columnArray_[0]); rowScale_ = saveR; columnScale_ = saveC; } acceptablePivot *= 10.0; // do ratio test if (ifValuesPass == 1) { checkPossibleValuesMove(rowArray_[0], columnArray_[0], acceptablePivot); } else { checkPossibleCleanup(rowArray_[0], columnArray_[0], acceptablePivot); if (sequenceIn_ < 0) { rowArray_[0]->clear(); columnArray_[0]->clear(); continue; // can't do anything } } // recompute true dualOut_ if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } // check what happened if was values pass // may want to move part way i.e. movement bool normalIteration = (sequenceIn_ != sequenceOut_); clearPivoted(sequenceOut_); // make sure won't be done again // see if end of values pass if (!numberCandidates) { int iRow; delete [] candidateList; delete [] givenDuals; candidate = -2; // -2 signals end givenDuals = NULL; candidateList = NULL; ifValuesPass = 1; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; //assert (fabs(dj_[iPivot]),1.0e-5); clearPivoted(iPivot); } } if (!normalIteration) { //rowArray_[0]->cleanAndPackSafe(1.0e-60); //columnArray_[0]->cleanAndPackSafe(1.0e-60); updateDualsInValuesPass(rowArray_[0], columnArray_[0], theta_); if (candidate == -2) problemStatus_ = -2; continue; // skip rest of iteration } else { // recompute dualOut_ if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } } } if (sequenceIn_ >= 0) { // normal iteration // update the incoming column double btranAlpha = -alpha_ * directionOut_; // for check unpackPacked(rowArray_[1]); // moved into updateWeights - factorization_->updateColumnFT(rowArray_[2],rowArray_[1]); // and update dual weights (can do in parallel - with extra array) alpha_ = dualRowPivot_->updateWeights(rowArray_[0], rowArray_[2], rowArray_[3], rowArray_[1]); // see if update stable #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_); #endif double checkValue = 1.0e-7; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha << alpha_ << CoinMessageEol; if (factorization_->pivots()) { dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); returnCode = -2; break; } else { // take on more relaxed criterion double test; if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 1.0e-4 * (1.0 + fabs(alpha_)); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) { dualRowPivot_->unrollWeights(); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag a %g %g\n", btranAlpha, alpha_); #endif //#define FEB_TRY #if 1 //def FEB_TRY // Make safer? factorization_->saferTolerances (-0.99, -1.03); #endif setFlagged(sequenceOut_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; break; } continue; } } } // update duals BEFORE replaceColumn so can do updateColumn double objectiveChange = 0.0; // do duals first as variables may flip bounds // rowArray_[0] and columnArray_[0] may have flips // so use rowArray_[3] for work array from here on int nswapped = 0; //rowArray_[0]->cleanAndPackSafe(1.0e-60); //columnArray_[0]->cleanAndPackSafe(1.0e-60); if (candidate == -1) { #if CLP_CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)==0) { #endif // make sure incoming doesn't count Status saveStatus = getStatus(sequenceIn_); setStatus(sequenceIn_, basic); nswapped = updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[2], theta_, objectiveChange, false); setStatus(sequenceIn_, saveStatus); #if CLP_CAN_HAVE_ZERO_OBJ>1 } else { rowArray_[0]->clear(); rowArray_[2]->clear(); columnArray_[0]->clear(); } #endif } else { updateDualsInValuesPass(rowArray_[0], columnArray_[0], theta_); } double oldDualOut = dualOut_; // which will change basic solution if (nswapped) { if (rowArray_[2]->getNumElements()) { factorization_->updateColumn(rowArray_[3], rowArray_[2]); dualRowPivot_->updatePrimalSolution(rowArray_[2], 1.0, objectiveChange); } // recompute dualOut_ valueOut_ = solution_[sequenceOut_]; if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } #if 0 if (dualOut_ < 0.0) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) { printf(" dualOut_ %g %g save %g\n", dualOut_, averagePrimalInfeasibility, saveDualOut); printf("values %g %g %g %g %g %g %g\n", lowerOut_, valueOut_, upperOut_, objectiveChange,); } #endif if (upperOut_ == lowerOut_) dualOut_ = 0.0; } if(dualOut_ < -CoinMax(1.0e-12 * averagePrimalInfeasibility, 1.0e-8) && factorization_->pivots() > 100 && getStatus(sequenceIn_) != isFree) { // going backwards - factorize dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now returnCode = -2; break; } #endif } // amount primal will move double movement = -dualOut_ * directionOut_ / alpha_; double movementOld = oldDualOut * directionOut_ / alpha_; // so objective should increase by fabs(dj)*movement // but we already have objective change - so check will be good if (objectiveChange + fabs(movementOld * dualIn_) < -CoinMax(1.0e-5, 1.0e-12 * fabs(objectiveValue_))) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("movement %g, swap change %g, rest %g * %g\n", objectiveChange + fabs(movement * dualIn_), objectiveChange, movement, dualIn_); #endif if(factorization_->pivots()) { // going backwards - factorize dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now returnCode = -2; break; } } // if stable replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_, (moreSpecialOptions_ & 16) != 0, acceptablePivot); // If looks like bad pivot - refactorize if (fabs(dualOut_) > 1.0e50) updateStatus = 2; // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { problemStatus_ = -2; // factorize now returnCode = -3; } } else if (updateStatus == 2) { // major error dualRowPivot_->unrollWeights(); // later we may need to unwind more e.g. fake bounds if (factorization_->pivots() && ((moreSpecialOptions_ & 16) == 0 || factorization_->pivots() > 4)) { problemStatus_ = -2; // factorize now returnCode = -2; moreSpecialOptions_ |= 16; break; } else { // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag b %g\n", alpha_); #endif setFlagged(sequenceOut_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); // make sure dual feasible // look at all rows and columns double objectiveChange = 0.0; updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1], 0.0, objectiveChange, true); rowArray_[1]->clear(); columnArray_[0]->clear(); continue; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); problemStatus_ = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } // update primal solution if (theta_ < 0.0 && candidate == -1) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("negative theta %g\n", theta_); #endif theta_ = 0.0; } // do actual flips flipBounds(rowArray_[0], columnArray_[0]); //rowArray_[1]->expand(); dualRowPivot_->updatePrimalSolution(rowArray_[1], movement, objectiveChange); #ifdef CLP_DEBUG double oldobj = objectiveValue_; #endif // modify dualout dualOut_ /= alpha_; dualOut_ *= -directionOut_; //setStatus(sequenceIn_,basic); dj_[sequenceIn_] = 0.0; double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound valueIn_ = upperIn_ + dualOut_; } else { // as if from lower bound valueIn_ = lowerIn_ + dualOut_; } objectiveChange += cost_[sequenceIn_] * (valueIn_ - oldValue); // outgoing // set dj to zero unless values pass if (directionOut_ > 0) { valueOut_ = lowerOut_; if (candidate == -1) dj_[sequenceOut_] = theta_; } else { valueOut_ = upperOut_; if (candidate == -1) dj_[sequenceOut_] = -theta_; } solution_[sequenceOut_] = valueOut_; int whatNext = housekeeping(objectiveChange); #if 0 for (int i=0;i-1.0e-5); assert (solution_[i]<=lower_[i]+1.0e-5); } else if (getStatus(i)==atUpperBound) { assert (dj_[i]<1.0e-5); assert (solution_[i]>=upper_[i]-1.0e-5); } } #endif #ifdef CLP_REPORT_PROGRESS if (ixxxxxx > ixxyyyy - 5) { handler_->setLogLevel(63); int nTotal = numberColumns_ + numberRows_; double oldObj = 0.0; double newObj = 0.0; for (int i = 0; i < nTotal; i++) { if (savePSol[i]) oldObj += savePSol[i] * saveCost[i]; if (solution_[i]) newObj += solution_[i] * cost_[i]; bool printIt = false; if (cost_[i] != saveCost[i]) printIt = true; if (status_[i] != saveStat[i]) printIt = true; if (printIt) printf("%d old %d cost %g sol %g, new %d cost %g sol %g\n", i, saveStat[i], saveCost[i], savePSol[i], status_[i], cost_[i], solution_[i]); // difference savePSol[i] = solution_[i] - savePSol[i]; } printf("pivots %d, old obj %g new %g\n", factorization_->pivots(), oldObj, newObj); memset(saveDj, 0, numberRows_ * sizeof(double)); times(1.0, savePSol, saveDj); double largest = 1.0e-6; int k = -1; for (int i = 0; i < numberRows_; i++) { saveDj[i] -= savePSol[i+numberColumns_]; if (fabs(saveDj[i]) > largest) { largest = fabs(saveDj[i]); k = i; } } if (k >= 0) printf("Not null %d %g\n", k, largest); } #endif #ifdef VUB { if ((sequenceIn_ < numberColumns_ && vub[sequenceIn_] >= 0) || toVub[sequenceIn_] >= 0 || (sequenceOut_ < numberColumns_ && vub[sequenceOut_] >= 0) || toVub[sequenceOut_] >= 0) { int inSequence = sequenceIn_; int inVub = -1; if (sequenceIn_ < numberColumns_) inVub = vub[sequenceIn_]; int inBack = toVub[inSequence]; int inSlack = -1; if (inSequence >= numberColumns_ && inBack >= 0) { inSlack = inSequence - numberColumns_; inSequence = inBack; inBack = toVub[inSequence]; } if (inVub >= 0) printf("Vub %d in ", inSequence); if (inBack >= 0 && inSlack < 0) printf("%d (descendent of %d) in ", inSequence, inBack); if (inSlack >= 0) printf("slack for row %d -> %d (descendent of %d) in ", inSlack, inSequence, inBack); int outSequence = sequenceOut_; int outVub = -1; if (sequenceOut_ < numberColumns_) outVub = vub[sequenceOut_]; int outBack = toVub[outSequence]; int outSlack = -1; if (outSequence >= numberColumns_ && outBack >= 0) { outSlack = outSequence - numberColumns_; outSequence = outBack; outBack = toVub[outSequence]; } if (outVub >= 0) printf("Vub %d out ", outSequence); if (outBack >= 0 && outSlack < 0) printf("%d (descendent of %d) out ", outSequence, outBack); if (outSlack >= 0) printf("slack for row %d -> %d (descendent of %d) out ", outSlack, outSequence, outBack); printf("\n"); } } #endif #if 0 if (numberIterations_ > 206033) handler_->setLogLevel(63); if (numberIterations_ > 210567) exit(77); #endif if (!givenDuals && ifValuesPass && ifValuesPass != 2) { handler_->message(CLP_END_VALUES_PASS, messages_) << numberIterations_; whatNext = 1; } #ifdef CHECK_ACCURACY if (whatNext) { CoinMemcpyN(solution_, (numberRows_ + numberColumns_), zzzzzz); } #endif //if (numberIterations_==1890) //whatNext=1; //if (numberIterations_>2000) //exit(77); // and set bounds correctly originalBound(sequenceIn_); changeBound(sequenceOut_); #ifdef CLP_DEBUG if (objectiveValue_ < oldobj - 1.0e-5 && (handler_->logLevel() & 16)) printf("obj backwards %g %g\n", objectiveValue_, oldobj); #endif #if 0 { for (int i = 0; i < numberRows_ + numberColumns_; i++) { FakeBound bound = getFakeBound(i); if (bound == ClpSimplexDual::upperFake) { assert (upper_[i] < 1.0e20); } else if (bound == ClpSimplexDual::lowerFake) { assert (lower_[i] > -1.0e20); } else if (bound == ClpSimplexDual::bothFake) { assert (upper_[i] < 1.0e20); assert (lower_[i] > -1.0e20); } } } #endif if (whatNext == 1 || candidate == -2) { problemStatus_ = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; break; } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 4; break; } } } else { #ifdef CLP_INVESTIGATE_SERIAL z_thinks = 1; #endif // no incoming column is valid spareIntArray_[3]=pivotRow_; pivotRow_ = -1; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (factorization_->pivots() < 2 && acceptablePivot_ <= 1.0e-8) { //&&goodAccuracy()) { // If not in branch and bound etc save ray delete [] ray_; if ((specialOptions_&(1024 | 4096)) == 0 || (specialOptions_ & 32) != 0) { // create ray anyway #ifdef PRINT_RAY_METHOD printf("Dual creating infeasibility ray direction out %d - pivRow %d seqOut %d lower %g,val %g,upper %g\n", directionOut_,spareIntArray_[3],sequenceOut_,lowerOut_,valueOut_,upperOut_); #endif ray_ = new double [ numberRows_]; rowArray_[0]->expand(); // in case packed const double * array = rowArray_[0]->denseVector(); for (int i=0;i dualTest) { double testValue = 1.0e-4; if (!factorization_->pivots() && numberPrimalInfeasibilities_ == 1) testValue = 1.0e-6; if (valueOut_ > upperOut_ + testValue || valueOut_ < lowerOut_ - testValue || (specialOptions_ & 64) == 0) { // say infeasible problemStatus_ = 1; // unless primal feasible!!!! //printf("%d %g %d %g\n",numberPrimalInfeasibilities_,sumPrimalInfeasibilities_, // numberDualInfeasibilities_,sumDualInfeasibilities_); //#define TEST_CLP_NODE #ifndef TEST_CLP_NODE // Should be correct - but ... int numberFake = numberAtFakeBound(); double sumPrimal = (!numberFake) ? 2.0e5 : sumPrimalInfeasibilities_; if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-5 || (sumPrimal < 1.0e5 && (specialOptions_ & 1024) != 0 && factorization_->pivots())) { if (sumPrimal > 50.0 && factorization_->pivots() > 2) { problemStatus_ = -4; #ifdef COIN_DEVELOP printf("status to -4 at %d - primalinf %g pivots %d\n", __LINE__, sumPrimalInfeasibilities_, factorization_->pivots()); #endif } else { problemStatus_ = 10; #if COIN_DEVELOP>1 printf("returning at %d - primal %d %g - dual %d %g fake %d weight %g - pivs %d - options (1024-16384) %d %d %d %d %d\n", __LINE__, numberPrimalInfeasibilities_, sumPrimalInfeasibilities_, numberDualInfeasibilities_, sumDualInfeasibilities_, numberFake_, dualBound_, factorization_->pivots(), (specialOptions_ & 1024) != 0 ? 1 : 0, (specialOptions_ & 2048) != 0 ? 1 : 0, (specialOptions_ & 4096) != 0 ? 1 : 0, (specialOptions_ & 8192) != 0 ? 1 : 0, (specialOptions_ & 16384) != 0 ? 1 : 0 ); #endif // Get rid of objective if ((specialOptions_ & 16384) == 0) objective_ = new ClpLinearObjective(NULL, numberColumns_); } } #else if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-6) { #ifdef COIN_DEVELOP printf("at %d - primal %d %g - dual %d %g fake %d weight %g - pivs %d\n", __LINE__, numberPrimalInfeasibilities_, sumPrimalInfeasibilities_, numberDualInfeasibilities_, sumDualInfeasibilities_, numberFake_, dualBound_, factorization_->pivots()); #endif if ((specialOptions_ & 1024) != 0 && factorization_->pivots()) { problemStatus_ = 10; #if COIN_DEVELOP>1 printf("returning at %d\n", __LINE__); #endif // Get rid of objective if ((specialOptions_ & 16384) == 0) objective_ = new ClpLinearObjective(NULL, numberColumns_); } } #endif rowArray_[0]->clear(); columnArray_[0]->clear(); returnCode = 1; break; } } // If special option set - put off as long as possible if ((specialOptions_ & 64) == 0 || (moreSpecialOptions_ & 64) != 0) { if (factorization_->pivots() == 0) problemStatus_ = -4; //say looks infeasible } else { // flag char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag c\n"); #endif setFlagged(sequenceOut_); if (!factorization_->pivots()) { rowArray_[0]->clear(); columnArray_[0]->clear(); continue; } } } if (factorization_->pivots() < 5 && acceptablePivot_ > 1.0e-8) acceptablePivot_ = 1.0e-8; rowArray_[0]->clear(); columnArray_[0]->clear(); returnCode = 1; break; } } else { #ifdef CLP_INVESTIGATE_SERIAL z_thinks = 0; #endif // no pivot row #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no row pivot\n"); #endif // If in branch and bound try and get rid of fixed variables if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) { assert (!candidateList); candidateList = new int[numberRows_]; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (flagged(iPivot) || !pivoted(iPivot)) continue; assert (iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]); candidateList[numberCandidates++] = iRow; } // and set first candidate if (!numberCandidates) { delete [] candidateList; candidateList = NULL; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; clearPivoted(iPivot); } } else { ifValuesPass = 2; continue; } } int numberPivots = factorization_->pivots(); bool specialCase; int useNumberFake; returnCode = 0; if (numberPivots <= CoinMax(dontFactorizePivots_, 20) && (specialOptions_ & 2048) != 0 && (true || !numberChanged_ || perturbation_ == 101) && dualBound_ >= 1.0e8) { specialCase = true; // as dual bound high - should be okay useNumberFake = 0; } else { specialCase = false; useNumberFake = numberFake_; } if (!numberPivots || specialCase) { // may have crept through - so may be optimal // check any flagged variables int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (flagged(iPivot)) break; } if (iRow < numberRows_ && numberPivots) { // try factorization returnCode = -2; } if (useNumberFake || numberDualInfeasibilities_) { // may be dual infeasible if ((specialOptions_ & 1024) == 0) problemStatus_ = -5; else if (!useNumberFake && numberPrimalInfeasibilities_ && !numberPivots) problemStatus_ = 1; } else { if (iRow < numberRows_) { #ifdef COIN_DEVELOP std::cout << "Flagged variables at end - infeasible?" << std::endl; printf("Probably infeasible - pivot was %g\n", alpha_); #endif //if (fabs(alpha_)<1.0e-4) { //problemStatus_=1; //} else { #ifdef CLP_DEBUG abort(); #endif //} problemStatus_ = -5; } else { problemStatus_ = 0; #ifndef CLP_CHECK_NUMBER_PIVOTS #define CLP_CHECK_NUMBER_PIVOTS 10 #endif #if CLP_CHECK_NUMBER_PIVOTS < 20 if (numberPivots > CLP_CHECK_NUMBER_PIVOTS) { #ifndef NDEBUG_CLP int nTotal = numberRows_ + numberColumns_; double * comp = CoinCopyOfArray(solution_, nTotal); #endif computePrimals(rowActivityWork_, columnActivityWork_); #ifndef NDEBUG_CLP double largest = 1.0e-5; int bad = -1; for (int i = 0; i < nTotal; i++) { double value = solution_[i]; double larger = CoinMax(fabs(value), fabs(comp[i])); double tol = 1.0e-5 + 1.0e-5 * larger; double diff = fabs(value - comp[i]); if (diff - tol > largest) { bad = i; largest = diff - tol; } } if (bad >= 0) COIN_DETAIL_PRINT(printf("bad %d old %g new %g\n", bad, comp[bad], solution_[bad])); #endif checkPrimalSolution(rowActivityWork_, columnActivityWork_); if (numberPrimalInfeasibilities_) { #ifdef CLP_INVESTIGATE printf("XXX Infeas ? %d inf summing to %g\n", numberPrimalInfeasibilities_, sumPrimalInfeasibilities_); #endif problemStatus_ = -1; returnCode = -2; } #ifndef NDEBUG_CLP memcpy(solution_, comp, nTotal * sizeof(double)); delete [] comp; #endif } #endif if (!problemStatus_) { // make it look OK numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; // May be perturbed if (perturbation_ == 101 || numberChanged_) { numberChanged_ = 0; // Number of variables with changed costs perturbation_ = 102; // stop any perturbations //double changeCost; //changeBounds(1,NULL,changeCost); createRim4(false); // make sure duals are current computeDuals(givenDuals); checkDualSolution(); progress_.modifyObjective(-COIN_DBL_MAX); if (numberDualInfeasibilities_) { problemStatus_ = 10; // was -3; } else { computeObjectiveValue(true); } } else if (numberPivots) { computeObjectiveValue(true); } if (numberPivots < -1000) { // objective may be wrong objectiveValue_ = innerProduct(cost_, numberColumns_ + numberRows_, solution_); objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); if ((specialOptions_ & 16384) == 0) { // and dual_ may be wrong (i.e. for fixed or basic) CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); int iRow; double * array = arrayVector->denseVector(); /* Use dual_ instead of array Even though dual_ is only numberRows_ long this is okay as gets permuted to longer rowArray_[2] */ arrayVector->setDenseVector(dual_); int * index = arrayVector->getIndices(); int number = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value = cost_[iPivot]; dual_[iRow] = value; if (value) { index[number++] = iRow; } } arrayVector->setNumElements(number); // Extended duals before "updateTranspose" matrix_->dualExpanded(this, arrayVector, NULL, 0); // Btran basic costs rowArray_[2]->clear(); factorization_->updateColumnTranspose(rowArray_[2], arrayVector); // and return vector arrayVector->setDenseVector(array); } } sumPrimalInfeasibilities_ = 0.0; } if ((specialOptions_&(1024 + 16384)) != 0 && !problemStatus_) { CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); double * rhs = arrayVector->denseVector(); times(1.0, solution_, rhs); #ifdef CHECK_ACCURACY bool bad = false; #endif bool bad2 = false; int i; for ( i = 0; i < numberRows_; i++) { if (rhs[i] < rowLowerWork_[i] - primalTolerance_ || rhs[i] > rowUpperWork_[i] + primalTolerance_) { bad2 = true; #ifdef CHECK_ACCURACY printf("row %d out of bounds %g, %g correct %g bad %g\n", i, rowLowerWork_[i], rowUpperWork_[i], rhs[i], rowActivityWork_[i]); #endif } else if (fabs(rhs[i] - rowActivityWork_[i]) > 1.0e-3) { #ifdef CHECK_ACCURACY bad = true; printf("row %d correct %g bad %g\n", i, rhs[i], rowActivityWork_[i]); #endif } rhs[i] = 0.0; } for ( i = 0; i < numberColumns_; i++) { if (solution_[i] < columnLowerWork_[i] - primalTolerance_ || solution_[i] > columnUpperWork_[i] + primalTolerance_) { bad2 = true; #ifdef CHECK_ACCURACY printf("column %d out of bounds %g, %g correct %g bad %g\n", i, columnLowerWork_[i], columnUpperWork_[i], solution_[i], columnActivityWork_[i]); #endif } } if (bad2) { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = factorization_->pivots(); forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } } } } } else { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = factorization_->pivots(); forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } break; } } if (givenDuals) { CoinMemcpyN(dj_, numberRows_ + numberColumns_, givenDuals); // get rid of any values pass array delete [] candidateList; } delete [] dubiousWeights; #ifdef CLP_REPORT_PROGRESS if (ixxxxxx > ixxyyyy - 5) { int nTotal = numberColumns_ + numberRows_; double oldObj = 0.0; double newObj = 0.0; for (int i = 0; i < nTotal; i++) { if (savePSol[i]) oldObj += savePSol[i] * saveCost[i]; if (solution_[i]) newObj += solution_[i] * cost_[i]; bool printIt = false; if (cost_[i] != saveCost[i]) printIt = true; if (status_[i] != saveStat[i]) printIt = true; if (printIt) printf("%d old %d cost %g sol %g, new %d cost %g sol %g\n", i, saveStat[i], saveCost[i], savePSol[i], status_[i], cost_[i], solution_[i]); // difference savePSol[i] = solution_[i] - savePSol[i]; } printf("exit pivots %d, old obj %g new %g\n", factorization_->pivots(), oldObj, newObj); memset(saveDj, 0, numberRows_ * sizeof(double)); times(1.0, savePSol, saveDj); double largest = 1.0e-6; int k = -1; for (int i = 0; i < numberRows_; i++) { saveDj[i] -= savePSol[i+numberColumns_]; if (fabs(saveDj[i]) > largest) { largest = fabs(saveDj[i]); k = i; } } if (k >= 0) printf("Not null %d %g\n", k, largest); } delete [] savePSol ; delete [] saveDj ; delete [] saveCost ; delete [] saveStat ; #endif return returnCode; } /* The duals are updated by the given arrays. Returns number of infeasibilities. rowArray and columnarray will have flipped The output vector has movement (row length array) */ int ClpSimplexDual::updateDualsInDual(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * outputArray, double theta, double & objectiveChange, bool fullRecompute) { outputArray->clear(); int numberInfeasibilities = 0; int numberRowInfeasibilities = 0; // get a tolerance double tolerance = dualTolerance_; // we can't really trust infeasibilities if there is dual error double error = CoinMin(1.0e-2, largestDualError_); // allow tolerance at least slightly bigger than standard tolerance = tolerance + error; double changeObj = 0.0; // Coding is very similar but we can save a bit by splitting // Do rows if (!fullRecompute) { int i; double * COIN_RESTRICT reducedCost = djRegion(0); const double * COIN_RESTRICT lower = lowerRegion(0); const double * COIN_RESTRICT upper = upperRegion(0); const double * COIN_RESTRICT cost = costRegion(0); double * COIN_RESTRICT work; int number; int * COIN_RESTRICT which; const unsigned char * COIN_RESTRICT statusArray = status_ + numberColumns_; assert(rowArray->packedMode()); work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); double multiplier[] = { -1.0, 1.0}; for (i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; work[i] = 0.0; int iStatus = (statusArray[iSequence] & 3) - 1; if (iStatus) { double value = reducedCost[iSequence] - theta * alphaI; reducedCost[iSequence] = value; double mult = multiplier[iStatus-1]; value *= mult; if (value < -tolerance) { // flipping bounds double movement = mult * (lower[iSequence] - upper[iSequence]); which[numberInfeasibilities++] = iSequence; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("%d %d, new dj %g, alpha %g, movement %g\n", 0, iSequence, value, alphaI, movement); #endif changeObj -= movement * cost[iSequence]; outputArray->quickAdd(iSequence, movement); } } } // Do columns reducedCost = djRegion(1); lower = lowerRegion(1); upper = upperRegion(1); cost = costRegion(1); // set number of infeasibilities in row array numberRowInfeasibilities = numberInfeasibilities; rowArray->setNumElements(numberInfeasibilities); numberInfeasibilities = 0; work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); if ((moreSpecialOptions_ & 8) != 0) { const unsigned char * COIN_RESTRICT statusArray = status_; for (i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; work[i] = 0.0; int iStatus = (statusArray[iSequence] & 3) - 1; if (iStatus) { double value = reducedCost[iSequence] - theta * alphaI; reducedCost[iSequence] = value; double mult = multiplier[iStatus-1]; value *= mult; if (value < -tolerance) { // flipping bounds double movement = mult * (upper[iSequence] - lower[iSequence]); which[numberInfeasibilities++] = iSequence; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("%d %d, new dj %g, alpha %g, movement %g\n", 1, iSequence, value, alphaI, movement); #endif changeObj += movement * cost[iSequence]; matrix_->add(this, outputArray, iSequence, movement); } } } } else { for (i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; work[i] = 0.0; Status status = getStatus(iSequence); if (status == atLowerBound) { double value = reducedCost[iSequence] - theta * alphaI; reducedCost[iSequence] = value; double movement = 0.0; if (value < -tolerance) { // to upper bound which[numberInfeasibilities++] = iSequence; movement = upper[iSequence] - lower[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("%d %d, new dj %g, alpha %g, movement %g\n", 1, iSequence, value, alphaI, movement); #endif changeObj += movement * cost[iSequence]; matrix_->add(this, outputArray, iSequence, movement); } } else if (status == atUpperBound) { double value = reducedCost[iSequence] - theta * alphaI; reducedCost[iSequence] = value; double movement = 0.0; if (value > tolerance) { // to lower bound (if swap) which[numberInfeasibilities++] = iSequence; movement = lower[iSequence] - upper[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("%d %d, new dj %g, alpha %g, movement %g\n", 1, iSequence, value, alphaI, movement); #endif changeObj += movement * cost[iSequence]; matrix_->add(this, outputArray, iSequence, movement); } } else if (status == isFree) { double value = reducedCost[iSequence] - theta * alphaI; reducedCost[iSequence] = value; } } } } else { double * COIN_RESTRICT solution = solutionRegion(0); double * COIN_RESTRICT reducedCost = djRegion(0); const double * COIN_RESTRICT lower = lowerRegion(0); const double * COIN_RESTRICT upper = upperRegion(0); const double * COIN_RESTRICT cost = costRegion(0); int * COIN_RESTRICT which; which = rowArray->getIndices(); int iSequence; for (iSequence = 0; iSequence < numberRows_; iSequence++) { double value = reducedCost[iSequence]; Status status = getStatus(iSequence + numberColumns_); // more likely to be at upper bound ? if (status == atUpperBound) { double movement = 0.0; //#define NO_SWAP7 if (value > tolerance) { // to lower bound (if swap) // put back alpha which[numberInfeasibilities++] = iSequence; movement = lower[iSequence] - upper[iSequence]; changeObj += movement * cost[iSequence]; outputArray->quickAdd(iSequence, -movement); #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif #ifndef NO_SWAP7 } else if (value > -tolerance) { // at correct bound but may swap FakeBound bound = getFakeBound(iSequence + numberColumns_); if (bound == ClpSimplexDual::upperFake) { movement = lower[iSequence] - upper[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif setStatus(iSequence + numberColumns_, atLowerBound); solution[iSequence] = lower[iSequence]; changeObj += movement * cost[iSequence]; //numberFake_--; //setFakeBound(iSequence+numberColumns_,noFake); } #endif } } else if (status == atLowerBound) { double movement = 0.0; if (value < -tolerance) { // to upper bound // put back alpha which[numberInfeasibilities++] = iSequence; movement = upper[iSequence] - lower[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif changeObj += movement * cost[iSequence]; outputArray->quickAdd(iSequence, -movement); #ifndef NO_SWAP7 } else if (value < tolerance) { // at correct bound but may swap FakeBound bound = getFakeBound(iSequence + numberColumns_); if (bound == ClpSimplexDual::lowerFake) { movement = upper[iSequence] - lower[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif setStatus(iSequence + numberColumns_, atUpperBound); solution[iSequence] = upper[iSequence]; changeObj += movement * cost[iSequence]; //numberFake_--; //setFakeBound(iSequence+numberColumns_,noFake); } #endif } } } // Do columns solution = solutionRegion(1); reducedCost = djRegion(1); lower = lowerRegion(1); upper = upperRegion(1); cost = costRegion(1); // set number of infeasibilities in row array numberRowInfeasibilities = numberInfeasibilities; rowArray->setNumElements(numberInfeasibilities); numberInfeasibilities = 0; which = columnArray->getIndices(); for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double value = reducedCost[iSequence]; Status status = getStatus(iSequence); if (status == atLowerBound) { double movement = 0.0; if (value < -tolerance) { // to upper bound // put back alpha which[numberInfeasibilities++] = iSequence; movement = upper[iSequence] - lower[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif changeObj += movement * cost[iSequence]; matrix_->add(this, outputArray, iSequence, movement); #ifndef NO_SWAP7 } else if (value < tolerance) { // at correct bound but may swap FakeBound bound = getFakeBound(iSequence); if (bound == ClpSimplexDual::lowerFake) { movement = upper[iSequence] - lower[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif setStatus(iSequence, atUpperBound); solution[iSequence] = upper[iSequence]; changeObj += movement * cost[iSequence]; //numberFake_--; //setFakeBound(iSequence,noFake); } #endif } } else if (status == atUpperBound) { double movement = 0.0; if (value > tolerance) { // to lower bound (if swap) // put back alpha which[numberInfeasibilities++] = iSequence; movement = lower[iSequence] - upper[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif changeObj += movement * cost[iSequence]; matrix_->add(this, outputArray, iSequence, movement); #ifndef NO_SWAP7 } else if (value > -tolerance) { // at correct bound but may swap FakeBound bound = getFakeBound(iSequence); if (bound == ClpSimplexDual::upperFake) { movement = lower[iSequence] - upper[iSequence]; #ifndef NDEBUG if (fabs(movement) >= 1.0e30) resetFakeBounds(-1000 - iSequence); #endif setStatus(iSequence, atLowerBound); solution[iSequence] = lower[iSequence]; changeObj += movement * cost[iSequence]; //numberFake_--; //setFakeBound(iSequence,noFake); } #endif } } } } #ifdef CLP_DEBUG if (fullRecompute && numberFake_ && (handler_->logLevel() & 16) != 0) printf("%d fake after full update\n", numberFake_); #endif // set number of infeasibilities columnArray->setNumElements(numberInfeasibilities); numberInfeasibilities += numberRowInfeasibilities; if (fullRecompute) { // do actual flips flipBounds(rowArray, columnArray); } objectiveChange += changeObj; return numberInfeasibilities; } void ClpSimplexDual::updateDualsInValuesPass(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double theta) { // use a tighter tolerance except for all being okay double tolerance = dualTolerance_; // Coding is very similar but we can save a bit by splitting // Do rows { int i; double * reducedCost = djRegion(0); double * work; int number; int * which; work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); for (i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; double value = reducedCost[iSequence] - theta * alphaI; work[i] = 0.0; reducedCost[iSequence] = value; Status status = getStatus(iSequence + numberColumns_); // more likely to be at upper bound ? if (status == atUpperBound) { if (value > tolerance) reducedCost[iSequence] = 0.0; } else if (status == atLowerBound) { if (value < -tolerance) { reducedCost[iSequence] = 0.0; } } } } rowArray->setNumElements(0); // Do columns { int i; double * reducedCost = djRegion(1); double * work; int number; int * which; work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); for (i = 0; i < number; i++) { int iSequence = which[i]; double alphaI = work[i]; double value = reducedCost[iSequence] - theta * alphaI; work[i] = 0.0; reducedCost[iSequence] = value; Status status = getStatus(iSequence); if (status == atLowerBound) { if (value < -tolerance) reducedCost[iSequence] = 0.0; } else if (status == atUpperBound) { if (value > tolerance) reducedCost[iSequence] = 0.0; } } } columnArray->setNumElements(0); } /* Chooses dual pivot row Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first rows we look at */ void ClpSimplexDual::dualRow(int alreadyChosen) { // get pivot row using whichever method it is int chosenRow = -1; #ifdef FORCE_FOLLOW bool forceThis = false; if (!fpFollow && strlen(forceFile)) { fpFollow = fopen(forceFile, "r"); assert (fpFollow); } if (fpFollow) { if (numberIterations_ <= force_iteration) { // read to next Clp0102 char temp[300]; while (fgets(temp, 250, fpFollow)) { if (strncmp(temp, "Clp0102", 7)) continue; char cin, cout; sscanf(temp + 9, "%d%*f%*s%*c%c%d%*s%*c%c%d", &force_iteration, &cin, &force_in, &cout, &force_out); if (cin == 'R') force_in += numberColumns_; if (cout == 'R') force_out += numberColumns_; forceThis = true; assert (numberIterations_ == force_iteration - 1); printf("Iteration %d will force %d out and %d in\n", force_iteration, force_out, force_in); alreadyChosen = force_out; break; } } else { // use old forceThis = true; } if (!forceThis) { fclose(fpFollow); fpFollow = NULL; forceFile = ""; } } #endif //double freeAlpha = 0.0; if (alreadyChosen < 0) { // first see if any free variables and put them in basis int nextFree = nextSuperBasic(); //nextFree=-1; //off if (nextFree >= 0) { // unpack vector and find a good pivot unpack(rowArray_[1], nextFree); factorization_->updateColumn(rowArray_[2], rowArray_[1]); double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); double bestFeasibleAlpha = 0.0; int bestFeasibleRow = -1; double bestInfeasibleAlpha = 0.0; int bestInfeasibleRow = -1; int i; for (i = 0; i < number; i++) { int iRow = which[i]; double alpha = fabs(work[iRow]); if (alpha > 1.0e-3) { int iSequence = pivotVariable_[iRow]; double value = solution_[iSequence]; double lower = lower_[iSequence]; double upper = upper_[iSequence]; double infeasibility = 0.0; if (value > upper) infeasibility = value - upper; else if (value < lower) infeasibility = lower - value; if (infeasibility * alpha > bestInfeasibleAlpha && alpha > 1.0e-1) { if (!flagged(iSequence)) { bestInfeasibleAlpha = infeasibility * alpha; bestInfeasibleRow = iRow; } } if (alpha > bestFeasibleAlpha && (lower > -1.0e20 || upper < 1.0e20)) { bestFeasibleAlpha = alpha; bestFeasibleRow = iRow; } } } if (bestInfeasibleRow >= 0) chosenRow = bestInfeasibleRow; else if (bestFeasibleAlpha > 1.0e-2) chosenRow = bestFeasibleRow; if (chosenRow >= 0) { pivotRow_ = chosenRow; //freeAlpha = work[chosenRow]; } rowArray_[1]->clear(); } } else { // in values pass chosenRow = alreadyChosen; #ifdef FORCE_FOLLOW if(forceThis) { alreadyChosen = -1; chosenRow = -1; for (int i = 0; i < numberRows_; i++) { if (pivotVariable_[i] == force_out) { chosenRow = i; break; } } assert (chosenRow >= 0); } #endif pivotRow_ = chosenRow; } if (chosenRow < 0) pivotRow_ = dualRowPivot_->pivotRow(); if (pivotRow_ >= 0) { sequenceOut_ = pivotVariable_[pivotRow_]; valueOut_ = solution_[sequenceOut_]; lowerOut_ = lower_[sequenceOut_]; upperOut_ = upper_[sequenceOut_]; if (alreadyChosen < 0) { // if we have problems we could try other way and hope we get a // zero pivot? if (valueOut_ > upperOut_) { directionOut_ = -1; dualOut_ = valueOut_ - upperOut_; } else if (valueOut_ < lowerOut_) { directionOut_ = 1; dualOut_ = lowerOut_ - valueOut_; } else { #if 1 // odd (could be free) - it's feasible - go to nearest if (valueOut_ - lowerOut_ < upperOut_ - valueOut_) { directionOut_ = 1; dualOut_ = lowerOut_ - valueOut_; } else { directionOut_ = -1; dualOut_ = valueOut_ - upperOut_; } #else // odd (could be free) - it's feasible - improve obj printf("direction from alpha of %g is %d\n", freeAlpha, freeAlpha > 0.0 ? 1 : -1); if (valueOut_ - lowerOut_ > 1.0e20) freeAlpha = 1.0; else if(upperOut_ - valueOut_ > 1.0e20) freeAlpha = -1.0; //if (valueOut_-lowerOut_= 0.0); #endif } else { // in values pass so just use sign of dj // We don't want to go through any barriers so set dualOut low // free variables will never be here dualOut_ = 1.0e-6; if (dj_[sequenceOut_] > 0.0) { // this will give a -1 in pivot row (as slacks are -1.0) directionOut_ = 1; } else { directionOut_ = -1; } } } return ; } // Checks if any fake bounds active - if so returns number and modifies // dualBound_ and everything. // Free variables will be left as free // Returns number of bounds changed if >=0 // Returns -1 if not initialize and no effect // Fills in changeVector which can be used to see if unbounded // and cost of change vector int ClpSimplexDual::changeBounds(int initialize, CoinIndexedVector * outputArray, double & changeCost) { numberFake_ = 0; if (!initialize) { int numberInfeasibilities; double newBound; newBound = 5.0 * dualBound_; numberInfeasibilities = 0; changeCost = 0.0; // put back original bounds and then check createRim1(false); int iSequence; // bounds will get bigger - just look at ones at bounds for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; double value = solution_[iSequence]; setFakeBound(iSequence, ClpSimplexDual::noFake); switch(getStatus(iSequence)) { case basic: case ClpSimplex::isFixed: break; case isFree: case superBasic: break; case atUpperBound: if (fabs(value - upperValue) > primalTolerance_) numberInfeasibilities++; break; case atLowerBound: if (fabs(value - lowerValue) > primalTolerance_) numberInfeasibilities++; break; } } // If dual infeasible then carry on if (numberInfeasibilities) { handler_->message(CLP_DUAL_CHECKB, messages_) << newBound << CoinMessageEol; int iSequence; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; double newLowerValue; double newUpperValue; Status status = getStatus(iSequence); if (status == atUpperBound || status == atLowerBound) { double value = solution_[iSequence]; if (value - lowerValue <= upperValue - value) { newLowerValue = CoinMax(lowerValue, value - 0.666667 * newBound); newUpperValue = CoinMin(upperValue, newLowerValue + newBound); } else { newUpperValue = CoinMin(upperValue, value + 0.666667 * newBound); newLowerValue = CoinMax(lowerValue, newUpperValue - newBound); } lower_[iSequence] = newLowerValue; upper_[iSequence] = newUpperValue; if (newLowerValue > lowerValue) { if (newUpperValue < upperValue) { setFakeBound(iSequence, ClpSimplexDual::bothFake); #ifdef CLP_INVESTIGATE abort(); // No idea what should happen here - I have never got here #endif numberFake_++; } else { setFakeBound(iSequence, ClpSimplexDual::lowerFake); numberFake_++; } } else { if (newUpperValue < upperValue) { setFakeBound(iSequence, ClpSimplexDual::upperFake); numberFake_++; } } if (status == atUpperBound) solution_[iSequence] = newUpperValue; else solution_[iSequence] = newLowerValue; double movement = solution_[iSequence] - value; if (movement && outputArray) { if (iSequence >= numberColumns_) { outputArray->quickAdd(iSequence, -movement); changeCost += movement * cost_[iSequence]; } else { matrix_->add(this, outputArray, iSequence, movement); changeCost += movement * cost_[iSequence]; } } } } dualBound_ = newBound; } else { numberInfeasibilities = -1; } return numberInfeasibilities; } else if (initialize == 1 || initialize == 3) { int iSequence; if (initialize == 3) { for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { setFakeBound(iSequence, ClpSimplexDual::noFake); } } double testBound = 0.999999 * dualBound_; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { Status status = getStatus(iSequence); if (status == atUpperBound || status == atLowerBound) { double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; double value = solution_[iSequence]; if (lowerValue > -largeValue_ || upperValue < largeValue_) { if (true || lowerValue - value > -0.5 * dualBound_ || upperValue - value < 0.5 * dualBound_) { if (fabs(lowerValue - value) <= fabs(upperValue - value)) { if (upperValue > lowerValue + testBound) { if (getFakeBound(iSequence) == ClpSimplexDual::noFake) numberFake_++; upper_[iSequence] = lowerValue + dualBound_; setFakeBound(iSequence, ClpSimplexDual::upperFake); } } else { if (lowerValue < upperValue - testBound) { if (getFakeBound(iSequence) == ClpSimplexDual::noFake) numberFake_++; lower_[iSequence] = upperValue - dualBound_; setFakeBound(iSequence, ClpSimplexDual::lowerFake); } } } else { if (getFakeBound(iSequence) == ClpSimplexDual::noFake) numberFake_++; lower_[iSequence] = -0.5 * dualBound_; upper_[iSequence] = 0.5 * dualBound_; setFakeBound(iSequence, ClpSimplexDual::bothFake); abort(); } if (status == atUpperBound) solution_[iSequence] = upper_[iSequence]; else solution_[iSequence] = lower_[iSequence]; } else { // set non basic free variables to fake bounds // I don't think we should ever get here CoinAssert(!("should not be here")); lower_[iSequence] = -0.5 * dualBound_; upper_[iSequence] = 0.5 * dualBound_; setFakeBound(iSequence, ClpSimplexDual::bothFake); numberFake_++; setStatus(iSequence, atUpperBound); solution_[iSequence] = 0.5 * dualBound_; } } else if (status == basic) { // make sure not at fake bound and bounds correct setFakeBound(iSequence, ClpSimplexDual::noFake); double gap = upper_[iSequence] - lower_[iSequence]; if (gap > 0.5 * dualBound_ && gap < 2.0 * dualBound_) { if (iSequence < numberColumns_) { if (columnScale_) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; // lower double value = columnLower_[iSequence]; if (value > -1.0e30) { value *= multiplier; } lower_[iSequence] = value; // upper value = columnUpper_[iSequence]; if (value < 1.0e30) { value *= multiplier; } upper_[iSequence] = value; } else { lower_[iSequence] = columnLower_[iSequence];; upper_[iSequence] = columnUpper_[iSequence];; } } else { int iRow = iSequence - numberColumns_; if (rowScale_) { // lower double multiplier = rhsScale_ * rowScale_[iRow]; double value = rowLower_[iRow]; if (value > -1.0e30) { value *= multiplier; } lower_[iSequence] = value; // upper value = rowUpper_[iRow]; if (value < 1.0e30) { value *= multiplier; } upper_[iSequence] = value; } else { lower_[iSequence] = rowLower_[iRow];; upper_[iSequence] = rowUpper_[iRow];; } } } } } return 1; } else { // just reset changed ones if (columnScale_) { int iSequence; for (iSequence = 0; iSequence < numberColumns_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); if (fakeStatus != noFake) { if ((static_cast (fakeStatus) & 1) != 0) { // lower double value = columnLower_[iSequence]; if (value > -1.0e30) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; value *= multiplier; } columnLowerWork_[iSequence] = value; } if ((static_cast (fakeStatus) & 2) != 0) { // upper double value = columnUpper_[iSequence]; if (value < 1.0e30) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; value *= multiplier; } columnUpperWork_[iSequence] = value; } } } for (iSequence = 0; iSequence < numberRows_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence + numberColumns_); if (fakeStatus != noFake) { if ((static_cast (fakeStatus) & 1) != 0) { // lower double value = rowLower_[iSequence]; if (value > -1.0e30) { double multiplier = rhsScale_ * rowScale_[iSequence]; value *= multiplier; } rowLowerWork_[iSequence] = value; } if ((static_cast (fakeStatus) & 2) != 0) { // upper double value = rowUpper_[iSequence]; if (value < 1.0e30) { double multiplier = rhsScale_ * rowScale_[iSequence]; value *= multiplier; } rowUpperWork_[iSequence] = value; } } } } else { int iSequence; for (iSequence = 0; iSequence < numberColumns_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); if ((static_cast (fakeStatus) & 1) != 0) { // lower columnLowerWork_[iSequence] = columnLower_[iSequence]; } if ((static_cast (fakeStatus) & 2) != 0) { // upper columnUpperWork_[iSequence] = columnUpper_[iSequence]; } } for (iSequence = 0; iSequence < numberRows_; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence + numberColumns_); if ((static_cast (fakeStatus) & 1) != 0) { // lower rowLowerWork_[iSequence] = rowLower_[iSequence]; } if ((static_cast (fakeStatus) & 2) != 0) { // upper rowUpperWork_[iSequence] = rowUpper_[iSequence]; } } } return 0; } } int ClpSimplexDual::dualColumn0(const CoinIndexedVector * rowArray, const CoinIndexedVector * columnArray, CoinIndexedVector * spareArray, double acceptablePivot, double & upperReturn, double &bestReturn, double & badFree) { // do first pass to get possibles double * spare = spareArray->denseVector(); int * index = spareArray->getIndices(); const double * work; int number; const int * which; const double * reducedCost; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e15; double upperTheta = 1.0e31; double freePivot = acceptablePivot; double bestPossible = 0.0; int numberRemaining = 0; int i; badFree = 0.0; if ((moreSpecialOptions_ & 8) != 0) { // No free or super basic double multiplier[] = { -1.0, 1.0}; double dualT = - dualTolerance_; for (int iSection = 0; iSection < 2; iSection++) { int addSequence; unsigned char * statusArray; if (!iSection) { work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); reducedCost = rowReducedCost_; addSequence = numberColumns_; statusArray = status_ + numberColumns_; } else { work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); reducedCost = reducedCostWork_; addSequence = 0; statusArray = status_; } for (i = 0; i < number; i++) { int iSequence = which[i]; double alpha; double oldValue; double value; assert (getStatus(iSequence + addSequence) != isFree && getStatus(iSequence + addSequence) != superBasic); int iStatus = (statusArray[iSequence] & 3) - 1; if (iStatus) { double mult = multiplier[iStatus-1]; alpha = work[i] * mult; if (alpha > 0.0) { oldValue = reducedCost[iSequence] * mult; value = oldValue - tentativeTheta * alpha; if (value < dualT) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < dualT && alpha >= acceptablePivot) { upperTheta = (oldValue - dualT) / alpha; //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta); } // add to list spare[numberRemaining] = alpha * mult; index[numberRemaining++] = iSequence + addSequence; } } } } } } else { // some free or super basic for (int iSection = 0; iSection < 2; iSection++) { int addSequence; if (!iSection) { work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); reducedCost = rowReducedCost_; addSequence = numberColumns_; } else { work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); reducedCost = reducedCostWork_; addSequence = 0; } for (i = 0; i < number; i++) { int iSequence = which[i]; double alpha; double oldValue; double value; bool keep; switch(getStatus(iSequence + addSequence)) { case basic: case ClpSimplex::isFixed: break; case isFree: case superBasic: alpha = work[i]; bestPossible = CoinMax(bestPossible, fabs(alpha)); oldValue = reducedCost[iSequence]; // If free has to be very large - should come in via dualRow //if (getStatus(iSequence+addSequence)==isFree&&fabs(alpha)<1.0e-3) //break; if (oldValue > dualTolerance_) { keep = true; } else if (oldValue < -dualTolerance_) { keep = true; } else { if (fabs(alpha) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) { keep = true; } else { keep = false; badFree = CoinMax(badFree, fabs(alpha)); } } if (keep) { // free - choose largest if (fabs(alpha) > freePivot) { freePivot = fabs(alpha); sequenceIn_ = iSequence + addSequence; theta_ = oldValue / alpha; alpha_ = alpha; } } break; case atUpperBound: alpha = work[i]; oldValue = reducedCost[iSequence]; value = oldValue - tentativeTheta * alpha; //assert (oldValue<=dualTolerance_*1.0001); if (value > dualTolerance_) { bestPossible = CoinMax(bestPossible, -alpha); value = oldValue - upperTheta * alpha; if (value > dualTolerance_ && -alpha >= acceptablePivot) { upperTheta = (oldValue - dualTolerance_) / alpha; //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta); } // add to list spare[numberRemaining] = alpha; index[numberRemaining++] = iSequence + addSequence; } break; case atLowerBound: alpha = work[i]; oldValue = reducedCost[iSequence]; value = oldValue - tentativeTheta * alpha; //assert (oldValue>=-dualTolerance_*1.0001); if (value < -dualTolerance_) { bestPossible = CoinMax(bestPossible, alpha); value = oldValue - upperTheta * alpha; if (value < -dualTolerance_ && alpha >= acceptablePivot) { upperTheta = (oldValue + dualTolerance_) / alpha; //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta); } // add to list spare[numberRemaining] = alpha; index[numberRemaining++] = iSequence + addSequence; } break; } } } } upperReturn = upperTheta; bestReturn = bestPossible; return numberRemaining; } /* Row array has row part of pivot row (as duals so sign may be switched) Column array has column part. This chooses pivot column. Spare array will be needed when we start getting clever. We will check for basic so spare array will never overflow. If necessary will modify costs */ double ClpSimplexDual::dualColumn(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, CoinIndexedVector * spareArray, CoinIndexedVector * spareArray2, double acceptablePivot, CoinBigIndex * /*dubiousWeights*/) { int numberPossiblySwapped = 0; int numberRemaining = 0; double totalThru = 0.0; // for when variables flip //double saveAcceptable=acceptablePivot; //acceptablePivot=1.0e-9; double bestEverPivot = acceptablePivot; int lastSequence = -1; double lastPivot = 0.0; double upperTheta; double newTolerance = dualTolerance_; //newTolerance = dualTolerance_+1.0e-6*dblParam_[ClpDualTolerance]; // will we need to increase tolerance //bool thisIncrease = false; // If we think we need to modify costs (not if something from broad sweep) bool modifyCosts = false; // Increase in objective due to swapping bounds (may be negative) double increaseInObjective = 0.0; // use spareArrays to put ones looked at in // we are going to flip flop between int iFlip = 0; // Possible list of pivots int interesting[2]; // where possible swapped ones are int swapped[2]; // for zeroing out arrays after int marker[2][2]; // pivot elements double * array[2], * spare, * spare2; // indices int * indices[2], * index, * index2; spareArray2->clear(); array[0] = spareArray->denseVector(); indices[0] = spareArray->getIndices(); spare = array[0]; index = indices[0]; array[1] = spareArray2->denseVector(); indices[1] = spareArray2->getIndices(); int i; // initialize lists for (i = 0; i < 2; i++) { interesting[i] = 0; swapped[i] = numberColumns_; marker[i][0] = 0; marker[i][1] = numberColumns_; } /* First we get a list of possible pivots. We can also see if the problem looks infeasible or whether we want to pivot in free variable. This may make objective go backwards but can only happen a finite number of times and I do want free variables basic. Then we flip back and forth. At the start of each iteration interesting[iFlip] should have possible candidates and swapped[iFlip] will have pivots if we decide to take a previous pivot. At end of each iteration interesting[1-iFlip] should have candidates if we go through this theta and swapped[1-iFlip] pivots if we don't go through. At first we increase theta and see what happens. We start theta at a reasonable guess. If in right area then we do bit by bit. */ // do first pass to get possibles upperTheta = 1.0e31; double bestPossible = 0.0; double badFree = 0.0; alpha_ = 0.0; if (spareIntArray_[0] >= 0) { numberRemaining = dualColumn0(rowArray, columnArray, spareArray, acceptablePivot, upperTheta, bestPossible, badFree); } else { // already done numberRemaining = spareArray->getNumElements(); spareArray->setNumElements(0); upperTheta = spareDoubleArray_[0]; bestPossible = spareDoubleArray_[1]; if (spareIntArray_[0] == -1) { theta_ = spareDoubleArray_[2]; alpha_ = spareDoubleArray_[3]; sequenceIn_ = spareIntArray_[1]; } else { #if 0 int n = numberRemaining; double u = upperTheta; double b = bestPossible; upperTheta = 1.0e31; bestPossible = 0.0; numberRemaining = dualColumn0(rowArray, columnArray, spareArray, acceptablePivot, upperTheta, bestPossible, badFree); assert (n == numberRemaining); assert (fabs(b - bestPossible) < 1.0e-7); assert (fabs(u - upperTheta) < 1.0e-7); #endif } } // switch off spareIntArray_[0] = 0; // We can also see if infeasible or pivoting on free double tentativeTheta = 1.0e25; interesting[0] = numberRemaining; marker[0][0] = numberRemaining; if (!numberRemaining && sequenceIn_ < 0) return 0.0; // Looks infeasible // If sum of bad small pivots too much #define MORE_CAREFUL #ifdef MORE_CAREFUL bool badSumPivots = false; #endif if (sequenceIn_ >= 0) { // free variable - always choose } else { theta_ = 1.0e50; // now flip flop between spare arrays until reasonable theta tentativeTheta = CoinMax(10.0 * upperTheta, 1.0e-7); // loops increasing tentative theta until can't go through while (tentativeTheta < 1.0e22) { double thruThis = 0.0; double bestPivot = acceptablePivot; int bestSequence = -1; numberPossiblySwapped = numberColumns_; numberRemaining = 0; upperTheta = 1.0e50; spare = array[iFlip]; index = indices[iFlip]; spare2 = array[1-iFlip]; index2 = indices[1-iFlip]; // try 3 different ways // 1 bias increase by ones with slightly wrong djs // 2 bias by all // 3 bias by all - tolerance #define TRYBIAS 3 double increaseInThis = 0.0; //objective increase in this loop for (i = 0; i < interesting[iFlip]; i++) { int iSequence = index[i]; double alpha = spare[i]; double oldValue = dj_[iSequence]; double value = oldValue - tentativeTheta * alpha; if (alpha < 0.0) { //at upper bound if (value > newTolerance) { double range = upper_[iSequence] - lower_[iSequence]; thruThis -= range * alpha; #if TRYBIAS==1 if (oldValue > 0.0) increaseInThis -= oldValue * range; #elif TRYBIAS==2 increaseInThis -= oldValue * range; #else increaseInThis -= (oldValue + dualTolerance_) * range; #endif // goes on swapped list (also means candidates if too many) spare2[--numberPossiblySwapped] = alpha; index2[numberPossiblySwapped] = iSequence; if (fabs(alpha) > bestPivot) { bestPivot = fabs(alpha); bestSequence = numberPossiblySwapped; } } else { value = oldValue - upperTheta * alpha; if (value > newTolerance && -alpha >= acceptablePivot) upperTheta = (oldValue - newTolerance) / alpha; spare2[numberRemaining] = alpha; index2[numberRemaining++] = iSequence; } } else { // at lower bound if (value < -newTolerance) { double range = upper_[iSequence] - lower_[iSequence]; thruThis += range * alpha; //?? is this correct - and should we look at good ones #if TRYBIAS==1 if (oldValue < 0.0) increaseInThis += oldValue * range; #elif TRYBIAS==2 increaseInThis += oldValue * range; #else increaseInThis += (oldValue - dualTolerance_) * range; #endif // goes on swapped list (also means candidates if too many) spare2[--numberPossiblySwapped] = alpha; index2[numberPossiblySwapped] = iSequence; if (fabs(alpha) > bestPivot) { bestPivot = fabs(alpha); bestSequence = numberPossiblySwapped; } } else { value = oldValue - upperTheta * alpha; if (value < -newTolerance && alpha >= acceptablePivot) upperTheta = (oldValue + newTolerance) / alpha; spare2[numberRemaining] = alpha; index2[numberRemaining++] = iSequence; } } } swapped[1-iFlip] = numberPossiblySwapped; interesting[1-iFlip] = numberRemaining; marker[1-iFlip][0] = CoinMax(marker[1-iFlip][0], numberRemaining); marker[1-iFlip][1] = CoinMin(marker[1-iFlip][1], numberPossiblySwapped); if (totalThru + thruThis >= fabs(dualOut_) || increaseInObjective + increaseInThis < 0.0) { // We should be pivoting in this batch // so compress down to this lot numberRemaining = 0; for (i = numberColumns_ - 1; i >= swapped[1-iFlip]; i--) { spare[numberRemaining] = spare2[i]; index[numberRemaining++] = index2[i]; } interesting[iFlip] = numberRemaining; int iTry; #define MAXTRY 100 // first get ratio with tolerance for (iTry = 0; iTry < MAXTRY; iTry++) { upperTheta = 1.0e50; numberPossiblySwapped = numberColumns_; numberRemaining = 0; increaseInThis = 0.0; //objective increase in this loop thruThis = 0.0; spare = array[iFlip]; index = indices[iFlip]; spare2 = array[1-iFlip]; index2 = indices[1-iFlip]; for (i = 0; i < interesting[iFlip]; i++) { int iSequence = index[i]; double alpha = spare[i]; double oldValue = dj_[iSequence]; double value = oldValue - upperTheta * alpha; if (alpha < 0.0) { //at upper bound if (value > newTolerance) { if (-alpha >= acceptablePivot) { upperTheta = (oldValue - newTolerance) / alpha; } } } else { // at lower bound if (value < -newTolerance) { if (alpha >= acceptablePivot) { upperTheta = (oldValue + newTolerance) / alpha; } } } } bestPivot = acceptablePivot; sequenceIn_ = -1; #ifdef DUBIOUS_WEIGHTS double bestWeight = COIN_DBL_MAX; #endif double largestPivot = acceptablePivot; // now choose largest and sum all ones which will go through //printf("XX it %d number %d\n",numberIterations_,interesting[iFlip]); // Sum of bad small pivots #ifdef MORE_CAREFUL double sumBadPivots = 0.0; badSumPivots = false; #endif // Make sure upperTheta will work (-O2 and above gives problems) upperTheta *= 1.0000000001; for (i = 0; i < interesting[iFlip]; i++) { int iSequence = index[i]; double alpha = spare[i]; double value = dj_[iSequence] - upperTheta * alpha; double badDj = 0.0; bool addToSwapped = false; if (alpha < 0.0) { //at upper bound if (value >= 0.0) { addToSwapped = true; #if TRYBIAS==1 badDj = -CoinMax(dj_[iSequence], 0.0); #elif TRYBIAS==2 badDj = -dj_[iSequence]; #else badDj = -dj_[iSequence] - dualTolerance_; #endif } } else { // at lower bound if (value <= 0.0) { addToSwapped = true; #if TRYBIAS==1 badDj = CoinMin(dj_[iSequence], 0.0); #elif TRYBIAS==2 badDj = dj_[iSequence]; #else badDj = dj_[iSequence] - dualTolerance_; #endif } } if (!addToSwapped) { // add to list of remaining spare2[numberRemaining] = alpha; index2[numberRemaining++] = iSequence; } else { // add to list of swapped spare2[--numberPossiblySwapped] = alpha; index2[numberPossiblySwapped] = iSequence; // select if largest pivot bool take = false; double absAlpha = fabs(alpha); #ifdef DUBIOUS_WEIGHTS // User could do anything to break ties here double weight; if (dubiousWeights) weight = dubiousWeights[iSequence]; else weight = 1.0; weight += randomNumberGenerator_.randomDouble() * 1.0e-2; if (absAlpha > 2.0 * bestPivot) { take = true; } else if (absAlpha > largestPivot) { // could multiply absAlpha and weight if (weight * bestPivot < bestWeight * absAlpha) take = true; } #else if (absAlpha > bestPivot) take = true; #endif #ifdef MORE_CAREFUL if (absAlpha < acceptablePivot && upperTheta < 1.0e20) { if (alpha < 0.0) { //at upper bound if (value > dualTolerance_) { double gap = upper_[iSequence] - lower_[iSequence]; if (gap < 1.0e20) sumBadPivots += value * gap; else sumBadPivots += 1.0e20; //printf("bad %d alpha %g dj at upper %g\n", // iSequence,alpha,value); } } else { //at lower bound if (value < -dualTolerance_) { double gap = upper_[iSequence] - lower_[iSequence]; if (gap < 1.0e20) sumBadPivots -= value * gap; else sumBadPivots += 1.0e20; //printf("bad %d alpha %g dj at lower %g\n", // iSequence,alpha,value); } } } #endif #ifdef FORCE_FOLLOW if (iSequence == force_in) { printf("taking %d - alpha %g best %g\n", force_in, absAlpha, largestPivot); take = true; } #endif if (take) { sequenceIn_ = numberPossiblySwapped; bestPivot = absAlpha; theta_ = dj_[iSequence] / alpha; largestPivot = CoinMax(largestPivot, 0.5 * bestPivot); #ifdef DUBIOUS_WEIGHTS bestWeight = weight; #endif //printf(" taken seq %d alpha %g weight %d\n", // iSequence,absAlpha,dubiousWeights[iSequence]); } else { //printf(" not taken seq %d alpha %g weight %d\n", // iSequence,absAlpha,dubiousWeights[iSequence]); } double range = upper_[iSequence] - lower_[iSequence]; thruThis += range * fabs(alpha); increaseInThis += badDj * range; } } marker[1-iFlip][0] = CoinMax(marker[1-iFlip][0], numberRemaining); marker[1-iFlip][1] = CoinMin(marker[1-iFlip][1], numberPossiblySwapped); #ifdef MORE_CAREFUL // If we have done pivots and things look bad set alpha_ 0.0 to force factorization if (sumBadPivots > 1.0e4) { if (handler_->logLevel() > 1) *handler_ << "maybe forcing re-factorization - sum " << sumBadPivots << " " << factorization_->pivots() << " pivots" << CoinMessageEol; if(factorization_->pivots() > 3) { badSumPivots = true; break; } } #endif swapped[1-iFlip] = numberPossiblySwapped; interesting[1-iFlip] = numberRemaining; // If we stop now this will be increase in objective (I think) double increase = (fabs(dualOut_) - totalThru) * theta_; increase += increaseInObjective; if (theta_ < 0.0) thruThis += fabs(dualOut_); // force using this one if (increaseInObjective < 0.0 && increase < 0.0 && lastSequence >= 0) { // back // We may need to be more careful - we could do by // switch so we always do fine grained? bestPivot = 0.0; } else { // add in totalThru += thruThis; increaseInObjective += increaseInThis; } if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && (bestPivot < 1.0e-3 || totalThru * 2.0 > fabs(dualOut_))) { // back to previous one sequenceIn_ = lastSequence; // swap regions iFlip = 1 - iFlip; break; } else if (sequenceIn_ == -1 && upperTheta > largeValue_) { if (lastPivot > acceptablePivot) { // back to previous one sequenceIn_ = lastSequence; // swap regions iFlip = 1 - iFlip; } else { // can only get here if all pivots too small } break; } else if (totalThru >= fabs(dualOut_)) { modifyCosts = true; // fine grain - we can modify costs break; // no point trying another loop } else { lastSequence = sequenceIn_; if (bestPivot > bestEverPivot) bestEverPivot = bestPivot; iFlip = 1 - iFlip; modifyCosts = true; // fine grain - we can modify costs } } if (iTry == MAXTRY) iFlip = 1 - iFlip; // flip back break; } else { // skip this lot if (bestPivot > 1.0e-3 || bestPivot > bestEverPivot) { bestEverPivot = bestPivot; lastSequence = bestSequence; } else { // keep old swapped CoinMemcpyN(array[iFlip] + swapped[iFlip], numberColumns_ - swapped[iFlip], array[1-iFlip] + swapped[iFlip]); CoinMemcpyN(indices[iFlip] + swapped[iFlip], numberColumns_ - swapped[iFlip], indices[1-iFlip] + swapped[iFlip]); marker[1-iFlip][1] = CoinMin(marker[1-iFlip][1], swapped[iFlip]); swapped[1-iFlip] = swapped[iFlip]; } increaseInObjective += increaseInThis; iFlip = 1 - iFlip; // swap regions tentativeTheta = 2.0 * upperTheta; totalThru += thruThis; } } // can get here without sequenceIn_ set but with lastSequence if (sequenceIn_ < 0 && lastSequence >= 0) { // back to previous one sequenceIn_ = lastSequence; // swap regions iFlip = 1 - iFlip; } #define MINIMUMTHETA 1.0e-18 // Movement should be minimum for anti-degeneracy - unless // fixed variable out double minimumTheta; if (upperOut_ > lowerOut_) minimumTheta = MINIMUMTHETA; else minimumTheta = 0.0; if (sequenceIn_ >= 0) { // at this stage sequenceIn_ is just pointer into index array // flip just so we can use iFlip iFlip = 1 - iFlip; spare = array[iFlip]; index = indices[iFlip]; double oldValue; alpha_ = spare[sequenceIn_]; sequenceIn_ = indices[iFlip][sequenceIn_]; oldValue = dj_[sequenceIn_]; theta_ = CoinMax(oldValue / alpha_, 0.0); if (theta_ < minimumTheta && fabs(alpha_) < 1.0e5 && 1) { // can't pivot to zero #if 0 if (oldValue - minimumTheta*alpha_ >= -dualTolerance_) { theta_ = minimumTheta; } else if (oldValue - minimumTheta*alpha_ >= -newTolerance) { theta_ = minimumTheta; thisIncrease = true; } else { theta_ = CoinMax((oldValue + newTolerance) / alpha_, 0.0); thisIncrease = true; } #else theta_ = minimumTheta; #endif } // may need to adjust costs so all dual feasible AND pivoted is exactly 0 //int costOffset = numberRows_+numberColumns_; if (modifyCosts && !badSumPivots) { int i; for (i = numberColumns_ - 1; i >= swapped[iFlip]; i--) { int iSequence = index[i]; double alpha = spare[i]; double value = dj_[iSequence] - theta_ * alpha; // can't be free here if (alpha < 0.0) { //at upper bound if (value > dualTolerance_) { //thisIncrease = true; #if CLP_CAN_HAVE_ZERO_OBJ<2 #define MODIFYCOST 2 #endif #if MODIFYCOST // modify cost to hit new tolerance double modification = alpha * theta_ - dj_[iSequence] + newTolerance; if ((specialOptions_&(2048 + 4096 + 16384)) != 0) { if ((specialOptions_ & 16384) != 0) { if (fabs(modification) < 1.0e-8) modification = 0.0; } else if ((specialOptions_ & 2048) != 0) { if (fabs(modification) < 1.0e-10) modification = 0.0; } else { if (fabs(modification) < 1.0e-12) modification = 0.0; } } dj_[iSequence] += modification; cost_[iSequence] += modification; if (modification) numberChanged_ ++; // Say changed costs //cost_[iSequence+costOffset] += modification; // save change #endif } } else { // at lower bound if (-value > dualTolerance_) { //thisIncrease = true; #if MODIFYCOST // modify cost to hit new tolerance double modification = alpha * theta_ - dj_[iSequence] - newTolerance; //modification = CoinMax(modification,-dualTolerance_); //assert (fabs(modification)<1.0e-7); if ((specialOptions_&(2048 + 4096)) != 0) { if ((specialOptions_ & 2048) != 0) { if (fabs(modification) < 1.0e-10) modification = 0.0; } else { if (fabs(modification) < 1.0e-12) modification = 0.0; } } dj_[iSequence] += modification; cost_[iSequence] += modification; if (modification) numberChanged_ ++; // Say changed costs //cost_[iSequence+costOffset] += modification; // save change #endif } } } } } } #ifdef MORE_CAREFUL // If we have done pivots and things look bad set alpha_ 0.0 to force factorization if ((badSumPivots || fabs(theta_ * badFree) > 10.0 * dualTolerance_) && factorization_->pivots()) { if (handler_->logLevel() > 1) *handler_ << "forcing re-factorization" << CoinMessageEol; sequenceIn_ = -1; } #endif if (sequenceIn_ >= 0) { lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (numberTimesOptimal_) { // can we adjust cost back closer to original //*** add coding } #if MODIFYCOST>1 // modify cost to hit zero exactly // so (dualIn_+modification)==theta_*alpha_ double modification = theta_ * alpha_ - dualIn_; // But should not move objective too much ?? #define DONT_MOVE_OBJECTIVE #ifdef DONT_MOVE_OBJECTIVE double moveObjective = fabs(modification * solution_[sequenceIn_]); double smallMove = CoinMax(fabs(objectiveValue_), 1.0e-3); if (moveObjective > smallMove) { if (handler_->logLevel() > 1) printf("would move objective by %g - original mod %g sol value %g\n", moveObjective, modification, solution_[sequenceIn_]); modification *= smallMove / moveObjective; } #endif if (badSumPivots) modification = 0.0; if ((specialOptions_&(2048 + 4096)) != 0) { if ((specialOptions_ & 16384) != 0) { // in fast dual if (fabs(modification) < 1.0e-7) modification = 0.0; } else if ((specialOptions_ & 2048) != 0) { if (fabs(modification) < 1.0e-10) modification = 0.0; } else { if (fabs(modification) < 1.0e-12) modification = 0.0; } } dualIn_ += modification; dj_[sequenceIn_] = dualIn_; cost_[sequenceIn_] += modification; if (modification) numberChanged_ ++; // Say changed costs //int costOffset = numberRows_+numberColumns_; //cost_[sequenceIn_+costOffset] += modification; // save change //assert (fabs(modification)<1.0e-6); #ifdef CLP_DEBUG if ((handler_->logLevel() & 32) && fabs(modification) > 1.0e-15) printf("exact %d new cost %g, change %g\n", sequenceIn_, cost_[sequenceIn_], modification); #endif #endif if (alpha_ < 0.0) { // as if from upper bound directionIn_ = -1; upperIn_ = valueIn_; } else { // as if from lower bound directionIn_ = 1; lowerIn_ = valueIn_; } } else { // no pivot bestPossible = 0.0; alpha_ = 0.0; } //if (thisIncrease) //dualTolerance_+= 1.0e-6*dblParam_[ClpDualTolerance]; // clear arrays for (i = 0; i < 2; i++) { CoinZeroN(array[i], marker[i][0]); CoinZeroN(array[i] + marker[i][1], numberColumns_ - marker[i][1]); } return bestPossible; } #ifdef CLP_ALL_ONE_FILE #undef MAXTRY #endif /* Checks if tentative optimal actually means unbounded Returns -3 if not, 2 if is unbounded */ int ClpSimplexDual::checkUnbounded(CoinIndexedVector * ray, CoinIndexedVector * spare, double changeCost) { int status = 2; // say unbounded factorization_->updateColumn(spare, ray); // get reduced cost int i; int number = ray->getNumElements(); int * index = ray->getIndices(); double * array = ray->denseVector(); for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; changeCost -= cost(iPivot) * array[iRow]; } double way; if (changeCost > 0.0) { //try going down way = 1.0; } else if (changeCost < 0.0) { //try going up way = -1.0; } else { #ifdef CLP_DEBUG printf("can't decide on up or down\n"); #endif way = 0.0; status = -3; } double movement = 1.0e10 * way; // some largish number double zeroTolerance = 1.0e-14 * dualBound_; for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; double arrayValue = array[iRow]; if (fabs(arrayValue) < zeroTolerance) arrayValue = 0.0; double newValue = solution(iPivot) + movement * arrayValue; if (newValue > upper(iPivot) + primalTolerance_ || newValue < lower(iPivot) - primalTolerance_) status = -3; // not unbounded } if (status == 2) { // create ray delete [] ray_; ray_ = new double [numberColumns_]; CoinZeroN(ray_, numberColumns_); for (i = 0; i < number; i++) { int iRow = index[i]; int iPivot = pivotVariable_[iRow]; double arrayValue = array[iRow]; if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance) ray_[iPivot] = way * array[iRow]; } } ray->clear(); return status; } //static int count_alpha=0; /* Checks if finished. Updates status */ void ClpSimplexDual::statusOfProblemInDual(int & lastCleaned, int type, double * givenDuals, ClpDataSave & saveData, int ifValuesPass) { #ifdef CLP_INVESTIGATE_SERIAL if (z_thinks > 0 && z_thinks < 2) z_thinks += 2; #endif bool arraysNotCreated = (type==0); // If lots of iterations then adjust costs if large ones if (numberIterations_ > 4 * (numberRows_ + numberColumns_) && objectiveScale_ == 1.0) { double largest = 0.0; for (int i = 0; i < numberRows_; i++) { int iColumn = pivotVariable_[i]; largest = CoinMax(largest, fabs(cost_[iColumn])); } if (largest > 1.0e6) { objectiveScale_ = 1.0e6 / largest; for (int i = 0; i < numberRows_ + numberColumns_; i++) cost_[i] *= objectiveScale_; } } int numberPivots = factorization_->pivots(); double realDualInfeasibilities = 0.0; if (type == 2) { if (alphaAccuracy_ != -1.0) alphaAccuracy_ = -2.0; // trouble - restore solution CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); forceFactorization_ = 1; // a bit drastic but .. changeMade_++; // say something changed // get correct bounds on all variables resetFakeBounds(0); } int tentativeStatus = problemStatus_; double changeCost; bool unflagVariables = true; bool weightsSaved = false; bool weightsSaved2 = numberIterations_ && !numberPrimalInfeasibilities_; int dontFactorizePivots = dontFactorizePivots_; if (type == 3) { type = 1; dontFactorizePivots = 1; } if (alphaAccuracy_ < 0.0 || !numberPivots || alphaAccuracy_ > 1.0e4 || numberPivots > 20) { if (problemStatus_ > -3 || numberPivots > dontFactorizePivots) { // factorize // later on we will need to recover from singularities // also we could skip if first time // save dual weights dualRowPivot_->saveWeights(this, 1); weightsSaved = true; if (type) { // is factorization okay? if (internalFactorize(1)) { // no - restore previous basis unflagVariables = false; assert (type == 1); changeMade_++; // say something changed // Keep any flagged variables int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (flagged(i)) saveStatus_[i] |= 64; //say flagged } CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); // get correct bounds on all variables resetFakeBounds(1); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag d\n"); #endif setFlagged(sequenceOut_); progress_.clearBadTimes(); // Go to safe factorization_->pivotTolerance(0.99); forceFactorization_ = 1; // a bit drastic but .. type = 2; //assert (internalFactorize(1)==0); if (internalFactorize(1)) { CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); // debug int returnCode = internalFactorize(1); while (returnCode) { // ouch // switch off dense int saveDense = factorization_->denseThreshold(); factorization_->setDenseThreshold(0); // Go to safe factorization_->pivotTolerance(0.99); // make sure will do safe factorization pivotVariable_[0] = -1; returnCode = internalFactorize(2); factorization_->setDenseThreshold(saveDense); } // get correct bounds on all variables resetFakeBounds(1); } } } if (problemStatus_ != -4 || numberPivots > 10) problemStatus_ = -3; } } else { //printf("testing with accuracy of %g and status of %d\n",alphaAccuracy_,problemStatus_); //count_alpha++; //if ((count_alpha%5000)==0) //printf("count alpha %d\n",count_alpha); } // at this stage status is -3 or -4 if looks infeasible // get primal and dual solutions #if 0 { int numberTotal = numberRows_ + numberColumns_; double * saveSol = CoinCopyOfArray(solution_, numberTotal); double * saveDj = CoinCopyOfArray(dj_, numberTotal); double tolerance = type ? 1.0e-4 : 1.0e-8; // always if values pass double saveObj = objectiveValue_; double sumPrimal = sumPrimalInfeasibilities_; int numberPrimal = numberPrimalInfeasibilities_; double sumDual = sumDualInfeasibilities_; int numberDual = numberDualInfeasibilities_; gutsOfSolution(givenDuals, NULL); int j; double largestPrimal = tolerance; int iPrimal = -1; for (j = 0; j < numberTotal; j++) { double difference = solution_[j] - saveSol[j]; if (fabs(difference) > largestPrimal) { iPrimal = j; largestPrimal = fabs(difference); } } double largestDual = tolerance; int iDual = -1; for (j = 0; j < numberTotal; j++) { double difference = dj_[j] - saveDj[j]; if (fabs(difference) > largestDual && upper_[j] > lower_[j]) { iDual = j; largestDual = fabs(difference); } } if (!type) { if (fabs(saveObj - objectiveValue_) > 1.0e-5 || numberPrimal != numberPrimalInfeasibilities_ || numberPrimal != 1 || fabs(sumPrimal - sumPrimalInfeasibilities_) > 1.0e-5 || iPrimal >= 0 || numberDual != numberDualInfeasibilities_ || numberDual != 0 || fabs(sumDual - sumDualInfeasibilities_) > 1.0e-5 || iDual >= 0) printf("type %d its %d pivots %d primal n(%d,%d) s(%g,%g) diff(%g,%d) dual n(%d,%d) s(%g,%g) diff(%g,%d) obj(%g,%g)\n", type, numberIterations_, numberPivots, numberPrimal, numberPrimalInfeasibilities_, sumPrimal, sumPrimalInfeasibilities_, largestPrimal, iPrimal, numberDual, numberDualInfeasibilities_, sumDual, sumDualInfeasibilities_, largestDual, iDual, saveObj, objectiveValue_); } else { if (fabs(saveObj - objectiveValue_) > 1.0e-5 || numberPrimalInfeasibilities_ || iPrimal >= 0 || numberDualInfeasibilities_ || iDual >= 0) printf("type %d its %d pivots %d primal n(%d,%d) s(%g,%g) diff(%g,%d) dual n(%d,%d) s(%g,%g) diff(%g,%d) obj(%g,%g)\n", type, numberIterations_, numberPivots, numberPrimal, numberPrimalInfeasibilities_, sumPrimal, sumPrimalInfeasibilities_, largestPrimal, iPrimal, numberDual, numberDualInfeasibilities_, sumDual, sumDualInfeasibilities_, largestDual, iDual, saveObj, objectiveValue_); } delete [] saveSol; delete [] saveDj; } #else if (type || ifValuesPass) gutsOfSolution(givenDuals, NULL); #endif // If bad accuracy treat as singular if ((largestPrimalError_ > 1.0e15 || largestDualError_ > 1.0e15) && numberIterations_) { // restore previous basis unflagVariables = false; changeMade_++; // say something changed // Keep any flagged variables int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (flagged(i)) saveStatus_[i] |= 64; //say flagged } CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); // get correct bounds on all variables resetFakeBounds(1); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag e\n"); #endif setFlagged(sequenceOut_); progress_.clearBadTimes(); // Go to safer double newTolerance = CoinMin(1.1 * factorization_->pivotTolerance(), 0.99); factorization_->pivotTolerance(newTolerance); forceFactorization_ = 1; // a bit drastic but .. if (alphaAccuracy_ != -1.0) alphaAccuracy_ = -2.0; type = 2; //assert (internalFactorize(1)==0); if (internalFactorize(1)) { CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); // debug int returnCode = internalFactorize(1); while (returnCode) { // ouch // switch off dense int saveDense = factorization_->denseThreshold(); factorization_->setDenseThreshold(0); // Go to safe factorization_->pivotTolerance(0.99); // make sure will do safe factorization pivotVariable_[0] = -1; returnCode = internalFactorize(2); factorization_->setDenseThreshold(saveDense); } // get correct bounds on all variables resetFakeBounds(1); } // get primal and dual solutions gutsOfSolution(givenDuals, NULL); } else if (goodAccuracy()) { // Can reduce tolerance double newTolerance = CoinMax(0.99 * factorization_->pivotTolerance(), saveData.pivotTolerance_); factorization_->pivotTolerance(newTolerance); } bestObjectiveValue_ = CoinMax(bestObjectiveValue_, objectiveValue_ - bestPossibleImprovement_); bool reallyBadProblems = false; // Double check infeasibility if no action if (progress_.lastIterationNumber(0) == numberIterations_) { if (dualRowPivot_->looksOptimal()) { numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } #if 1 } else { double thisObj = objectiveValue_ - bestPossibleImprovement_; #ifdef CLP_INVESTIGATE assert (bestPossibleImprovement_ > -1000.0 && objectiveValue_ > -1.0e100); if (bestPossibleImprovement_) printf("obj %g add in %g -> %g\n", objectiveValue_, bestPossibleImprovement_, thisObj); #endif double lastObj = progress_.lastObjective(0); #ifndef NDEBUG #ifdef COIN_DEVELOP resetFakeBounds(-1); #endif #endif #ifdef CLP_REPORT_PROGRESS ixxxxxx++; if (ixxxxxx >= ixxyyyy - 4 && ixxxxxx <= ixxyyyy) { char temp[20]; sprintf(temp, "sol%d.out", ixxxxxx); printf("sol%d.out\n", ixxxxxx); FILE * fp = fopen(temp, "w"); int nTotal = numberRows_ + numberColumns_; for (int i = 0; i < nTotal; i++) fprintf(fp, "%d %d %g %g %g %g %g\n", i, status_[i], lower_[i], solution_[i], upper_[i], cost_[i], dj_[i]); fclose(fp); } #endif if(!ifValuesPass && firstFree_ < 0) { double testTol = 5.0e-3; if (progress_.timesFlagged() > 10) { testTol *= pow(2.0, progress_.timesFlagged() - 8); } else if (progress_.timesFlagged() > 5) { testTol *= 5.0; } if (lastObj > thisObj + testTol*(fabs(thisObj) + fabs(lastObj)) + testTol) { int maxFactor = factorization_->maximumPivots(); if ((specialOptions_ & 1048576) == 0) { if (progress_.timesFlagged() > 10) progress_.incrementReallyBadTimes(); if (maxFactor > 10 - 9) { #ifdef COIN_DEVELOP printf("lastobj %g thisobj %g\n", lastObj, thisObj); #endif //if (forceFactorization_<0) //forceFactorization_= maxFactor; //forceFactorization_ = CoinMax(1,(forceFactorization_>>1)); if ((progressFlag_ & 4) == 0 && lastObj < thisObj + 1.0e4 && largestPrimalError_ < 1.0e2) { // Just save costs // save extra copy of cost_ int nTotal = numberRows_ + numberColumns_; double * temp = new double [2*nTotal]; memcpy(temp, cost_, nTotal * sizeof(double)); memcpy(temp + nTotal, cost_, nTotal * sizeof(double)); delete [] cost_; cost_ = temp; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; progressFlag_ |= 4; } else { forceFactorization_ = 1; #ifdef COIN_DEVELOP printf("Reducing factorization frequency - bad backwards\n"); #endif #if 1 unflagVariables = false; changeMade_++; // say something changed int nTotal = numberRows_ + numberColumns_; CoinMemcpyN(saveStatus_, nTotal, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); if ((progressFlag_ & 4) == 0) { // save extra copy of cost_ double * temp = new double [2*nTotal]; memcpy(temp, cost_, nTotal * sizeof(double)); memcpy(temp + nTotal, cost_, nTotal * sizeof(double)); delete [] cost_; cost_ = temp; objectiveWork_ = cost_; rowObjectiveWork_ = cost_ + numberColumns_; progressFlag_ |= 4; } else { memcpy(cost_, cost_ + nTotal, nTotal * sizeof(double)); } // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); double pivotTolerance = factorization_->pivotTolerance(); if(pivotTolerance < 0.2) factorization_->pivotTolerance(0.2); else if(progress_.timesFlagged() > 2) factorization_->pivotTolerance(CoinMin(pivotTolerance * 1.1, 0.99)); if (alphaAccuracy_ != -1.0) alphaAccuracy_ = -2.0; if (internalFactorize(1)) { CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); // restore extra stuff int dummy; matrix_->generalExpanded(this, 6, dummy); // debug int returnCode = internalFactorize(1); while (returnCode) { // ouch // switch off dense int saveDense = factorization_->denseThreshold(); factorization_->setDenseThreshold(0); // Go to safe factorization_->pivotTolerance(0.99); // make sure will do safe factorization pivotVariable_[0] = -1; returnCode = internalFactorize(2); factorization_->setDenseThreshold(saveDense); } } resetFakeBounds(0); type = 2; // so will restore weights // get primal and dual solutions gutsOfSolution(givenDuals, NULL); if (numberPivots < 2) { // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; #ifdef COIN_DEVELOP printf("flag d\n"); #endif setFlagged(sequenceOut_); progress_.clearBadTimes(); progress_.incrementTimesFlagged(); } if (numberPivots < 10) reallyBadProblems = true; #ifdef COIN_DEVELOP printf("obj now %g\n", objectiveValue_); #endif progress_.modifyObjective(objectiveValue_ - bestPossibleImprovement_); #endif } } } else { // in fast dual give up #ifdef COIN_DEVELOP printf("In fast dual?\n"); #endif problemStatus_ = 3; } } else if (lastObj < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj)) - 1.0e-3) { numberTimesOptimal_ = 0; } } #endif } // Up tolerance if looks a bit odd if (numberIterations_ > CoinMax(1000, numberRows_ >> 4) && (specialOptions_ & 64) != 0) { if (sumPrimalInfeasibilities_ && sumPrimalInfeasibilities_ < 1.0e5) { int backIteration = progress_.lastIterationNumber(CLP_PROGRESS - 1); if (backIteration > 0 && numberIterations_ - backIteration < 9 * CLP_PROGRESS) { if (factorization_->pivotTolerance() < 0.9) { // up tolerance factorization_->pivotTolerance(CoinMin(factorization_->pivotTolerance() * 1.05 + 0.02, 0.91)); //printf("tol now %g\n",factorization_->pivotTolerance()); progress_.clearIterationNumbers(); } } } } // Check if looping int loop; if (!givenDuals && type != 2) loop = progress_.looping(); else loop = -1; if (progress_.reallyBadTimes() > 10) { problemStatus_ = 10; // instead - try other algorithm #if COIN_DEVELOP>2 printf("returning at %d\n", __LINE__); #endif } int situationChanged = 0; if (loop >= 0) { problemStatus_ = loop; //exit if in loop if (!problemStatus_) { // declaring victory numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else { problemStatus_ = 10; // instead - try other algorithm #if COIN_DEVELOP>2 printf("returning at %d\n", __LINE__); #endif } return; } else if (loop < -1) { // something may have changed gutsOfSolution(NULL, NULL); situationChanged = 1; } // really for free variables in if((progressFlag_ & 2) != 0) { situationChanged = 2; } progressFlag_ &= (~3); //reset progress flag if ((progressFlag_ & 4) != 0) { // save copy of cost_ int nTotal = numberRows_ + numberColumns_; memcpy(cost_ + nTotal, cost_, nTotal * sizeof(double)); } /*if (!numberIterations_&&sumDualInfeasibilities_) printf("OBJ %g sumPinf %g sumDinf %g\n", objectiveValue(),sumPrimalInfeasibilities_, sumDualInfeasibilities_);*/ // mark as having gone optimal if looks like it if (!numberPrimalInfeasibilities_&& !numberDualInfeasibilities_) progressFlag_ |= 8; if (handler_->detail(CLP_SIMPLEX_STATUS, messages_) < 100) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } #if 0 printf("IT %d %g %g(%d) %g(%d)\n", numberIterations_, objectiveValue(), sumPrimalInfeasibilities_, numberPrimalInfeasibilities_, sumDualInfeasibilities_, numberDualInfeasibilities_); #endif double approximateObjective = objectiveValue_; #ifdef CLP_REPORT_PROGRESS if (ixxxxxx >= ixxyyyy - 4 && ixxxxxx <= ixxyyyy) { char temp[20]; sprintf(temp, "x_sol%d.out", ixxxxxx); FILE * fp = fopen(temp, "w"); int nTotal = numberRows_ + numberColumns_; for (int i = 0; i < nTotal; i++) fprintf(fp, "%d %d %g %g %g %g %g\n", i, status_[i], lower_[i], solution_[i], upper_[i], cost_[i], dj_[i]); fclose(fp); if (ixxxxxx == ixxyyyy) exit(6); } #endif realDualInfeasibilities = sumDualInfeasibilities_; double saveTolerance = dualTolerance_; // If we need to carry on cleaning variables if (!numberPrimalInfeasibilities_ && (specialOptions_ & 1024) != 0 && CLEAN_FIXED) { for (int iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (!flagged(iPivot) && pivoted(iPivot)) { // carry on numberPrimalInfeasibilities_ = -1; sumOfRelaxedPrimalInfeasibilities_ = 1.0; sumPrimalInfeasibilities_ = 1.0; break; } } } /* If we are primal feasible and any dual infeasibilities are on free variables then it is better to go to primal */ if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilitiesWithoutFree_ && numberDualInfeasibilities_) problemStatus_ = 10; // dual bound coming in //double saveDualBound = dualBound_; bool needCleanFake = false; while (problemStatus_ <= -3) { int cleanDuals = 0; if (situationChanged != 0) cleanDuals = 1; int numberChangedBounds = 0; int doOriginalTolerance = 0; if ( lastCleaned == numberIterations_) doOriginalTolerance = 1; // check optimal // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } //if (dualFeasible()||problemStatus_==-4||(primalFeasible()&&!numberDualInfeasibilitiesWithoutFree_)) { if (dualFeasible() || problemStatus_ == -4) { progress_.modifyObjective(objectiveValue_ - bestPossibleImprovement_); #ifdef COIN_DEVELOP if (sumDualInfeasibilities_ || bestPossibleImprovement_) printf("improve %g dualinf %g -> %g\n", bestPossibleImprovement_, sumDualInfeasibilities_, sumDualInfeasibilities_ * dualBound_); #endif // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); #if 0 if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit) && !numberAtFakeBound()) { //looks infeasible on objective if (perturbation_ == 101) { cleanDuals = 1; // Save costs int numberTotal = numberRows_ + numberColumns_; double * saveCost = CoinCopyOfArray(cost_, numberTotal); // make sure fake bounds are back changeBounds(1, NULL, changeCost); createRim4(false); // make sure duals are current computeDuals(givenDuals); checkDualSolution(); if(objectiveValue()*optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit) && !numberDualInfeasibilities_) { perturbation_ = 102; // stop any perturbations printf("cutoff test succeeded\n"); } else { printf("cutoff test failed\n"); // put back memcpy(cost_, saveCost, numberTotal * sizeof(double)); // make sure duals are current computeDuals(givenDuals); checkDualSolution(); progress_.modifyObjective(-COIN_DBL_MAX); problemStatus_ = -1; } delete [] saveCost; } } #endif if (primalFeasible() && !givenDuals) { // may be optimal - or may be bounds are wrong handler_->message(CLP_DUAL_BOUNDS, messages_) << dualBound_ << CoinMessageEol; // save solution in case unbounded double * saveColumnSolution = NULL; double * saveRowSolution = NULL; bool inCbc = (specialOptions_ & (0x01000000 | 16384)) != 0; if (!inCbc) { saveColumnSolution = CoinCopyOfArray(columnActivityWork_, numberColumns_); saveRowSolution = CoinCopyOfArray(rowActivityWork_, numberRows_); } numberChangedBounds = changeBounds(0, rowArray_[3], changeCost); if (numberChangedBounds <= 0 && !numberDualInfeasibilities_) { //looks optimal - do we need to reset tolerance if (perturbation_ == 101) { perturbation_ = 102; // stop any perturbations cleanDuals = 1; // make sure fake bounds are back //computeObjectiveValue(); changeBounds(1, NULL, changeCost); //computeObjectiveValue(); createRim4(false); // make sure duals are current computeDuals(givenDuals); checkDualSolution(); progress_.modifyObjective(-COIN_DBL_MAX); #define DUAL_TRY_FASTER #ifdef DUAL_TRY_FASTER if (numberDualInfeasibilities_) { #endif numberChanged_ = 1; // force something to happen lastCleaned = numberIterations_ - 1; #ifdef DUAL_TRY_FASTER } else { //double value = objectiveValue_; computeObjectiveValue(true); //printf("old %g new %g\n",value,objectiveValue_); //numberChanged_=1; } #endif } if (lastCleaned < numberIterations_ && numberTimesOptimal_ < 4 && (numberChanged_ || (specialOptions_ & 4096) == 0)) { #if CLP_CAN_HAVE_ZERO_OBJ if ((specialOptions_&2097152)==0) { #endif doOriginalTolerance = 2; numberTimesOptimal_++; changeMade_++; // say something changed if (numberTimesOptimal_ == 1) { dualTolerance_ = dblParam_[ClpDualTolerance]; } else { if (numberTimesOptimal_ == 2) { // better to have small tolerance even if slower factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15)); } dualTolerance_ = dblParam_[ClpDualTolerance]; dualTolerance_ *= pow(2.0, numberTimesOptimal_ - 1); } cleanDuals = 2; // If nothing changed optimal else primal #if CLP_CAN_HAVE_ZERO_OBJ } else { // no cost - skip checks problemStatus_=0; } #endif } else { problemStatus_ = 0; // optimal if (lastCleaned < numberIterations_ && numberChanged_) { handler_->message(CLP_SIMPLEX_GIVINGUP, messages_) << CoinMessageEol; } } } else { cleanDuals = 1; if (doOriginalTolerance == 1) { // check unbounded // find a variable with bad dj int iSequence; int iChosen = -1; if (!inCbc) { double largest = 100.0 * primalTolerance_; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { double djValue = dj_[iSequence]; double originalLo = originalLower(iSequence); double originalUp = originalUpper(iSequence); if (fabs(djValue) > fabs(largest)) { if (getStatus(iSequence) != basic) { if (djValue > 0 && originalLo < -1.0e20) { if (djValue > fabs(largest)) { largest = djValue; iChosen = iSequence; } } else if (djValue < 0 && originalUp > 1.0e20) { if (-djValue > fabs(largest)) { largest = djValue; iChosen = iSequence; } } } } } } if (iChosen >= 0) { int iSave = sequenceIn_; sequenceIn_ = iChosen; unpack(rowArray_[1]); sequenceIn_ = iSave; // if dual infeasibilities then must be free vector so add in dual if (numberDualInfeasibilities_) { if (fabs(changeCost) > 1.0e-5) COIN_DETAIL_PRINT(printf("Odd free/unbounded combo\n")); changeCost += cost_[iChosen]; } problemStatus_ = checkUnbounded(rowArray_[1], rowArray_[0], changeCost); rowArray_[1]->clear(); } else { problemStatus_ = -3; } if (problemStatus_ == 2 && perturbation_ == 101) { perturbation_ = 102; // stop any perturbations cleanDuals = 1; createRim4(false); progress_.modifyObjective(-COIN_DBL_MAX); problemStatus_ = -1; } if (problemStatus_ == 2) { // it is unbounded - restore solution // but first add in changes to non-basic int iColumn; double * original = columnArray_[0]->denseVector(); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if(getColumnStatus(iColumn) != basic) ray_[iColumn] += saveColumnSolution[iColumn] - original[iColumn]; columnActivityWork_[iColumn] = original[iColumn]; } CoinMemcpyN(saveRowSolution, numberRows_, rowActivityWork_); } } else { doOriginalTolerance = 2; rowArray_[0]->clear(); } } delete [] saveColumnSolution; delete [] saveRowSolution; } if (problemStatus_ == -4 || problemStatus_ == -5) { // may be infeasible - or may be bounds are wrong numberChangedBounds = changeBounds(0, NULL, changeCost); needCleanFake = true; /* Should this be here as makes no difference to being feasible. But seems to make a difference to run times. */ if (perturbation_ == 101 && 0) { perturbation_ = 102; // stop any perturbations cleanDuals = 1; numberChangedBounds = 1; // make sure fake bounds are back changeBounds(1, NULL, changeCost); needCleanFake = true; createRim4(false); progress_.modifyObjective(-COIN_DBL_MAX); } if ((numberChangedBounds <= 0 || dualBound_ > 1.0e20 || (largestPrimalError_ > 1.0 && dualBound_ > 1.0e17)) && (numberPivots < 4 || sumPrimalInfeasibilities_ > 1.0e-6)) { problemStatus_ = 1; // infeasible if (perturbation_ == 101) { perturbation_ = 102; // stop any perturbations //cleanDuals=1; //numberChangedBounds=1; //createRim4(false); } } else { problemStatus_ = -1; //iterate cleanDuals = 1; if (numberChangedBounds <= 0) doOriginalTolerance = 2; // and delete ray which has been created delete [] ray_; ray_ = NULL; } } } else { cleanDuals = 1; } if (problemStatus_ < 0) { if (doOriginalTolerance == 2) { // put back original tolerance lastCleaned = numberIterations_; numberChanged_ = 0; // Number of variables with changed costs handler_->message(CLP_DUAL_ORIGINAL, messages_) << CoinMessageEol; perturbation_ = 102; // stop any perturbations #if 0 double * xcost = new double[numberRows_+numberColumns_]; double * xlower = new double[numberRows_+numberColumns_]; double * xupper = new double[numberRows_+numberColumns_]; double * xdj = new double[numberRows_+numberColumns_]; double * xsolution = new double[numberRows_+numberColumns_]; CoinMemcpyN(cost_, (numberRows_ + numberColumns_), xcost); CoinMemcpyN(lower_, (numberRows_ + numberColumns_), xlower); CoinMemcpyN(upper_, (numberRows_ + numberColumns_), xupper); CoinMemcpyN(dj_, (numberRows_ + numberColumns_), xdj); CoinMemcpyN(solution_, (numberRows_ + numberColumns_), xsolution); #endif createRim4(false); progress_.modifyObjective(-COIN_DBL_MAX); // make sure duals are current computeDuals(givenDuals); checkDualSolution(); #if 0 int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (cost_[i] != xcost[i]) printf("** %d old cost %g new %g sol %g\n", i, xcost[i], cost_[i], solution_[i]); if (lower_[i] != xlower[i]) printf("** %d old lower %g new %g sol %g\n", i, xlower[i], lower_[i], solution_[i]); if (upper_[i] != xupper[i]) printf("** %d old upper %g new %g sol %g\n", i, xupper[i], upper_[i], solution_[i]); if (dj_[i] != xdj[i]) printf("** %d old dj %g new %g sol %g\n", i, xdj[i], dj_[i], solution_[i]); if (solution_[i] != xsolution[i]) printf("** %d old solution %g new %g sol %g\n", i, xsolution[i], solution_[i], solution_[i]); } //delete [] xcost; //delete [] xupper; //delete [] xlower; //delete [] xdj; //delete [] xsolution; #endif // put back bounds as they were if was optimal if (doOriginalTolerance == 2 && cleanDuals != 2) { changeMade_++; // say something changed /* We may have already changed some bounds in this function so save numberFake_ and add in. Worst that can happen is that we waste a bit of time - but it must be finite. */ //int saveNumberFake = numberFake_; //resetFakeBounds(-1); changeBounds(3, NULL, changeCost); needCleanFake = true; //numberFake_ += saveNumberFake; //resetFakeBounds(-1); cleanDuals = 2; //cleanDuals=1; } #if 0 //int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (cost_[i] != xcost[i]) printf("** %d old cost %g new %g sol %g\n", i, xcost[i], cost_[i], solution_[i]); if (lower_[i] != xlower[i]) printf("** %d old lower %g new %g sol %g\n", i, xlower[i], lower_[i], solution_[i]); if (upper_[i] != xupper[i]) printf("** %d old upper %g new %g sol %g\n", i, xupper[i], upper_[i], solution_[i]); if (dj_[i] != xdj[i]) printf("** %d old dj %g new %g sol %g\n", i, xdj[i], dj_[i], solution_[i]); if (solution_[i] != xsolution[i]) printf("** %d old solution %g new %g sol %g\n", i, xsolution[i], solution_[i], solution_[i]); } delete [] xcost; delete [] xupper; delete [] xlower; delete [] xdj; delete [] xsolution; #endif } if (cleanDuals == 1 || (cleanDuals == 2 && !numberDualInfeasibilities_)) { // make sure dual feasible // look at all rows and columns rowArray_[0]->clear(); columnArray_[0]->clear(); double objectiveChange = 0.0; double savePrimalInfeasibilities = sumPrimalInfeasibilities_; if (!numberIterations_) { int nTotal = numberRows_ + numberColumns_; if (arraysNotCreated) { // create save arrays delete [] saveStatus_; delete [] savedSolution_; saveStatus_ = new unsigned char [nTotal]; savedSolution_ = new double [nTotal]; arraysNotCreated = false; } // save arrays CoinMemcpyN(status_, nTotal, saveStatus_); CoinMemcpyN(rowActivityWork_, numberRows_, savedSolution_ + numberColumns_); CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_); } #if 0 double * xcost = new double[numberRows_+numberColumns_]; double * xlower = new double[numberRows_+numberColumns_]; double * xupper = new double[numberRows_+numberColumns_]; double * xdj = new double[numberRows_+numberColumns_]; double * xsolution = new double[numberRows_+numberColumns_]; CoinMemcpyN(cost_, (numberRows_ + numberColumns_), xcost); CoinMemcpyN(lower_, (numberRows_ + numberColumns_), xlower); CoinMemcpyN(upper_, (numberRows_ + numberColumns_), xupper); CoinMemcpyN(dj_, (numberRows_ + numberColumns_), xdj); CoinMemcpyN(solution_, (numberRows_ + numberColumns_), xsolution); #endif if (givenDuals) dualTolerance_ = 1.0e50; #if CLP_CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)==0) { #endif updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1], 0.0, objectiveChange, true); #if CLP_CAN_HAVE_ZERO_OBJ>1 } else { rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); } #endif dualTolerance_ = saveTolerance; #if 0 int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (cost_[i] != xcost[i]) printf("** %d old cost %g new %g sol %g\n", i, xcost[i], cost_[i], solution_[i]); if (lower_[i] != xlower[i]) printf("** %d old lower %g new %g sol %g\n", i, xlower[i], lower_[i], solution_[i]); if (upper_[i] != xupper[i]) printf("** %d old upper %g new %g sol %g\n", i, xupper[i], upper_[i], solution_[i]); if (dj_[i] != xdj[i]) printf("** %d old dj %g new %g sol %g\n", i, xdj[i], dj_[i], solution_[i]); if (solution_[i] != xsolution[i]) printf("** %d old solution %g new %g sol %g\n", i, xsolution[i], solution_[i], solution_[i]); } delete [] xcost; delete [] xupper; delete [] xlower; delete [] xdj; delete [] xsolution; #endif // for now - recompute all gutsOfSolution(NULL, NULL); if (givenDuals) dualTolerance_ = 1.0e50; #if CLP_CAN_HAVE_ZERO_OBJ>1 if ((specialOptions_&2097152)==0) { #endif updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1], 0.0, objectiveChange, true); #if CLP_CAN_HAVE_ZERO_OBJ>1 } else { rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); } #endif dualTolerance_ = saveTolerance; if (!numberIterations_ && sumPrimalInfeasibilities_ > 1.0e5*(savePrimalInfeasibilities+1.0e3) && (moreSpecialOptions_ & (256|8192)) == 0) { // Use primal int nTotal = numberRows_ + numberColumns_; CoinMemcpyN(saveStatus_, nTotal, status_); CoinMemcpyN(savedSolution_ + numberColumns_ , numberRows_, rowActivityWork_); CoinMemcpyN(savedSolution_ , numberColumns_, columnActivityWork_); problemStatus_ = 10; situationChanged = 0; } //assert(numberDualInfeasibilitiesWithoutFree_==0); if (numberDualInfeasibilities_) { if ((numberPrimalInfeasibilities_ || numberPivots) && problemStatus_!=10) { problemStatus_ = -1; // carry on as normal } else { problemStatus_ = 10; // try primal #if COIN_DEVELOP>1 printf("returning at %d\n", __LINE__); #endif } } else if (situationChanged == 2) { problemStatus_ = -1; // carry on as normal // need to reset bounds changeBounds(3, NULL, changeCost); } situationChanged = 0; } else { // iterate if (cleanDuals != 2) { problemStatus_ = -1; } else { problemStatus_ = 10; // try primal #if COIN_DEVELOP>2 printf("returning at %d\n", __LINE__); #endif } } } } // unflag all variables (we may want to wait a bit?) if ((tentativeStatus != -2 && tentativeStatus != -1) && unflagVariables) { int iRow; int numberFlagged = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (flagged(iPivot)) { numberFlagged++; clearFlagged(iPivot); } } #ifdef COIN_DEVELOP if (numberFlagged) { printf("unflagging %d variables - tentativeStatus %d probStat %d ninf %d nopt %d\n", numberFlagged, tentativeStatus, problemStatus_, numberPrimalInfeasibilities_, numberTimesOptimal_); } #endif unflagVariables = numberFlagged > 0; if (numberFlagged && !numberPivots) { /* looks like trouble as we have not done any iterations. Try changing pivot tolerance then give it a few goes and give up */ if (factorization_->pivotTolerance() < 0.9) { factorization_->pivotTolerance(0.99); problemStatus_ = -1; } else if (numberTimesOptimal_ < 3) { numberTimesOptimal_++; problemStatus_ = -1; } else { unflagVariables = false; //secondaryStatus_ = 1; // and say probably infeasible if ((moreSpecialOptions_ & 256) == 0) { // try primal problemStatus_ = 10; } else { // almost certainly infeasible problemStatus_ = 1; } #if COIN_DEVELOP>1 printf("returning at %d\n", __LINE__); #endif } } } if (problemStatus_ < 0) { if (needCleanFake) { double dummyChangeCost = 0.0; changeBounds(3, NULL, dummyChangeCost); } #if 0 if (objectiveValue_ < lastObjectiveValue_ - 1.0e-8 * CoinMax(fabs(objectivevalue_), fabs(lastObjectiveValue_))) { } else { lastObjectiveValue_ = objectiveValue_; } #endif if (type == 0 || type == 1) { if (!type && arraysNotCreated) { // create save arrays delete [] saveStatus_; delete [] savedSolution_; saveStatus_ = new unsigned char [numberRows_+numberColumns_]; savedSolution_ = new double [numberRows_+numberColumns_]; } // save arrays CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus_); CoinMemcpyN(rowActivityWork_, numberRows_, savedSolution_ + numberColumns_); CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_); // save extra stuff int dummy; matrix_->generalExpanded(this, 5, dummy); } if (weightsSaved) { // restore weights (if saved) - also recompute infeasibility list if (!reallyBadProblems && (largestPrimalError_ < 100.0 || numberPivots > 10)) { if (tentativeStatus > -3) dualRowPivot_->saveWeights(this, (type < 2) ? 2 : 4); else dualRowPivot_->saveWeights(this, 3); } else { // reset weights or scale back dualRowPivot_->saveWeights(this, 6); } } else if (weightsSaved2 && numberPrimalInfeasibilities_) { dualRowPivot_->saveWeights(this, 3); } } // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); #if 0 if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ > limit + 100.0) { printf("lim %g obj %g %g - wo perturb %g sum dual %g\n", limit, objectiveValue_, objectiveValue(), computeInternalObjectiveValue(), sumDualInfeasibilities_); } #endif if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ > limit && !numberAtFakeBound()) { bool looksInfeasible = !numberDualInfeasibilities_; if (objectiveValue()*optimizationDirection_ > limit + fabs(0.1 * limit) + 1.0e2 * sumDualInfeasibilities_ + 1.0e4 && sumDualInfeasibilities_ < largestDualError_ && numberIterations_ > 0.5 * numberRows_ + 1000) looksInfeasible = true; if (looksInfeasible) { // Even if not perturbed internal costs may have changed // be careful if (true || numberIterations_) { if(computeInternalObjectiveValue() > limit) { problemStatus_ = 1; secondaryStatus_ = 1; // and say was on cutoff } } else { problemStatus_ = 1; secondaryStatus_ = 1; // and say was on cutoff } } } // If we are in trouble and in branch and bound give up if ((specialOptions_ & 1024) != 0) { int looksBad = 0; if (largestPrimalError_ * largestDualError_ > 1.0e2) { looksBad = 1; } else if (largestPrimalError_ > 1.0e-2 && objectiveValue_ > CoinMin(1.0e15, 1.0e3 * limit)) { looksBad = 2; } if (looksBad) { if (factorization_->pivotTolerance() < 0.9) { // up tolerance factorization_->pivotTolerance(CoinMin(factorization_->pivotTolerance() * 1.05 + 0.02, 0.91)); } else if (numberIterations_ > 10000) { if (handler_->logLevel() > 2) printf("bad dual - saying infeasible %d\n", looksBad); problemStatus_ = 1; secondaryStatus_ = 1; // and say was on cutoff } else if (largestPrimalError_ > 1.0e5) { { //int iBigB = -1; double bigB = 0.0; //int iBigN = -1; double bigN = 0.0; for (int i = 0; i < numberRows_ + numberColumns_; i++) { double value = fabs(solution_[i]); if (getStatus(i) == basic) { if (value > bigB) { bigB = value; //iBigB = i; } } else { if (value > bigN) { bigN = value; //iBigN = i; } } } #ifdef CLP_INVESTIGATE if (bigB > 1.0e8 || bigN > 1.0e8) { if (handler_->logLevel() > 0) printf("it %d - basic %d %g, nonbasic %d %g\n", numberIterations_, iBigB, bigB, iBigN, bigN); } #endif } #if COIN_DEVELOP!=2 if (handler_->logLevel() > 2) #endif printf("bad dual - going to primal %d %g\n", looksBad, largestPrimalError_); allSlackBasis(true); problemStatus_ = 10; } } } if (problemStatus_ < 0 && !changeMade_) { problemStatus_ = 4; // unknown } lastGoodIteration_ = numberIterations_; if (numberIterations_ > lastBadIteration_ + 100) moreSpecialOptions_ &= ~16; // clear check accuracy flag if (problemStatus_ < 0) { sumDualInfeasibilities_ = realDualInfeasibilities; // back to say be careful if (sumDualInfeasibilities_) numberDualInfeasibilities_ = 1; } #ifdef CLP_REPORT_PROGRESS if (ixxxxxx > ixxyyyy - 3) { printf("objectiveValue_ %g\n", objectiveValue_); handler_->setLogLevel(63); int nTotal = numberColumns_ + numberRows_; double newObj = 0.0; for (int i = 0; i < nTotal; i++) { if (solution_[i]) newObj += solution_[i] * cost_[i]; } printf("xxx obj %g\n", newObj); // for now - recompute all gutsOfSolution(NULL, NULL); newObj = 0.0; for (int i = 0; i < nTotal; i++) { if (solution_[i]) newObj += solution_[i] * cost_[i]; } printf("yyy obj %g %g\n", newObj, objectiveValue_); progress_.modifyObjective(objectiveValue_ - bestPossibleImprovement_); } #endif #if 1 double thisObj = progress_.lastObjective(0); double lastObj = progress_.lastObjective(1); if (lastObj > thisObj + 1.0e-4 * CoinMax(fabs(thisObj), fabs(lastObj)) + 1.0e-4 && givenDuals == NULL && firstFree_ < 0) { int maxFactor = factorization_->maximumPivots(); if (maxFactor > 10) { if (forceFactorization_ < 0) forceFactorization_ = maxFactor; forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1)); //printf("Reducing factorization frequency\n"); } } #endif // Allow matrices to be sorted etc int fake = -999; // signal sort matrix_->correctSequence(this, fake, fake); if (alphaAccuracy_ > 0.0) alphaAccuracy_ = 1.0; // If we are stopping - use plausible objective // Maybe only in fast dual if (problemStatus_ > 2) objectiveValue_ = approximateObjective; if (problemStatus_ == 1 && (progressFlag_&8) != 0 && fabs(objectiveValue_) > 1.0e10 ) problemStatus_ = 10; // infeasible - but has looked feasible } /* While updateDualsInDual sees what effect is of flip this does actual flipping. If change >0.0 then value in array >0.0 => from lower to upper */ void ClpSimplexDual::flipBounds(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray) { int number; int * which; int iSection; for (iSection = 0; iSection < 2; iSection++) { int i; double * solution = solutionRegion(iSection); double * lower = lowerRegion(iSection); double * upper = upperRegion(iSection); int addSequence; if (!iSection) { number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } for (i = 0; i < number; i++) { int iSequence = which[i]; Status status = getStatus(iSequence + addSequence); switch(status) { case basic: case isFree: case superBasic: case ClpSimplex::isFixed: break; case atUpperBound: // to lower bound setStatus(iSequence + addSequence, atLowerBound); solution[iSequence] = lower[iSequence]; break; case atLowerBound: // to upper bound setStatus(iSequence + addSequence, atUpperBound); solution[iSequence] = upper[iSequence]; break; } } } rowArray->setNumElements(0); columnArray->setNumElements(0); } // Restores bound to original bound void ClpSimplexDual::originalBound( int iSequence) { if (getFakeBound(iSequence) != noFake) { numberFake_--;; setFakeBound(iSequence, noFake); if (iSequence >= numberColumns_) { // rows int iRow = iSequence - numberColumns_; rowLowerWork_[iRow] = rowLower_[iRow]; rowUpperWork_[iRow] = rowUpper_[iRow]; if (rowScale_) { if (rowLowerWork_[iRow] > -1.0e50) rowLowerWork_[iRow] *= rowScale_[iRow] * rhsScale_; if (rowUpperWork_[iRow] < 1.0e50) rowUpperWork_[iRow] *= rowScale_[iRow] * rhsScale_; } else if (rhsScale_ != 1.0) { if (rowLowerWork_[iRow] > -1.0e50) rowLowerWork_[iRow] *= rhsScale_; if (rowUpperWork_[iRow] < 1.0e50) rowUpperWork_[iRow] *= rhsScale_; } } else { // columns columnLowerWork_[iSequence] = columnLower_[iSequence]; columnUpperWork_[iSequence] = columnUpper_[iSequence]; if (rowScale_) { double multiplier = 1.0 * inverseColumnScale_[iSequence]; if (columnLowerWork_[iSequence] > -1.0e50) columnLowerWork_[iSequence] *= multiplier * rhsScale_; if (columnUpperWork_[iSequence] < 1.0e50) columnUpperWork_[iSequence] *= multiplier * rhsScale_; } else if (rhsScale_ != 1.0) { if (columnLowerWork_[iSequence] > -1.0e50) columnLowerWork_[iSequence] *= rhsScale_; if (columnUpperWork_[iSequence] < 1.0e50) columnUpperWork_[iSequence] *= rhsScale_; } } } } /* As changeBounds but just changes new bounds for a single variable. Returns true if change */ bool ClpSimplexDual::changeBound( int iSequence) { // old values double oldLower = lower_[iSequence]; double oldUpper = upper_[iSequence]; double value = solution_[iSequence]; bool modified = false; originalBound(iSequence); // original values double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; // back to altered values lower_[iSequence] = oldLower; upper_[iSequence] = oldUpper; assert (getFakeBound(iSequence) == noFake); //if (getFakeBound(iSequence)!=noFake) //numberFake_--;; if (value == oldLower) { if (upperValue > oldLower + dualBound_) { upper_[iSequence] = oldLower + dualBound_; setFakeBound(iSequence, upperFake); modified = true; numberFake_++; } } else if (value == oldUpper) { if (lowerValue < oldUpper - dualBound_) { lower_[iSequence] = oldUpper - dualBound_; setFakeBound(iSequence, lowerFake); modified = true; numberFake_++; } } else { assert(value == oldLower || value == oldUpper); } return modified; } #if ABC_NORMAL_DEBUG>0 //#define PERT_STATISTICS #endif #ifdef PERT_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; } #endif // Perturbs problem int ClpSimplexDual::perturb() { if (perturbation_ > 100) return 0; //perturbed already if (perturbation_ == 100) perturbation_ = 50; // treat as normal int savePerturbation = perturbation_; bool modifyRowCosts = false; // dual perturbation double perturbation = 1.0e-20; // maximum fraction of cost to perturb double maximumFraction = 1.0e-5; double constantPerturbation = 100.0 * dualTolerance_; int maxLength = 0; int minLength = numberRows_; double averageCost = 0.0; #if 0 // look at element range double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive); largestPositive = CoinMax(fabs(largestNegative), largestPositive); double elementRatio = largestPositive / smallestPositive; #endif int numberNonZero = 0; if (!numberIterations_ && perturbation_ >= 50) { // See if we need to perturb double * sort = new double[numberColumns_]; // Use objective BEFORE scaling const double * obj = ((moreSpecialOptions_ & 128) == 0) ? objective() : cost_; int i; for (i = 0; i < numberColumns_; i++) { double value = fabs(obj[i]); sort[i] = value; averageCost += value; if (value) numberNonZero++; } if (numberNonZero) averageCost /= static_cast (numberNonZero); else averageCost = 1.0; std::sort(sort, sort + numberColumns_); int number = 1; double last = sort[0]; for (i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } delete [] sort; if (!numberNonZero && perturbation_ < 55) return 1; // safer to use primal #if 0 printf("nnz %d percent %d", number, (number * 100) / numberColumns_); if (number * 4 > numberColumns_) printf(" - Would not perturb\n"); else printf(" - Would perturb\n"); //exit(0); #endif //printf("ratio number diff costs %g, element ratio %g\n",((double)number)/((double) numberColumns_), // elementRatio); //number=0; //if (number*4>numberColumns_||elementRatio>1.0e12) { if (number * 4 > numberColumns_) { perturbation_ = 100; return 0; // good enough } } int iColumn; const int * columnLength = matrix_->getVectorLengths(); for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLowerWork_[iColumn] < columnUpperWork_[iColumn]) { int length = columnLength[iColumn]; if (length > 2) { maxLength = CoinMax(maxLength, length); minLength = CoinMin(minLength, length); } } } // If > 70 then do rows if (perturbation_ >= 70) { modifyRowCosts = true; perturbation_ -= 20; printf("Row costs modified, "); } bool uniformChange = false; bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0; if (perturbation_ > 50) { // Experiment // maximumFraction could be 1.0e-10 to 1.0 double m[] = {1.0e-10, 1.0e-9, 1.0e-8, 1.0e-7, 1.0e-6, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0}; int whichOne = perturbation_ - 51; //if (inCbcOrOther&&whichOne>0) //whichOne--; maximumFraction = m[CoinMin(whichOne, 10)]; } else if (inCbcOrOther) { //maximumFraction = 1.0e-6; } int iRow; double smallestNonZero = 1.0e100; numberNonZero = 0; if (perturbation_ >= 50) { perturbation = 1.0e-8; if (perturbation_ > 50 && perturbation_ < 60) perturbation = CoinMax(1.0e-8,maximumFraction); bool allSame = true; double lastValue = 0.0; for (iRow = 0; iRow < numberRows_; iRow++) { double lo = rowLowerWork_[iRow]; double up = rowUpperWork_[iRow]; if (lo < up) { double value = fabs(rowObjectiveWork_[iRow]); perturbation = CoinMax(perturbation, value); if (value) { modifyRowCosts = true; smallestNonZero = CoinMin(smallestNonZero, value); } } if (lo && lo > -1.0e10) { numberNonZero++; lo = fabs(lo); if (!lastValue) lastValue = lo; else if (fabs(lo - lastValue) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { numberNonZero++; up = fabs(up); if (!lastValue) lastValue = up; else if (fabs(up - lastValue) > 1.0e-7) allSame = false; } } double lastValue2 = 0.0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double lo = columnLowerWork_[iColumn]; double up = columnUpperWork_[iColumn]; if (lo < up) { double value = fabs(objectiveWork_[iColumn]); perturbation = CoinMax(perturbation, value); if (value) { smallestNonZero = CoinMin(smallestNonZero, value); } } if (lo && lo > -1.0e10) { //numberNonZero++; lo = fabs(lo); if (!lastValue2) lastValue2 = lo; else if (fabs(lo - lastValue2) > 1.0e-7) allSame = false; } if (up && up < 1.0e10) { //numberNonZero++; up = fabs(up); if (!lastValue2) lastValue2 = up; else if (fabs(up - lastValue2) > 1.0e-7) allSame = false; } } if (allSame) { // Check elements double smallestNegative; double largestNegative; double smallestPositive; double largestPositive; matrix_->rangeOfElements(smallestNegative, largestNegative, smallestPositive, largestPositive); if (smallestNegative == largestNegative && smallestPositive == largestPositive) { // Really hit perturbation double adjust = CoinMin(100.0 * maximumFraction, 1.0e-3 * CoinMax(lastValue, lastValue2)); maximumFraction = CoinMax(adjust, maximumFraction); } } perturbation = CoinMin(perturbation, smallestNonZero / maximumFraction); } else { // user is in charge maximumFraction = 1.0e-1; // but some experiments if (perturbation_ <= -900) { modifyRowCosts = true; perturbation_ += 1000; printf("Row costs modified, "); } if (perturbation_ <= -10) { perturbation_ += 10; maximumFraction = 1.0; if ((-perturbation_) % 100 >= 10) { uniformChange = true; perturbation_ += 20; } while (perturbation_ < -10) { perturbation_ += 100; maximumFraction *= 1.0e-1; } } perturbation = pow(10.0, perturbation_); } double largestZero = 0.0; double largest = 0.0; double largestPerCent = 0.0; // modify costs bool printOut = (handler_->logLevel() == 63); printOut = false; //assert (!modifyRowCosts); modifyRowCosts = false; if (modifyRowCosts) { for (iRow = 0; iRow < numberRows_; iRow++) { if (rowLowerWork_[iRow] < rowUpperWork_[iRow]) { double value = perturbation; double currentValue = rowObjectiveWork_[iRow]; value = CoinMin(value, maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-3)); if (rowLowerWork_[iRow] > -largeValue_) { if (fabs(rowLowerWork_[iRow]) < fabs(rowUpperWork_[iRow])) value *= randomNumberGenerator_.randomDouble(); else value *= -randomNumberGenerator_.randomDouble(); } else if (rowUpperWork_[iRow] < largeValue_) { value *= -randomNumberGenerator_.randomDouble(); } else { value = 0.0; } if (currentValue) { largest = CoinMax(largest, fabs(value)); if (fabs(value) > fabs(currentValue)*largestPerCent) largestPerCent = fabs(value / currentValue); } else { largestZero = CoinMax(largestZero, fabs(value)); } if (printOut) printf("row %d cost %g change %g\n", iRow, rowObjectiveWork_[iRow], value); rowObjectiveWork_[iRow] += value; } } } // more its but faster double weight[]={1.0e-4,1.0e-2,1.0e-1,1.0,2.0,10.0,100.0,200.0,400.0,600.0,1000.0}; // good its double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,2.0,5.0,10.0,20.0,30.0,40.0,100.0}; double weight[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 40.0, 100.0}; //double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,20.0,50.0,100.0,120.0,130.0,140.0,200.0}; //double extraWeight = 10.0; // Scale back if wanted double weight2[] = {1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; if (constantPerturbation < 99.0 * dualTolerance_) { perturbation *= 0.1; //extraWeight = 0.5; memcpy(weight, weight2, sizeof(weight2)); } // adjust weights if all columns long double factor = 1.0; if (maxLength) { factor = 3.0 / static_cast (minLength); } // Make variables with more elements more expensive const double m1 = 0.5; double smallestAllowed = CoinMin(1.0e-2 * dualTolerance_, maximumFraction); double largestAllowed = CoinMax(1.0e3 * dualTolerance_, maximumFraction * averageCost); // smaller if in BAB //if (inCbcOrOther) //largestAllowed=CoinMin(largestAllowed,1.0e-5); //smallestAllowed = CoinMin(smallestAllowed,0.1*largestAllowed); #define SAVE_PERT #ifdef SAVE_PERT if (2 * numberColumns_ > maximumPerturbationSize_) { delete [] perturbationArray_; maximumPerturbationSize_ = 2 * numberColumns_; perturbationArray_ = new double [maximumPerturbationSize_]; for (iColumn = 0; iColumn < maximumPerturbationSize_; iColumn++) { perturbationArray_[iColumn] = randomNumberGenerator_.randomDouble(); } } #endif for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnLowerWork_[iColumn] < columnUpperWork_[iColumn] && getStatus(iColumn) != basic) { double value = perturbation; double currentValue = objectiveWork_[iColumn]; value = CoinMin(value, constantPerturbation + maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-8)); //value = CoinMin(value,constantPerturbation;+maximumFraction*fabs(currentValue)); double value2 = constantPerturbation + 1.0e-1 * smallestNonZero; if (uniformChange) { value = maximumFraction; value2 = maximumFraction; } if (columnLowerWork_[iColumn] > -largeValue_) { if (fabs(columnLowerWork_[iColumn]) < fabs(columnUpperWork_[iColumn])) { #ifndef SAVE_PERT value *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); value2 *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); #else value *= (1.0 - m1 + m1 * perturbationArray_[2*iColumn]); value2 *= (1.0 - m1 + m1 * perturbationArray_[2*iColumn+1]); #endif } else { //value *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); //value2 *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble()); value = 0.0; } } else if (columnUpperWork_[iColumn] < largeValue_) { #ifndef SAVE_PERT value *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); value2 *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble()); #else value *= -(1.0 - m1 + m1 * perturbationArray_[2*iColumn]); value2 *= -(1.0 - m1 + m1 * perturbationArray_[2*iColumn+1]); #endif } else { value = 0.0; } if (value) { int length = columnLength[iColumn]; if (length > 3) { length = static_cast (static_cast (length) * factor); length = CoinMax(3, length); } double multiplier; #if 1 if (length < 10) multiplier = weight[length]; else multiplier = weight[10]; #else if (length < 10) multiplier = weight[length]; else multiplier = weight[10] + extraWeight * (length - 10); multiplier *= 0.5; #endif value *= multiplier; value = CoinMin(value, value2); if (savePerturbation < 50 || savePerturbation > 60) { if (fabs(value) <= dualTolerance_) value = 0.0; } else if (value) { // get in range if (fabs(value) <= smallestAllowed) { value *= 10.0; while (fabs(value) <= smallestAllowed) value *= 10.0; } else if (fabs(value) > largestAllowed) { value *= 0.1; while (fabs(value) > largestAllowed) value *= 0.1; } } if (currentValue) { largest = CoinMax(largest, fabs(value)); if (fabs(value) > fabs(currentValue)*largestPerCent) largestPerCent = fabs(value / currentValue); } else { largestZero = CoinMax(largestZero, fabs(value)); } // but negative if at ub if (getStatus(iColumn) == atUpperBound) value = -value; if (printOut) printf("col %d cost %g change %g\n", iColumn, objectiveWork_[iColumn], value); objectiveWork_[iColumn] += value; } } } handler_->message(CLP_SIMPLEX_PERTURB, messages_) << 100.0 * maximumFraction << perturbation << largest << 100.0 * largestPerCent << largestZero << CoinMessageEol; // and zero changes //int nTotal = numberRows_+numberColumns_; //CoinZeroN(cost_+nTotal,nTotal); // say perturbed #ifdef PERT_STATISTICS { double averageCost = 0.0; int numberNonZero = 0; double * COIN_RESTRICT sort = new double[numberColumns_]; for (int i = 0; i < numberColumns_; i++) { double value = fabs(cost_[i]); sort[i] = value; averageCost += value; if (value) numberNonZero++; } if (numberNonZero) averageCost /= static_cast (numberNonZero); else averageCost = 1.0; std::sort(sort, sort + numberColumns_); int number = 1; double last = sort[0]; for (int i = 1; i < numberColumns_; i++) { if (last != sort[i]) number++; last = sort[i]; } printf("nnz %d percent %d", number, (number * 100) / numberColumns_); delete [] sort; breakdown("Objective", numberColumns_+numberRows_, cost_); } #endif perturbation_ = 101; return 0; } /* For strong branching. On input lower and upper are new bounds while on output they are change in objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) Returns -2 if bad factorization */ int ClpSimplexDual::strongBranching(int numberVariables, const int * variables, double * newLower, double * newUpper, double ** outputSolution, int * outputStatus, int * outputIterations, bool stopOnFirstInfeasible, bool alwaysFinish, int startFinishOptions) { int i; int returnCode = 0; double saveObjectiveValue = objectiveValue_; algorithm_ = -1; //scaling(false); // put in standard form (and make row copy) // create modifiable copies of model rim and do optional scaling createRim(7 + 8 + 16 + 32, true, startFinishOptions); // change newLower and newUpper if scaled // Do initial factorization // and set certain stuff // We can either set increasing rows so ...IsBasic gives pivot row // or we can just increment iBasic one by one // for now let ...iBasic give pivot row int useFactorization = false; if ((startFinishOptions & 2) != 0 && (whatsChanged_&(2 + 512)) == 2 + 512) useFactorization = true; // Keep factorization if possible // switch off factorization if bad if (pivotVariable_[0] < 0) useFactorization = false; if (!useFactorization || factorization_->numberRows() != numberRows_) { useFactorization = false; factorization_->setDefaultValues(); int factorizationStatus = internalFactorize(0); if (factorizationStatus < 0) { // some error // we should either debug or ignore #ifndef NDEBUG printf("***** ClpDual strong branching factorization error - debug\n"); #endif return -2; } else if (factorizationStatus && factorizationStatus <= numberRows_) { handler_->message(CLP_SINGULARITIES, messages_) << factorizationStatus << CoinMessageEol; } } // save stuff ClpFactorization saveFactorization(*factorization_); // Get fake bounds correctly double changeCost; changeBounds(3, NULL, changeCost); int saveNumberFake = numberFake_; // save basis and solution double * saveSolution = new double[numberRows_+numberColumns_]; CoinMemcpyN(solution_, numberRows_ + numberColumns_, saveSolution); unsigned char * saveStatus = new unsigned char [numberRows_+numberColumns_]; CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus); // save bounds as createRim makes clean copies double * saveLower = new double[numberRows_+numberColumns_]; CoinMemcpyN(lower_, numberRows_ + numberColumns_, saveLower); double * saveUpper = new double[numberRows_+numberColumns_]; CoinMemcpyN(upper_, numberRows_ + numberColumns_, saveUpper); double * saveObjective = new double[numberRows_+numberColumns_]; CoinMemcpyN(cost_, numberRows_ + numberColumns_, saveObjective); int * savePivot = new int [numberRows_]; CoinMemcpyN(pivotVariable_, numberRows_, savePivot); // need to save/restore weights. int iSolution = 0; for (i = 0; i < numberVariables; i++) { int iColumn = variables[i]; double objectiveChange; double saveBound; // try down saveBound = columnUpper_[iColumn]; // external view - in case really getting optimal columnUpper_[iColumn] = newUpper[i]; assert (inverseColumnScale_ || scalingFlag_ <= 0); if (scalingFlag_ <= 0) upper_[iColumn] = newUpper[i] * rhsScale_; else upper_[iColumn] = (newUpper[i] * inverseColumnScale_[iColumn]) * rhsScale_; // scale // Start of fast iterations int status = fastDual(alwaysFinish); CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50); #ifdef CLP_DEBUG printf("first status %d obj %g\n",problemStatus_,objectiveValue_); #endif if(problemStatus_==10) problemStatus_=3; // make sure plausible double obj = CoinMax(objectiveValue_, saveObjectiveValue); if (status && problemStatus_ != 3) { // not finished - might be optimal checkPrimalSolution(rowActivityWork_, columnActivityWork_); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if (!numberPrimalInfeasibilities_ && obj < limit) { problemStatus_ = 0; } status = problemStatus_; } if (problemStatus_ == 3) status = 2; if (status || (problemStatus_ == 0 && !isDualObjectiveLimitReached())) { objectiveChange = obj - saveObjectiveValue; } else { objectiveChange = 1.0e100; status = 1; } if (scalingFlag_ <= 0) { CoinMemcpyN(solution_, numberColumns_, outputSolution[iSolution]); } else { int j; double * sol = outputSolution[iSolution]; for (j = 0; j < numberColumns_; j++) sol[j] = solution_[j] * columnScale_[j]; } outputStatus[iSolution] = status; outputIterations[iSolution] = numberIterations_; iSolution++; // restore numberFake_ = saveNumberFake; CoinMemcpyN(saveSolution, numberRows_ + numberColumns_, solution_); CoinMemcpyN(saveStatus, numberColumns_ + numberRows_, status_); CoinMemcpyN(saveLower, numberRows_ + numberColumns_, lower_); CoinMemcpyN(saveUpper, numberRows_ + numberColumns_, upper_); CoinMemcpyN(saveObjective, numberRows_ + numberColumns_, cost_); columnUpper_[iColumn] = saveBound; CoinMemcpyN(savePivot, numberRows_, pivotVariable_); //delete factorization_; //factorization_ = new ClpFactorization(saveFactorization,numberRows_); setFactorization(saveFactorization); newUpper[i] = objectiveChange; #ifdef CLP_DEBUG printf("down on %d costs %g\n", iColumn, objectiveChange); #endif // try up saveBound = columnLower_[iColumn]; // external view - in case really getting optimal columnLower_[iColumn] = newLower[i]; assert (inverseColumnScale_ || scalingFlag_ <= 0); if (scalingFlag_ <= 0) lower_[iColumn] = newLower[i] * rhsScale_; else lower_[iColumn] = (newLower[i] * inverseColumnScale_[iColumn]) * rhsScale_; // scale // Start of fast iterations status = fastDual(alwaysFinish); CoinAssert (problemStatus_||objectiveValue_<1.0e50); #ifdef CLP_DEBUG printf("second status %d obj %g\n",problemStatus_,objectiveValue_); #endif if(problemStatus_==10) problemStatus_=3; // make sure plausible obj = CoinMax(objectiveValue_, saveObjectiveValue); if (status && problemStatus_ != 3) { // not finished - might be optimal checkPrimalSolution(rowActivityWork_, columnActivityWork_); double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if (!numberPrimalInfeasibilities_ && obj < limit) { problemStatus_ = 0; } status = problemStatus_; } if (problemStatus_ == 3) status = 2; if (status || (problemStatus_ == 0 && !isDualObjectiveLimitReached())) { objectiveChange = obj - saveObjectiveValue; } else { objectiveChange = 1.0e100; status = 1; } if (scalingFlag_ <= 0) { CoinMemcpyN(solution_, numberColumns_, outputSolution[iSolution]); } else { int j; double * sol = outputSolution[iSolution]; for (j = 0; j < numberColumns_; j++) sol[j] = solution_[j] * columnScale_[j]; } outputStatus[iSolution] = status; outputIterations[iSolution] = numberIterations_; iSolution++; // restore numberFake_ = saveNumberFake; CoinMemcpyN(saveSolution, numberRows_ + numberColumns_, solution_); CoinMemcpyN(saveStatus, numberColumns_ + numberRows_, status_); CoinMemcpyN(saveLower, numberRows_ + numberColumns_, lower_); CoinMemcpyN(saveUpper, numberRows_ + numberColumns_, upper_); CoinMemcpyN(saveObjective, numberRows_ + numberColumns_, cost_); columnLower_[iColumn] = saveBound; CoinMemcpyN(savePivot, numberRows_, pivotVariable_); //delete factorization_; //factorization_ = new ClpFactorization(saveFactorization,numberRows_); setFactorization(saveFactorization); newLower[i] = objectiveChange; #ifdef CLP_DEBUG printf("up on %d costs %g\n", iColumn, objectiveChange); #endif /* Possibilities are: Both sides feasible - store Neither side feasible - set objective high and exit if desired One side feasible - change bounds and resolve */ if (newUpper[i] < 1.0e100) { if(newLower[i] < 1.0e100) { // feasible - no action } else { // up feasible, down infeasible returnCode = 1; if (stopOnFirstInfeasible) break; } } else { if(newLower[i] < 1.0e100) { // down feasible, up infeasible returnCode = 1; if (stopOnFirstInfeasible) break; } else { // neither side feasible returnCode = -1; break; } } } delete [] saveSolution; delete [] saveLower; delete [] saveUpper; delete [] saveObjective; delete [] saveStatus; delete [] savePivot; if ((startFinishOptions & 1) == 0) { deleteRim(1); whatsChanged_ &= ~0xffff; } else { // Original factorization will have been put back by last loop //delete factorization_; //factorization_ = new ClpFactorization(saveFactorization); deleteRim(0); // mark all as current whatsChanged_ = 0x3ffffff; } objectiveValue_ = saveObjectiveValue; return returnCode; } // treat no pivot as finished (unless interesting) int ClpSimplexDual::fastDual(bool alwaysFinish) { progressFlag_ = 0; bestObjectiveValue_ = objectiveValue_; algorithm_ = -1; secondaryStatus_ = 0; // Say in fast dual if (!alwaysFinish) specialOptions_ |= 1048576; specialOptions_ |= 16384; int saveDont = dontFactorizePivots_; if ((specialOptions_ & 2048) == 0) dontFactorizePivots_ = 0; else if(!dontFactorizePivots_) dontFactorizePivots_ = 20; //handler_->setLogLevel(63); // save data ClpDataSave data = saveData(); dualTolerance_ = dblParam_[ClpDualTolerance]; primalTolerance_ = dblParam_[ClpPrimalTolerance]; // save dual bound double saveDualBound = dualBound_; // Start can skip some things in transposeTimes specialOptions_ |= 131072; if (alphaAccuracy_ != -1.0) alphaAccuracy_ = 1.0; // for dual we will change bounds using dualBound_ // for this we need clean basis so it is after factorize #if 0 { int numberTotal = numberRows_ + numberColumns_; double * saveSol = CoinCopyOfArray(solution_, numberTotal); double * saveDj = CoinCopyOfArray(dj_, numberTotal); double tolerance = 1.0e-8; gutsOfSolution(NULL, NULL); int j; double largestPrimal = tolerance; int iPrimal = -1; for (j = 0; j < numberTotal; j++) { double difference = solution_[j] - saveSol[j]; if (fabs(difference) > largestPrimal) { iPrimal = j; largestPrimal = fabs(difference); } } double largestDual = tolerance; int iDual = -1; for (j = 0; j < numberTotal; j++) { double difference = dj_[j] - saveDj[j]; if (fabs(difference) > largestDual && upper_[j] > lower_[j]) { iDual = j; largestDual = fabs(difference); } } if (iPrimal >= 0 || iDual >= 0) printf("pivots %d primal diff(%g,%d) dual diff(%g,%d)\n", factorization_->pivots(), largestPrimal, iPrimal, largestDual, iDual); delete [] saveSol; delete [] saveDj; } #else if ((specialOptions_ & 524288) == 0) gutsOfSolution(NULL, NULL); #endif #if 0 if (numberPrimalInfeasibilities_ != 1 || numberDualInfeasibilities_) printf("dual %g (%d) primal %g (%d)\n", sumDualInfeasibilities_, numberDualInfeasibilities_, sumPrimalInfeasibilities_, numberPrimalInfeasibilities_); #endif #ifndef NDEBUG #ifdef COIN_DEVELOP resetFakeBounds(-1); #endif #endif //numberFake_ =0; // Number of variables at fake bounds numberChanged_ = 0; // Number of variables with changed costs //changeBounds(1,NULL,objectiveChange); problemStatus_ = -1; numberIterations_ = 0; if ((specialOptions_ & 524288) == 0) { factorization_->sparseThreshold(0); factorization_->goSparse(); } int lastCleaned = 0; // last time objective or bounds cleaned up // number of times we have declared optimality numberTimesOptimal_ = 0; // This says whether to restore things etc int factorType = 0; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible BUT also from whileIterating return code is: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations */ int returnCode = 0; int iRow, iColumn; int maxPass = maximumIterations(); while (problemStatus_ < 0) { // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // If getting nowhere - why not give it a kick // does not seem to work too well - do some more work if ((specialOptions_ & 524288) != 0 && (moreSpecialOptions_&2048) == 0 && perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_&1048576)==0) { perturb(); // Can't get here if values pass gutsOfSolution(NULL, NULL); if (handler_->logLevel() > 2) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } } // may factorize, checks if problem finished // should be able to speed this up on first time statusOfProblemInDual(lastCleaned, factorType, NULL, data, 0); // Say good factorization factorType = 1; maxPass--; if (maxPass < -10) { // odd returnCode = 1; problemStatus_ = 3; // can't say anything interesting - might as well return #ifdef CLP_DEBUG printf("returning from fastDual after %d iterations with code %d because of loop\n", numberIterations_, returnCode); #endif break; } // Do iterations if (problemStatus_ < 0) { double * givenPi = NULL; returnCode = whileIterating(givenPi, 0); if ((!alwaysFinish && returnCode < 0) || returnCode == 3) { if (returnCode != 3) assert (problemStatus_ < 0); returnCode = 1; problemStatus_ = 3; // can't say anything interesting - might as well return #ifdef CLP_DEBUG printf("returning from fastDual after %d iterations with code %d\n", numberIterations_, returnCode); #endif break; } if (returnCode == -2) factorType = 3; returnCode = 0; } } // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // Say not in fast dual specialOptions_ &= ~(16384 | 1048576); assert(!numberFake_ || ((specialOptions_&(2048 | 4096)) != 0 && dualBound_ >= 1.0e8) || returnCode || problemStatus_); // all bounds should be okay if (numberFake_ > 0 && false) { // Set back double dummy; changeBounds(2, NULL, dummy); } // Restore any saved stuff restoreData(data); dontFactorizePivots_ = saveDont; dualBound_ = saveDualBound; // Stop can skip some things in transposeTimes specialOptions_ &= ~131072; if (!problemStatus_) { // see if cutoff reached double limit = 0.0; getDblParam(ClpDualObjectiveLimit, limit); if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit)) { // actually infeasible on objective problemStatus_ = 1; secondaryStatus_ = 1; } } if (problemStatus_ == 3) objectiveValue_ = CoinMax(bestObjectiveValue_, objectiveValue_ - bestPossibleImprovement_); return returnCode; } // This does first part of StrongBranching ClpFactorization * ClpSimplexDual::setupForStrongBranching(char * arrays, int numberRows, int numberColumns, bool solveLp) { if (solveLp) { // make sure won't create fake objective int saveOptions = specialOptions_; specialOptions_ |= 16384; // solve int saveMaximumIterations = intParam_[ClpMaxNumIteration]; intParam_[ClpMaxNumIteration] = 100+numberRows_+numberColumns_; dual(0, 7); if (problemStatus_ == 10) { ClpSimplex::dual(0, 0); assert (problemStatus_ != 10); if (problemStatus_ == 0) { dual(0, 7); //assert (problemStatus_!=10); } } intParam_[ClpMaxNumIteration] = saveMaximumIterations; specialOptions_ = saveOptions; if (problemStatus_ != 0 && problemStatus_ != 10) return NULL; // say infeasible or odd // May be empty solveLp = (solution_ != NULL && problemStatus_ == 0); } problemStatus_ = 0; if (!solveLp) { algorithm_ = -1; // put in standard form (and make row copy) // create modifiable copies of model rim and do optional scaling int startFinishOptions; if((specialOptions_ & 4096) == 0) { startFinishOptions = 0; } else { startFinishOptions = 1 + 2 + 4; } createRim(7 + 8 + 16 + 32, true, startFinishOptions); // Do initial factorization // and set certain stuff // We can either set increasing rows so ...IsBasic gives pivot row // or we can just increment iBasic one by one // for now let ...iBasic give pivot row bool useFactorization = false; if ((startFinishOptions & 2) != 0 && (whatsChanged_&(2 + 512)) == 2 + 512) { useFactorization = true; // Keep factorization if possible // switch off factorization if bad if (pivotVariable_[0] < 0 || factorization_->numberRows() != numberRows_) useFactorization = false; } if (!useFactorization) { factorization_->setDefaultValues(); int factorizationStatus = internalFactorize(0); if (factorizationStatus < 0) { // some error // we should either debug or ignore #ifndef NDEBUG printf("***** ClpDual strong branching factorization error - debug\n"); #endif } else if (factorizationStatus && factorizationStatus <= numberRows_) { handler_->message(CLP_SINGULARITIES, messages_) << factorizationStatus << CoinMessageEol; } } } // Get fake bounds correctly double dummyChangeCost; changeBounds(3, NULL, dummyChangeCost); double * arrayD = reinterpret_cast (arrays); arrayD[0] = objectiveValue() * optimizationDirection_; double * saveSolution = arrayD + 1; double * saveLower = saveSolution + (numberRows + numberColumns); double * saveUpper = saveLower + (numberRows + numberColumns); double * saveObjective = saveUpper + (numberRows + numberColumns); double * saveLowerOriginal = saveObjective + (numberRows + numberColumns); double * saveUpperOriginal = saveLowerOriginal + numberColumns; arrayD = saveUpperOriginal + numberColumns; int * savePivot = reinterpret_cast (arrayD); int * whichRow = savePivot + numberRows; int * whichColumn = whichRow + 3 * numberRows; int * arrayI = whichColumn + 2 * numberColumns; unsigned char * saveStatus = reinterpret_cast (arrayI + 1); // save stuff // save basis and solution CoinMemcpyN(solution_, numberRows_ + numberColumns_, saveSolution); CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus); CoinMemcpyN(lower_, numberRows_ + numberColumns_, saveLower); CoinMemcpyN(upper_, numberRows_ + numberColumns_, saveUpper); CoinMemcpyN(cost_, numberRows_ + numberColumns_, saveObjective); CoinMemcpyN(pivotVariable_, numberRows_, savePivot); ClpFactorization * factorization = factorization_; factorization_ = NULL; return factorization; } // This cleans up after strong branching void ClpSimplexDual::cleanupAfterStrongBranching(ClpFactorization * factorization) { int startFinishOptions; /* COIN_CLP_VETTED Looks safe for Cbc */ if((specialOptions_ & 4096) == 0) { startFinishOptions = 0; } else { startFinishOptions = 1 + 2 + 4; } if ((startFinishOptions & 1) == 0 && cost_) { deleteRim(1); } else { // Original factorization will have been put back by last loop delete factorization_; factorization_ = factorization; //deleteRim(0); // mark all as current } whatsChanged_ &= ~0xffff; } /* Checks number of variables at fake bounds. This is used by fastDual so can exit gracefully before end */ int ClpSimplexDual::numberAtFakeBound() { int iSequence; int numberFake = 0; for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { FakeBound bound = getFakeBound(iSequence); switch(getStatus(iSequence)) { case basic: break; case isFree: case superBasic: case ClpSimplex::isFixed: //setFakeBound (iSequence, noFake); break; case atUpperBound: if (bound == upperFake || bound == bothFake) numberFake++; break; case atLowerBound: if (bound == lowerFake || bound == bothFake) numberFake++; break; } } //numberFake_ = numberFake; return numberFake; } /* Pivot out a variable and choose an incoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Return codes as before but -1 means no acceptable pivot */ int ClpSimplexDual::pivotResultPart1() { // Get good size for pivot // Allow first few iterations to take tiny double acceptablePivot = 1.0e-1 * acceptablePivot_; if (numberIterations_ > 100) acceptablePivot = acceptablePivot_; if (factorization_->pivots() > 10) acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict else if (factorization_->pivots() > 5) acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict else if (factorization_->pivots()) acceptablePivot = acceptablePivot_; // relax // But factorizations complain if <1.0e-8 //acceptablePivot=CoinMax(acceptablePivot,1.0e-8); double bestPossiblePivot = 1.0; // get sign for finding row of tableau // create as packed double direction = directionOut_; assert (!rowArray_[0]->getNumElements()); rowArray_[1]->clear(); //assert (!rowArray_[1]->getNumElements()); assert (!columnArray_[0]->getNumElements()); assert (!columnArray_[1]->getNumElements()); rowArray_[0]->createPacked(1, &pivotRow_, &direction); factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]); // Allow to do dualColumn0 if (numberThreads_ < -1) spareIntArray_[0] = 1; spareDoubleArray_[0] = acceptablePivot; rowArray_[3]->clear(); sequenceIn_ = -1; // put row of tableau in rowArray[0] and columnArray[0] assert (!rowArray_[1]->getNumElements()); if (!scaledMatrix_) { if ((moreSpecialOptions_ & 8) != 0 && !rowScale_) spareIntArray_[0] = 1; matrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[1], columnArray_[0]); } else { double * saveR = rowScale_; double * saveC = columnScale_; rowScale_ = NULL; columnScale_ = NULL; if ((moreSpecialOptions_ & 8) != 0) spareIntArray_[0] = 1; scaledMatrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[1], columnArray_[0]); rowScale_ = saveR; columnScale_ = saveC; } // do ratio test for normal iteration dualOut_ *= 1.0e-8; bestPossiblePivot = dualColumn(rowArray_[0], columnArray_[0], rowArray_[3], columnArray_[1], acceptablePivot, NULL/*dubiousWeights*/); dualOut_ *= 1.0e8; if (fabs(bestPossiblePivot)<1.0e-6) return -1; else return 0; } /* Row array has row part of pivot row Column array has column part. This is used in dual values pass */ void ClpSimplexDual::checkPossibleValuesMove(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double acceptablePivot) { double * work; int number; int * which; int iSection; double tolerance = dualTolerance_ * 1.001; double thetaDown = 1.0e31; double changeDown ; double thetaUp = 1.0e31; double bestAlphaDown = acceptablePivot * 0.99999; double bestAlphaUp = acceptablePivot * 0.99999; int sequenceDown = -1; int sequenceUp = sequenceOut_; double djBasic = dj_[sequenceOut_]; if (djBasic > 0.0) { // basic at lower bound so directionOut_ 1 and -1 in pivot row // dj will go to zero on other way thetaUp = djBasic; changeDown = -lower_[sequenceOut_]; } else { // basic at upper bound so directionOut_ -1 and 1 in pivot row // dj will go to zero on other way thetaUp = -djBasic; changeDown = upper_[sequenceOut_]; } bestAlphaUp = 1.0; int addSequence; double alphaUp = 0.0; double alphaDown = 0.0; for (iSection = 0; iSection < 2; iSection++) { int i; if (!iSection) { work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } for (i = 0; i < number; i++) { int iSequence = which[i]; int iSequence2 = iSequence + addSequence; double alpha; double oldValue; double value; switch(getStatus(iSequence2)) { case basic: break; case ClpSimplex::isFixed: alpha = work[i]; changeDown += alpha * upper_[iSequence2]; break; case isFree: case superBasic: alpha = work[i]; // dj must be effectively zero as dual feasible if (fabs(alpha) > bestAlphaUp) { thetaDown = 0.0; thetaUp = 0.0; bestAlphaDown = fabs(alpha); bestAlphaUp = bestAlphaDown; sequenceDown = iSequence2; sequenceUp = sequenceDown; alphaUp = alpha; alphaDown = alpha; } break; case atUpperBound: alpha = work[i]; oldValue = dj_[iSequence2]; changeDown += alpha * upper_[iSequence2]; if (alpha >= acceptablePivot) { // might do other way value = oldValue + thetaUp * alpha; if (value > -tolerance) { if (value > tolerance || fabs(alpha) > bestAlphaUp) { thetaUp = -oldValue / alpha; bestAlphaUp = fabs(alpha); sequenceUp = iSequence2; alphaUp = alpha; } } } else if (alpha <= -acceptablePivot) { // might do this way value = oldValue - thetaDown * alpha; if (value > -tolerance) { if (value > tolerance || fabs(alpha) > bestAlphaDown) { thetaDown = oldValue / alpha; bestAlphaDown = fabs(alpha); sequenceDown = iSequence2; alphaDown = alpha; } } } break; case atLowerBound: alpha = work[i]; oldValue = dj_[iSequence2]; changeDown += alpha * lower_[iSequence2]; if (alpha <= -acceptablePivot) { // might do other way value = oldValue + thetaUp * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaUp) { thetaUp = -oldValue / alpha; bestAlphaUp = fabs(alpha); sequenceUp = iSequence2; alphaUp = alpha; } } } else if (alpha >= acceptablePivot) { // might do this way value = oldValue - thetaDown * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaDown) { thetaDown = oldValue / alpha; bestAlphaDown = fabs(alpha); sequenceDown = iSequence2; alphaDown = alpha; } } } break; } } } thetaUp *= -1.0; double changeUp = -thetaUp * changeDown; changeDown = -thetaDown * changeDown; if (CoinMax(fabs(thetaDown), fabs(thetaUp)) < 1.0e-8) { // largest if (fabs(alphaDown) < fabs(alphaUp)) { sequenceDown = -1; } } // choose sequenceIn_ = -1; if (changeDown > changeUp && sequenceDown >= 0) { theta_ = thetaDown; if (fabs(changeDown) < 1.0e30) sequenceIn_ = sequenceDown; alpha_ = alphaDown; #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("predicted way - dirout %d, change %g,%g theta %g\n", directionOut_, changeDown, changeUp, theta_); #endif } else { theta_ = thetaUp; if (fabs(changeUp) < 1.0e30) sequenceIn_ = sequenceUp; alpha_ = alphaUp; if (sequenceIn_ != sequenceOut_) { #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("opposite way - dirout %d, change %g,%g theta %g\n", directionOut_, changeDown, changeUp, theta_); #endif } else { #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("opposite way to zero dj - dirout %d, change %g,%g theta %g\n", directionOut_, changeDown, changeUp, theta_); #endif } } if (sequenceIn_ >= 0) { lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (alpha_ < 0.0) { // as if from upper bound directionIn_ = -1; upperIn_ = valueIn_; } else { // as if from lower bound directionIn_ = 1; lowerIn_ = valueIn_; } } } /* Row array has row part of pivot row Column array has column part. This is used in cleanup */ void ClpSimplexDual::checkPossibleCleanup(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double acceptablePivot) { double * work; int number; int * which; int iSection; double tolerance = dualTolerance_ * 1.001; double thetaDown = 1.0e31; double thetaUp = 1.0e31; double bestAlphaDown = acceptablePivot * 10.0; double bestAlphaUp = acceptablePivot * 10.0; int sequenceDown = -1; int sequenceUp = -1; double djSlack = dj_[pivotRow_]; if (getRowStatus(pivotRow_) == basic) djSlack = COIN_DBL_MAX; if (fabs(djSlack) < tolerance) djSlack = 0.0; int addSequence; double alphaUp = 0.0; double alphaDown = 0.0; for (iSection = 0; iSection < 2; iSection++) { int i; if (!iSection) { work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } for (i = 0; i < number; i++) { int iSequence = which[i]; int iSequence2 = iSequence + addSequence; double alpha; double oldValue; double value; switch(getStatus(iSequence2)) { case basic: break; case ClpSimplex::isFixed: alpha = work[i]; if (addSequence) { COIN_DETAIL_PRINT(printf("possible - pivot row %d this %d\n", pivotRow_, iSequence)); oldValue = dj_[iSequence2]; if (alpha <= -acceptablePivot) { // might do other way value = oldValue + thetaUp * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaUp) { thetaUp = -oldValue / alpha; bestAlphaUp = fabs(alpha); sequenceUp = iSequence2; alphaUp = alpha; } } } else if (alpha >= acceptablePivot) { // might do this way value = oldValue - thetaDown * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaDown) { thetaDown = oldValue / alpha; bestAlphaDown = fabs(alpha); sequenceDown = iSequence2; alphaDown = alpha; } } } } break; case isFree: case superBasic: alpha = work[i]; // dj must be effectively zero as dual feasible if (fabs(alpha) > bestAlphaUp) { thetaDown = 0.0; thetaUp = 0.0; bestAlphaDown = fabs(alpha); bestAlphaUp = bestAlphaDown; sequenceDown = iSequence2; sequenceUp = sequenceDown; alphaUp = alpha; alphaDown = alpha; } break; case atUpperBound: alpha = work[i]; oldValue = dj_[iSequence2]; if (alpha >= acceptablePivot) { // might do other way value = oldValue + thetaUp * alpha; if (value > -tolerance) { if (value > tolerance || fabs(alpha) > bestAlphaUp) { thetaUp = -oldValue / alpha; bestAlphaUp = fabs(alpha); sequenceUp = iSequence2; alphaUp = alpha; } } } else if (alpha <= -acceptablePivot) { // might do this way value = oldValue - thetaDown * alpha; if (value > -tolerance) { if (value > tolerance || fabs(alpha) > bestAlphaDown) { thetaDown = oldValue / alpha; bestAlphaDown = fabs(alpha); sequenceDown = iSequence2; alphaDown = alpha; } } } break; case atLowerBound: alpha = work[i]; oldValue = dj_[iSequence2]; if (alpha <= -acceptablePivot) { // might do other way value = oldValue + thetaUp * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaUp) { thetaUp = -oldValue / alpha; bestAlphaUp = fabs(alpha); sequenceUp = iSequence2; alphaUp = alpha; } } } else if (alpha >= acceptablePivot) { // might do this way value = oldValue - thetaDown * alpha; if (value < tolerance) { if (value < -tolerance || fabs(alpha) > bestAlphaDown) { thetaDown = oldValue / alpha; bestAlphaDown = fabs(alpha); sequenceDown = iSequence2; alphaDown = alpha; } } } break; } } } thetaUp *= -1.0; // largest if (bestAlphaDown < bestAlphaUp) sequenceDown = -1; else sequenceUp = -1; sequenceIn_ = -1; if (sequenceDown >= 0) { theta_ = thetaDown; sequenceIn_ = sequenceDown; alpha_ = alphaDown; #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("predicted way - dirout %d, theta %g\n", directionOut_, theta_); #endif } else if (sequenceUp >= 0) { theta_ = thetaUp; sequenceIn_ = sequenceUp; alpha_ = alphaUp; #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("opposite way - dirout %d,theta %g\n", directionOut_, theta_); #endif } if (sequenceIn_ >= 0) { lowerIn_ = lower_[sequenceIn_]; upperIn_ = upper_[sequenceIn_]; valueIn_ = solution_[sequenceIn_]; dualIn_ = dj_[sequenceIn_]; if (alpha_ < 0.0) { // as if from upper bound directionIn_ = -1; upperIn_ = valueIn_; } else { // as if from lower bound directionIn_ = 1; lowerIn_ = valueIn_; } } } /* This sees if we can move duals in dual values pass. This is done before any pivoting */ void ClpSimplexDual::doEasyOnesInValuesPass(double * dj) { // Get column copy CoinPackedMatrix * columnCopy = matrix(); // Get a row copy in standard format CoinPackedMatrix copy; copy.setExtraGap(0.0); copy.setExtraMajor(0.0); copy.reverseOrderedCopyOf(*columnCopy); // get matrix data pointers const int * column = copy.getIndices(); const CoinBigIndex * rowStart = copy.getVectorStarts(); const int * rowLength = copy.getVectorLengths(); const double * elementByRow = copy.getElements(); double tolerance = dualTolerance_ * 1.001; int iRow; #ifdef CLP_DEBUG { double value5 = 0.0; int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (dj[i] < -1.0e-6) value5 += dj[i] * upper_[i]; else if (dj[i] > 1.0e-6) value5 += dj[i] * lower_[i]; } printf("Values objective Value before %g\n", value5); } #endif // for scaled row double * scaled = NULL; if (rowScale_) scaled = new double[numberColumns_]; for (iRow = 0; iRow < numberRows_; iRow++) { int iSequence = iRow + numberColumns_; double djBasic = dj[iSequence]; if (getRowStatus(iRow) == basic && fabs(djBasic) > tolerance) { double changeUp ; // always -1 in pivot row if (djBasic > 0.0) { // basic at lower bound changeUp = -lower_[iSequence]; } else { // basic at upper bound changeUp = upper_[iSequence]; } bool canMove = true; int i; const double * thisElements = elementByRow + rowStart[iRow]; const int * thisIndices = column + rowStart[iRow]; if (rowScale_) { // scale row double scale = rowScale_[iRow]; for (i = 0; i < rowLength[iRow]; i++) { int iColumn = thisIndices[i]; double alpha = thisElements[i]; scaled[i] = scale * alpha * columnScale_[iColumn]; } thisElements = scaled; } for (i = 0; i < rowLength[iRow]; i++) { int iColumn = thisIndices[i]; double alpha = thisElements[i]; double oldValue = dj[iColumn];; double value; switch(getStatus(iColumn)) { case basic: if (dj[iColumn] < -tolerance && fabs(solution_[iColumn] - upper_[iColumn]) < 1.0e-8) { // at ub changeUp += alpha * upper_[iColumn]; // might do other way value = oldValue + djBasic * alpha; if (value > tolerance) canMove = false; } else if (dj[iColumn] > tolerance && fabs(solution_[iColumn] - lower_[iColumn]) < 1.0e-8) { changeUp += alpha * lower_[iColumn]; // might do other way value = oldValue + djBasic * alpha; if (value < -tolerance) canMove = false; } else { canMove = false; } break; case ClpSimplex::isFixed: changeUp += alpha * upper_[iColumn]; break; case isFree: case superBasic: canMove = false; break; case atUpperBound: changeUp += alpha * upper_[iColumn]; // might do other way value = oldValue + djBasic * alpha; if (value > tolerance) canMove = false; break; case atLowerBound: changeUp += alpha * lower_[iColumn]; // might do other way value = oldValue + djBasic * alpha; if (value < -tolerance) canMove = false; break; } } if (canMove) { if (changeUp * djBasic > 1.0e-12 || fabs(changeUp) < 1.0e-8) { // move for (i = 0; i < rowLength[iRow]; i++) { int iColumn = thisIndices[i]; double alpha = thisElements[i]; dj[iColumn] += djBasic * alpha; } dj[iSequence] = 0.0; #ifdef CLP_DEBUG { double value5 = 0.0; int i; for (i = 0; i < numberRows_ + numberColumns_; i++) { if (dj[i] < -1.0e-6) value5 += dj[i] * upper_[i]; else if (dj[i] > 1.0e-6) value5 += dj[i] * lower_[i]; } printf("Values objective Value after row %d old dj %g %g\n", iRow, djBasic, value5); } #endif } } } } delete [] scaled; } int ClpSimplexDual::nextSuperBasic() { if (firstFree_ >= 0) { int returnValue = firstFree_; int iColumn = firstFree_ + 1; for (; iColumn < numberRows_ + numberColumns_; iColumn++) { if (getStatus(iColumn) == isFree) if (fabs(dj_[iColumn]) > 1.0e2 * dualTolerance_) break; } firstFree_ = iColumn; if (firstFree_ == numberRows_ + numberColumns_) firstFree_ = -1; return returnValue; } else { return -1; } } void ClpSimplexDual::resetFakeBounds(int type) { if (type == 0) { // put back original bounds and then check createRim1(false); double dummyChangeCost = 0.0; changeBounds(3, NULL, dummyChangeCost); } else if (type < 0) { #ifndef NDEBUG // just check int nTotal = numberRows_ + numberColumns_; double * tempLower = CoinCopyOfArray(lower_, nTotal); double * tempUpper = CoinCopyOfArray(upper_, nTotal); int iSequence; // Get scaled true bounds if (columnScale_) { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { // lower double value = columnLower_[iSequence]; if (value > -1.0e30) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; value *= multiplier; } tempLower[iSequence] = value; // upper value = columnUpper_[iSequence]; if (value < 1.0e30) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; value *= multiplier; } tempUpper[iSequence] = value; } for (iSequence = 0; iSequence < numberRows_; iSequence++) { // lower double value = rowLower_[iSequence]; if (value > -1.0e30) { double multiplier = rhsScale_ * rowScale_[iSequence]; value *= multiplier; } tempLower[iSequence+numberColumns_] = value; // upper value = rowUpper_[iSequence]; if (value < 1.0e30) { double multiplier = rhsScale_ * rowScale_[iSequence]; value *= multiplier; } tempUpper[iSequence+numberColumns_] = value; } } else { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { // lower tempLower[iSequence] = columnLower_[iSequence]; // upper tempUpper[iSequence] = columnUpper_[iSequence]; } for (iSequence = 0; iSequence < numberRows_; iSequence++) { // lower tempLower[iSequence+numberColumns_] = rowLower_[iSequence]; // upper tempUpper[iSequence+numberColumns_] = rowUpper_[iSequence]; } } int nFake = 0; int nErrors = 0; int nSuperBasic = 0; int nWarnings = 0; for (iSequence = 0; iSequence < nTotal; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); Status status = getStatus(iSequence); bool isFake = false; #ifdef CLP_INVESTIGATE char RC = 'C'; #endif int jSequence = iSequence; if (jSequence >= numberColumns_) { #ifdef CLP_INVESTIGATE RC = 'R'; #endif jSequence -= numberColumns_; } double lowerValue = tempLower[iSequence]; double upperValue = tempUpper[iSequence]; double value = solution_[iSequence]; CoinRelFltEq equal; if (status == atUpperBound || status == atLowerBound) { if (fakeStatus == ClpSimplexDual::upperFake) { if(!equal(upper_[iSequence], (lowerValue + dualBound_)) || !(equal(upper_[iSequence], value) || equal(lower_[iSequence], value))) { nErrors++; #ifdef CLP_INVESTIGATE printf("** upperFake %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue); #endif } isFake = true;; } else if (fakeStatus == ClpSimplexDual::lowerFake) { if(!equal(lower_[iSequence], (upperValue - dualBound_)) || !(equal(upper_[iSequence], value) || equal(lower_[iSequence], value))) { nErrors++; #ifdef CLP_INVESTIGATE printf("** lowerFake %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue); #endif } isFake = true;; } else if (fakeStatus == ClpSimplexDual::bothFake) { nWarnings++; #ifdef CLP_INVESTIGATE printf("** %d at bothFake?\n", iSequence); #endif } else if (upper_[iSequence] - lower_[iSequence] > 2.0 * dualBound_) { nErrors++; #ifdef CLP_INVESTIGATE printf("** noFake! %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue); #endif } } else if (status == superBasic || status == isFree) { nSuperBasic++; //printf("** free or superbasic %c%d %g <= %g <= %g true %g, %g - status %d\n", // RC,jSequence,lower_[iSequence],solution_[iSequence], // upper_[iSequence],lowerValue,upperValue,status); } else if (status == basic) { bool odd = false; if (!equal(lower_[iSequence], lowerValue)) odd = true; if (!equal(upper_[iSequence], upperValue)) odd = true; if (odd) { #ifdef CLP_INVESTIGATE printf("** basic %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue); #endif nWarnings++; } } else if (status == isFixed) { if (!equal(upper_[iSequence], lower_[iSequence])) { nErrors++; #ifdef CLP_INVESTIGATE printf("** fixed! %c%d %g <= %g <= %g true %g, %g\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue); #endif } } if (isFake) { nFake++; } else { if (fakeStatus != ClpSimplexDual::noFake) { nErrors++; #ifdef CLP_INVESTIGATE printf("** bad fake status %c%d %d\n", RC, jSequence, fakeStatus); #endif } } } if (nFake != numberFake_) { #ifdef CLP_INVESTIGATE printf("nfake %d numberFake %d\n", nFake, numberFake_); #endif nErrors++; } if (nErrors || type <= -1000) { #ifdef CLP_INVESTIGATE printf("%d errors, %d warnings, %d free/superbasic, %d fake\n", nErrors, nWarnings, nSuperBasic, numberFake_); printf("dualBound %g\n", dualBound_); #endif if (type <= -1000) { iSequence = -type; iSequence -= 1000; #ifdef CLP_INVESTIGATE char RC = 'C'; #endif int jSequence = iSequence; if (jSequence >= numberColumns_) { #ifdef CLP_INVESTIGATE RC = 'R'; #endif jSequence -= numberColumns_; } #ifdef CLP_INVESTIGATE double lowerValue = tempLower[iSequence]; double upperValue = tempUpper[iSequence]; printf("*** movement>1.0e30 for %c%d %g <= %g <= %g true %g, %g - status %d\n", RC, jSequence, lower_[iSequence], solution_[iSequence], upper_[iSequence], lowerValue, upperValue, status_[iSequence]); #endif assert (nErrors); // should have been picked up } assert (!nErrors); } delete [] tempLower; delete [] tempUpper; #endif } else if (lower_) { // reset using status int nTotal = numberRows_ + numberColumns_; int iSequence; if (columnScale_) { for (iSequence = 0; iSequence < numberColumns_; iSequence++) { double multiplier = rhsScale_ * inverseColumnScale_[iSequence]; // lower double value = columnLower_[iSequence]; if (value > -1.0e30) { value *= multiplier; } lower_[iSequence] = value; // upper value = columnUpper_[iSequence]; if (value < 1.0e30) { value *= multiplier; } upper_[iSequence] = value; } for (iSequence = 0; iSequence < numberRows_; iSequence++) { // lower double multiplier = rhsScale_ * rowScale_[iSequence]; double value = rowLower_[iSequence]; if (value > -1.0e30) { value *= multiplier; } lower_[iSequence+numberColumns_] = value; // upper value = rowUpper_[iSequence]; if (value < 1.0e30) { value *= multiplier; } upper_[iSequence+numberColumns_] = value; } } else { memcpy(lower_, columnLower_, numberColumns_ * sizeof(double)); memcpy(upper_, columnUpper_, numberColumns_ * sizeof(double)); memcpy(lower_ + numberColumns_, rowLower_, numberRows_ * sizeof(double)); memcpy(upper_ + numberColumns_, rowUpper_, numberRows_ * sizeof(double)); } numberFake_ = 0; for (iSequence = 0; iSequence < nTotal; iSequence++) { FakeBound fakeStatus = getFakeBound(iSequence); if (fakeStatus != ClpSimplexDual::noFake) { Status status = getStatus(iSequence); if (status == basic || status == isFixed) { setFakeBound(iSequence, ClpSimplexDual::noFake); continue; } double lowerValue = lower_[iSequence]; double upperValue = upper_[iSequence]; double value = solution_[iSequence]; numberFake_++; if (fakeStatus == ClpSimplexDual::upperFake) { upper_[iSequence] = lowerValue + dualBound_; if (status == ClpSimplex::atLowerBound) { solution_[iSequence] = lowerValue; } else if (status == ClpSimplex::atUpperBound) { solution_[iSequence] = upper_[iSequence]; } else { printf("Unknown status %d for variable %d in %s line %d\n", status,iSequence,__FILE__,__LINE__); abort(); } } else if (fakeStatus == ClpSimplexDual::lowerFake) { lower_[iSequence] = upperValue - dualBound_; if (status == ClpSimplex::atLowerBound) { solution_[iSequence] = lower_[iSequence]; } else if (status == ClpSimplex::atUpperBound) { solution_[iSequence] = upperValue; } else { printf("Unknown status %d for variable %d in %s line %d\n", status,iSequence,__FILE__,__LINE__); abort(); } } else { assert (fakeStatus == ClpSimplexDual::bothFake); if (status == ClpSimplex::atLowerBound) { lower_[iSequence] = value; upper_[iSequence] = value + dualBound_; } else if (status == ClpSimplex::atUpperBound) { upper_[iSequence] = value; lower_[iSequence] = value - dualBound_; } else if (status == ClpSimplex::isFree || status == ClpSimplex::superBasic) { lower_[iSequence] = value - 0.5 * dualBound_; upper_[iSequence] = value + 0.5 * dualBound_; } else { printf("Unknown status %d for variable %d in %s line %d\n", status,iSequence,__FILE__,__LINE__); abort(); } } } } #ifndef NDEBUG } else { COIN_DETAIL_PRINT(printf("NULL lower\n")); #endif } } Clp-1.15.10/src/config.h.in0000644000076600007660000000753012253625014013672 0ustar coincoin/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1, 2, 3, or 4 if Aboca should be build. */ #undef CLP_HAS_ABC /* SVN revision number of project */ #undef CLP_SVN_REV /* Version number of project */ #undef CLP_VERSION /* Major Version number of project */ #undef CLP_VERSION_MAJOR /* Minor Version number of project */ #undef CLP_VERSION_MINOR /* Release Version number of project */ #undef CLP_VERSION_RELEASE /* Define to the debug sanity check level (0 is no test) */ #undef COIN_CLP_CHECKLEVEL /* Define to the debug verbosity level (0 is no output) */ #undef COIN_CLP_VERBOSITY /* Define to 1 if the AMD package is available */ #undef COIN_HAS_AMD /* If defined, the BLAS Library is available. */ #undef COIN_HAS_BLAS /* Define to 1 if the CHOLMOD package is available */ #undef COIN_HAS_CHOLMOD /* Define to 1 if the CoinUtils package is available */ #undef COIN_HAS_COINUTILS /* Define to 1 if the Glpk package is available */ #undef COIN_HAS_GLPK /* Define to 1 if the Mumps package is available */ #undef COIN_HAS_MUMPS /* Define to 1 if the Netlib package is available */ #undef COIN_HAS_NETLIB /* Define to 1 if the Osi package is available */ #undef COIN_HAS_OSI /* 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 WSMP package is available */ #undef COIN_HAS_WSMP /* Define to dummy `main' function (if any) required to link to the Fortran libraries. */ #undef F77_DUMMY_MAIN /* Define to a macro mangling the given C identifier (in lower and upper case), which must not contain underscores, for linking with Fortran. */ #undef F77_FUNC /* As F77_FUNC, but for C identifiers containing underscores. */ #undef F77_FUNC_ /* Define if F77 and FC dummy `main' functions are identical. */ #undef FC_DUMMY_MAIN_EQ_F77 /* 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 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 /* 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 Clp-1.15.10/src/CoinAbcDenseFactorization.hpp0000644000076600007660000004446012101105055017363 0ustar coincoin/* $Id: CoinAbcDenseFactorization.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2008, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef CoinAbcDenseFactorization_H #define CoinAbcDenseFactorization_H #include #include #include #include "CoinTypes.hpp" #include "CoinAbcCommon.hpp" #include "CoinIndexedVector.hpp" class CoinPackedMatrix; /// Abstract base class which also has some scalars so can be used from Dense or Simp class CoinAbcAnyFactorization { public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor CoinAbcAnyFactorization ( ); /// Copy constructor CoinAbcAnyFactorization ( const CoinAbcAnyFactorization &other); /// Destructor virtual ~CoinAbcAnyFactorization ( ); /// = copy CoinAbcAnyFactorization & operator = ( const CoinAbcAnyFactorization & other ); /// Clone virtual CoinAbcAnyFactorization * clone() const = 0; //@} /**@name general stuff such as status */ //@{ /// Returns status inline int status ( ) const { return status_; } /// Sets status inline void setStatus ( int value) { status_=value; } /// Returns number of pivots since factorization inline int pivots ( ) const { return numberPivots_; } #if ABC_PARALLEL==2 /// Says parallel inline void setParallelMode(int value) {parallelMode_=value;}; #endif /// Sets number of pivots since factorization inline void setPivots ( int value ) { numberPivots_=value; } /// Returns number of slacks inline int numberSlacks ( ) const { return numberSlacks_; } /// Sets number of slacks inline void setNumberSlacks ( int value ) { numberSlacks_=value; } /// Set number of Rows after factorization inline void setNumberRows(int value) { numberRows_ = value; } /// Number of Rows after factorization inline int numberRows ( ) const { return numberRows_; } /// Number of dense rows after factorization inline CoinSimplexInt numberDense ( ) const { return numberDense_; } /// Number of good columns in factorization inline int numberGoodColumns ( ) const { return numberGoodU_; } /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed inline void relaxAccuracyCheck(double value) { relaxCheck_ = value;} inline double getAccuracyCheck() const { return relaxCheck_;} /// Maximum number of pivots between factorizations inline int maximumPivots ( ) const { return maximumPivots_ ; } /// Set maximum pivots virtual void maximumPivots ( int value ); /// Pivot tolerance inline double pivotTolerance ( ) const { return pivotTolerance_ ; } void pivotTolerance ( double value ); /// Minimum pivot tolerance inline double minimumPivotTolerance ( ) const { return minimumPivotTolerance_ ; } void minimumPivotTolerance ( double value ); virtual CoinFactorizationDouble * pivotRegion() const { return NULL;} /// Area factor inline double areaFactor ( ) const { return areaFactor_ ; } inline void areaFactor ( CoinSimplexDouble value ) { areaFactor_=value; } /// Zero tolerance inline double zeroTolerance ( ) const { return zeroTolerance_ ; } void zeroTolerance ( double value ); /// Returns array to put basis elements in virtual CoinFactorizationDouble * elements() const; /// Returns pivot row virtual int * pivotRow() const; /// Returns work area virtual CoinFactorizationDouble * workArea() const; /// Returns int work area virtual int * intWorkArea() const; /// Number of entries in each row virtual int * numberInRow() const; /// Number of entries in each column virtual int * numberInColumn() const; /// Returns array to put basis starts in virtual CoinBigIndex * starts() const; /// Returns permute back virtual int * permuteBack() const; /// Sees whether to go sparse virtual void goSparse() {} #ifndef NDEBUG virtual inline void checkMarkArrays() const {} #endif /** Get solve mode e.g. 0 C++ code, 1 Lapack, 2 choose If 4 set then values pass if 8 set then has iterated */ inline int solveMode() const { return solveMode_ ;} /** Set solve mode e.g. 0 C++ code, 1 Lapack, 2 choose If 4 set then values pass if 8 set then has iterated */ inline void setSolveMode(int value) { solveMode_ = value;} /// Returns true if wants tableauColumn in replaceColumn virtual bool wantsTableauColumn() const; /** Useful information for factorization 0 - iteration number whereFrom is 0 for factorize and 1 for replaceColumn */ virtual void setUsefulInformation(const int * info,int whereFrom); /// Get rid of all memory virtual void clearArrays() {} //@} /**@name virtual general stuff such as permutation */ //@{ /// Returns array to put basis indices in virtual int * indices() const = 0; /// Returns permute in virtual int * permute() const = 0; /// Returns pivotColumn or permute virtual int * pivotColumn() const; /// Total number of elements in factorization virtual int numberElements ( ) const = 0; //@} /**@name Do factorization - public */ //@{ /// Gets space for a factorization virtual void getAreas ( int numberRows, int numberColumns, CoinBigIndex maximumL, CoinBigIndex maximumU ) = 0; /// PreProcesses column ordered copy of basis virtual void preProcess ( ) = 0; /** Does most of factorization returning status 0 - OK -99 - needs more memory -1 - singular - use numberGoodColumns and redo */ virtual int factor (AbcSimplex * model) = 0; #ifdef EARLY_FACTORIZE /// Returns -2 if can't, -1 if singular, -99 memory, 0 OK virtual int factorize (AbcSimplex * /*model*/, CoinIndexedVector & /*stuff*/) { return -2;} #endif /// Does post processing on valid factorization - putting variables on correct rows virtual void postProcess(const int * sequence, int * pivotVariable) = 0; /// Makes a non-singular basis by replacing variables virtual void makeNonSingular(int * sequence) = 0; //@} /**@name rank one updates which do exist */ //@{ #if 0 /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots Fills in region for use later partial update already in U */ virtual int checkReplace ( CoinIndexedVector * /*regionSparse*/, int /*pivotRow*/, double & /*pivotCheck*/, double /*acceptablePivot = 1.0e-8*/) {return 0;} /** Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If skipBtranU is false will do btran part partial update already in U */ virtual int replaceColumn ( CoinIndexedVector * regionSparse, int pivotRow, double pivotCheck , bool skipBtranU=false, double acceptablePivot=1.0e-8)=0; #endif #ifdef EARLY_FACTORIZE /// 0 success, -1 can't +1 accuracy problems virtual int replaceColumns ( const AbcSimplex * /*model*/, CoinIndexedVector & /*stuff*/, int /*firstPivot*/,int /*lastPivot*/,bool /*cleanUp*/) { return -1;} #endif #ifdef ABC_LONG_FACTORIZATION /// Clear all hidden arrays virtual void clearHiddenArrays() {} #endif /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update already in U */ virtual #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * /*regionSparse*/, int /*pivotRow*/) {return 0.0;} virtual #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * /*regionSparse*/, CoinIndexedVector * /*partialUpdate*/, int /*pivotRow*/) {return 0.0;} virtual void checkReplacePart1a ( CoinIndexedVector * /* regionSparse */, int /*pivotRow*/) {} virtual double checkReplacePart1b (CoinIndexedVector * /*regionSparse*/, int /*pivotRow*/) {return 0.0;} /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ virtual int checkReplacePart2 ( int pivotRow, double btranAlpha, double ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha, double acceptablePivot = 1.0e-8) = 0; /** Replaces one Column to basis, partial update already in U */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ) = 0; /** Replaces one Column to basis, partial update in vector */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, CoinIndexedVector * partialUpdate, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha )=0; //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ //@{ /** Updates one column (FTRAN) from unpacked regionSparse Tries to do FT update number returned is negative if no room */ virtual int updateColumnFT ( CoinIndexedVector & regionSparse) = 0; virtual int updateColumnFTPart1 ( CoinIndexedVector & regionSparse) = 0; virtual void updateColumnFTPart2 ( CoinIndexedVector & regionSparse) = 0; virtual void updateColumnFT ( CoinIndexedVector & regionSparseFT, CoinIndexedVector & partialUpdate, int which)=0; /** This version has same effect as above with FTUpdate==false so number returned is always >=0 */ virtual int updateColumn ( CoinIndexedVector & regionSparse) const = 0; /// does FTRAN on two unpacked columns virtual int updateTwoColumnsFT(CoinIndexedVector & regionFT, CoinIndexedVector & regionOther) = 0; /** Updates one column (BTRAN) from unpacked regionSparse */ virtual int updateColumnTranspose ( CoinIndexedVector & regionSparse) const = 0; /** This version does FTRAN on array when indices not set up */ virtual void updateFullColumn ( CoinIndexedVector & regionSparse) const = 0; /** Updates one column (BTRAN) from unpacked regionSparse */ virtual void updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const = 0; /** Updates one column for dual steepest edge weights (FTRAN) */ virtual void updateWeights ( CoinIndexedVector & regionSparse) const=0; /** Updates one column (FTRAN) */ virtual void updateColumnCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; /** Updates one column (BTRAN) */ virtual void updateColumnTransposeCpu ( CoinIndexedVector & regionSparse,int whichCpu) const; //@} ////////////////// data ////////////////// protected: /**@name data */ //@{ /// Pivot tolerance double pivotTolerance_; /// Minimum pivot tolerance double minimumPivotTolerance_; /// Area factor double areaFactor_; /// Zero tolerance double zeroTolerance_; //#ifndef slackValue_ #define slackValue2_ 1.0 //#endif /// Relax check on accuracy in replaceColumn double relaxCheck_; /// Number of elements after factorization CoinBigIndex factorElements_; /// Number of Rows in factorization int numberRows_; /// Number of dense rows in factorization int numberDense_; /// Number factorized in U (not row singletons) int numberGoodU_; /// Maximum number of pivots before factorization int maximumPivots_; /// Number pivots since last factorization int numberPivots_; /// Number slacks int numberSlacks_; /// Status of factorization int status_; /// Maximum rows ever (i.e. use to copy arrays etc) int maximumRows_; #if ABC_PARALLEL==2 int parallelMode_; #endif /// Pivot row int * pivotRow_; /** Elements of factorization and updates length is maxR*maxR+maxSpace will always be long enough so can have nR*nR ints in maxSpace */ CoinFactorizationDouble * elements_; /// Work area of numberRows_ CoinFactorizationDouble * workArea_; /** Solve mode e.g. 0 C++ code, 1 Lapack, 2 choose If 4 set then values pass if 8 set then has iterated */ int solveMode_; //@} }; /** This deals with Factorization and Updates This is a simple dense version so other people can write a better one I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex may be redefined to get 64 bits. */ class CoinAbcDenseFactorization : public CoinAbcAnyFactorization { friend void CoinAbcDenseFactorizationUnitTest( const std::string & mpsDir ); public: /**@name Constructors and destructor and copy */ //@{ /// Default constructor CoinAbcDenseFactorization ( ); /// Copy constructor CoinAbcDenseFactorization ( const CoinAbcDenseFactorization &other); /// Destructor virtual ~CoinAbcDenseFactorization ( ); /// = copy CoinAbcDenseFactorization & operator = ( const CoinAbcDenseFactorization & other ); /// Clone virtual CoinAbcAnyFactorization * clone() const ; //@} /**@name Do factorization - public */ //@{ /// Gets space for a factorization virtual void getAreas ( int numberRows, int numberColumns, CoinBigIndex maximumL, CoinBigIndex maximumU ); /// PreProcesses column ordered copy of basis virtual void preProcess ( ); /** Does most of factorization returning status 0 - OK -99 - needs more memory -1 - singular - use numberGoodColumns and redo */ virtual int factor (AbcSimplex * model); /// Does post processing on valid factorization - putting variables on correct rows virtual void postProcess(const int * sequence, int * pivotVariable); /// Makes a non-singular basis by replacing variables virtual void makeNonSingular(int * sequence); //@} /**@name general stuff such as number of elements */ //@{ /// Total number of elements in factorization virtual inline int numberElements ( ) const { return numberRows_*(numberRows_+numberPivots_); } /// Returns maximum absolute value in factorization double maximumCoefficient() const; //@} /**@name rank one updates which do exist */ //@{ /** Replaces one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room If skipBtranU is false will do btran part partial update already in U */ virtual int replaceColumn ( CoinIndexedVector * regionSparse, int pivotRow, double pivotCheck , bool skipBtranU=false, double acceptablePivot=1.0e-8); /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ virtual int checkReplacePart2 ( int pivotRow, double btranAlpha, double ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha, double acceptablePivot = 1.0e-8) ; /** Replaces one Column to basis, partial update already in U */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ); /** Replaces one Column to basis, partial update in vector */ virtual void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, CoinIndexedVector * /*partialUpdate*/, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ) { replaceColumnPart3(model,regionSparse,tableauColumn,pivotRow,alpha);} //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ //@{ /** Updates one column (FTRAN) from unpacked regionSparse Tries to do FT update number returned is negative if no room */ virtual int updateColumnFT ( CoinIndexedVector & regionSparse) {return updateColumn(regionSparse);} virtual int updateColumnFTPart1 ( CoinIndexedVector & regionSparse) {return updateColumn(regionSparse);} virtual void updateColumnFTPart2 ( CoinIndexedVector & /*regionSparse*/) {} virtual void updateColumnFT ( CoinIndexedVector & regionSparseFT,CoinIndexedVector & /*partialUpdate*/,int /*which*/) { updateColumnFT(regionSparseFT);} /** This version has same effect as above with FTUpdate==false so number returned is always >=0 */ virtual int updateColumn ( CoinIndexedVector & regionSparse) const; /// does FTRAN on two unpacked columns virtual int updateTwoColumnsFT(CoinIndexedVector & regionFT, CoinIndexedVector & regionOther); /** Updates one column (BTRAN) from unpacked regionSparse */ virtual int updateColumnTranspose ( CoinIndexedVector & regionSparse) const; /** This version does FTRAN on array when indices not set up */ virtual void updateFullColumn ( CoinIndexedVector & regionSparse) const {updateColumn(regionSparse);} /** Updates one column (BTRAN) from unpacked regionSparse */ virtual void updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const {updateColumnTranspose(regionSparse);} /** Updates one column for dual steepest edge weights (FTRAN) */ virtual void updateWeights ( CoinIndexedVector & regionSparse) const; //@} /// *** Below this user may not want to know about /**@name various uses of factorization which user may not want to know about (left over from my LP code) */ //@{ /// Get rid of all memory inline void clearArrays() { gutsOfDestructor();} /// Returns array to put basis indices in virtual inline int * indices() const { return reinterpret_cast (elements_+numberRows_*numberRows_);} /// Returns permute in virtual inline int * permute() const { return NULL;/*pivotRow_*/;} //@} /// The real work of desstructor void gutsOfDestructor(); /// The real work of constructor void gutsOfInitialize(); /// The real work of copy void gutsOfCopy(const CoinAbcDenseFactorization &other); //@} protected: /** Returns accuracy status of replaceColumn returns 0=OK, 1=Probably OK, 2=singular */ int checkPivot(double saveFromU, double oldPivot) const; ////////////////// data ////////////////// protected: /// Maximum length of iterating area CoinBigIndex maximumSpace_; /// Use for array size to get multiple of 8 CoinSimplexInt maximumRowsAdjusted_; /**@name data */ //@{ //@} }; #endif Clp-1.15.10/src/CoinAbcHelperFunctions.hpp0000644000076600007660000016472312101105055016705 0ustar coincoin/* $Id: CoinAbcHelperFunctions.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2003, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CoinAbcHelperFunctions_H #define CoinAbcHelperFunctions_H #include "ClpConfig.h" #ifdef HAVE_CMATH # include #else # ifdef HAVE_MATH_H # include # else # include # endif #endif #include "CoinAbcCommon.hpp" #ifndef abc_assert #define abc_assert(condition) \ { if (!condition) {printf("abc_assert in %s at line %d - %s is false\n", \ __FILE__, __LINE__, __STRING(condition)); abort();} } #endif // cilk_for granularity. #define CILK_FOR_GRAINSIZE 128 //#define AVX2 2 #if AVX2==1 #include "emmintrin.h" #elif AVX2==2 #include #elif AVX2==3 #include "avx2intrin.h" #endif //#define __AVX__ 1 //#define __AVX2__ 1 /** Note (JJF) I have added some operations on arrays even though they may duplicate CoinDenseVector. */ #define UNROLL_SCATTER 2 #define INLINE_SCATTER 1 #if INLINE_SCATTER==0 void CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region); #else void ABC_INLINE inline CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL_SCATTER==0 for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL_SCATTER==1 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL_SCATTER==2 if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } if ((number&2)!=0) { CoinSimplexInt iRow0 = thisIndex[number-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble value0 = thisElement[number-1]; CoinSimplexInt iRow1 = thisIndex[number-2]; CoinFactorizationDouble regionValue1 = region[iRow1]; CoinFactorizationDouble value1 = thisElement[number-2]; region[iRow0] = regionValue0 - value0 * pivotValue; region[iRow1] = regionValue1 - value1 * pivotValue; number-=2; } #pragma cilk_grainsize=CILK_FOR_GRAINSIZE for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; CoinSimplexInt iRow2 = thisIndex[j-2]; CoinSimplexInt iRow3 = thisIndex[j-3]; CoinFactorizationDouble regionValue2 = region[iRow2]; CoinFactorizationDouble regionValue3 = region[iRow3]; region[iRow2] = regionValue2 - thisElement[j-2] * pivotValue; region[iRow3] = regionValue3 - thisElement[j-3] * pivotValue; } #elif UNROLL_SCATTER==3 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(static_cast(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } void ABC_INLINE inline CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL_SCATTER==0 const int * COIN_RESTRICT thisIndex = reinterpret_cast(thisElement+number); for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL_SCATTER==1 const int * COIN_RESTRICT thisIndex = reinterpret_cast(thisElement+number); if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } #elif UNROLL_SCATTER==2 const int * COIN_RESTRICT thisIndex = reinterpret_cast(thisElement+number); if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } if ((number&2)!=0) { CoinSimplexInt iRow0 = thisIndex[number-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble value0 = thisElement[number-1]; CoinSimplexInt iRow1 = thisIndex[number-2]; CoinFactorizationDouble regionValue1 = region[iRow1]; CoinFactorizationDouble value1 = thisElement[number-2]; region[iRow0] = regionValue0 - value0 * pivotValue; region[iRow1] = regionValue1 - value1 * pivotValue; number-=2; } #if AVX2==22 CoinFactorizationDouble temp[4] __attribute__ ((aligned (32))); __m256d pv = _mm256_broadcast_sd(&pivotValue); for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { __m256d elements=_mm256_loadu_pd(thisElement+j-3); CoinSimplexInt iRow0 = thisIndex[j-3]; CoinSimplexInt iRow1 = thisIndex[j-2]; CoinSimplexInt iRow2 = thisIndex[j-1]; CoinSimplexInt iRow3 = thisIndex[j-0]; temp[0] = region[iRow0]; temp[1] = region[iRow1]; temp[2] = region[iRow2]; temp[3] = region[iRow3]; __m256d t0=_mm256_load_pd(temp); t0 -= pv*elements; _mm256_store_pd (temp, t0); region[iRow0] = temp[0]; region[iRow1] = temp[1]; region[iRow2] = temp[2]; region[iRow3] = temp[3]; } #else #pragma cilk_grainsize=CILK_FOR_GRAINSIZE for (CoinBigIndex j=number-1 ; j >=0; j-=4 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; CoinSimplexInt iRow2 = thisIndex[j-2]; CoinSimplexInt iRow3 = thisIndex[j-3]; CoinFactorizationDouble regionValue2 = region[iRow2]; CoinFactorizationDouble regionValue3 = region[iRow3]; region[iRow2] = regionValue2 - thisElement[j-2] * pivotValue; region[iRow3] = regionValue3 - thisElement[j-3] * pivotValue; } #endif #elif UNROLL_SCATTER==3 const int * COIN_RESTRICT thisIndex = reinterpret_cast(thisElement+number); CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch(static_cast(number)) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number&1)!=0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j=number-1 ; j >=0; j-=2 ) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j-1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j-1] * pivotValue; } break; } #endif } #endif //#define COIN_PREFETCH #ifdef COIN_PREFETCH #if 1 #define coin_prefetch(mem) \ __asm__ __volatile__ ("prefetchnta %0" : : "m" (*(reinterpret_cast(mem)))) #define coin_prefetch_const(mem) \ __asm__ __volatile__ ("prefetchnta %0" : : "m" (*(reinterpret_cast(mem)))) #else #define coin_prefetch(mem) \ __asm__ __volatile__ ("prefetch %0" : : "m" (*(reinterpret_cast(mem)))) #define coin_prefetch_const(mem) \ __asm__ __volatile__ ("prefetch %0" : : "m" (*(reinterpret_cast(mem)))) #endif #else // dummy #define coin_prefetch(mem) #define coin_prefetch_const(mem) #endif #define NEW_CHUNK_SIZE 4 #define NEW_CHUNK_SIZE_INCREMENT (NEW_CHUNK_SIZE+NEW_CHUNK_SIZE/2); #define NEW_CHUNK_SIZE_OFFSET (NEW_CHUNK_SIZE/2) // leaf, pure, nothrow and hot give warnings // fastcall and sseregparm give wrong results //#define SCATTER_ATTRIBUTE __attribute__ ((leaf,fastcall,pure,sseregparm,nothrow,hot)) #define SCATTER_ATTRIBUTE typedef void (*scatterUpdate) (int,CoinFactorizationDouble,const CoinFactorizationDouble *, double *) SCATTER_ATTRIBUTE ; typedef struct { scatterUpdate functionPointer; CoinBigIndex offset; int number; } scatterStruct; void CoinAbcScatterUpdate0(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate1(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate2(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate3(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate5(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate6(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate7(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate8(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4N(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus1(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus2(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus3(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate1Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate2Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate3Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate5Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate6Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate7Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate8Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NSubtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus1Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus2Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus3Subtract(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate1Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate2Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate3Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate5Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate6Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate7Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate8Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NAdd(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus1Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus2Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; void CoinAbcScatterUpdate4NPlus3Add(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT thisElement, CoinFactorizationDouble * COIN_RESTRICT region) SCATTER_ATTRIBUTE ; #if INLINE_SCATTER==0 void CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region, double * COIN_RESTRICT work); #else #if 0 void ABC_INLINE inline CoinAbcScatterUpdate(int number,CoinFactorizationDouble pivotValue, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region, double * COIN_RESTRICT /*work*/) { #if UNROLL_SCATTER==0 for (CoinBigIndex j=number-1 ; j >=0; j-- ) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert (value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL_SCATTER==1 if ((number&1)!=0) { CoinSimplexInt iRow = thisIndex[0]; thisIndex++; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[0]; thisElement++; region[iRow] = regionValue - value * pivotValue; } number = number>>1; CoinFactorizationDouble work2[4]; for ( ; number !=0; number-- ) { CoinSimplexInt iRow0 = thisIndex[0]; CoinSimplexInt iRow1 = thisIndex[1]; work2[0] = region[iRow0]; work2[1] = region[iRow1]; #if 0 work2[2] = region[iRow0]; work2[3] = region[iRow1]; //__v4df b = __builtin_ia32_maskloadpd256(work2); __v4df b = __builtin_ia32_loadupd256(work2); //__v4df b = _mm256_load_pd(work2); #endif work2[0] -= thisElement[0] * pivotValue; work2[1] -= thisElement[1] * pivotValue; region[iRow0] = work2[0]; region[iRow1] = work2[1]; thisIndex+=2; thisElement+=2; } #endif } #endif #endif #define UNROLL_GATHER 0 #define INLINE_GATHER 1 #if INLINE_GATHER==0 CoinFactorizationDouble CoinAbcGatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region); #else CoinFactorizationDouble ABC_INLINE inline CoinAbcGatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble * COIN_RESTRICT thisElement, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { #if UNROLL_GATHER==0 CoinFactorizationDouble pivotValue=0.0; for (CoinBigIndex j = 0; j < number; j ++ ) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; #else #error code #endif } #endif #define UNROLL_MULTIPLY_INDEXED 0 #define INLINE_MULTIPLY_INDEXED 0 #if INLINE_MULTIPLY_INDEXED==0 void CoinAbcMultiplyIndexed(int number, const double * COIN_RESTRICT multiplier, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region); void CoinAbcMultiplyIndexed(int number, const long double * COIN_RESTRICT multiplier, const int * COIN_RESTRICT thisIndex, long double * COIN_RESTRICT region); #else void ABC_INLINE inline CoinAbcMultiplyIndexed(int number, const double * COIN_RESTRICT multiplier, const int * COIN_RESTRICT thisIndex, CoinFactorizationDouble * COIN_RESTRICT region) { } #endif double CoinAbcMaximumAbsElement(const double * region, int size); void CoinAbcMinMaxAbsElement(const double * region, int size,double & minimum , double & maximum); void CoinAbcMinMaxAbsNormalValues(const double * region, int size,double & minimum , double & maximum); void CoinAbcScale(double * region, double multiplier,int size); void CoinAbcScaleNormalValues(double * region, double multiplier,double killIfLessThanThis,int size); /// maximum fabs(region[i]) and then region[i]*=multiplier double CoinAbcMaximumAbsElementAndScale(double * region, double multiplier,int size); void CoinAbcSetElements(double * region, int size, double value); void CoinAbcMultiplyAdd(const double * region1, int size, double multiplier1, double * regionChanged, double multiplier2); double CoinAbcInnerProduct(const double * region1, int size, const double * region2); void CoinAbcGetNorms(const double * region, int size, double & norm1, double & norm2); /// regionTo[index[i]]=regionFrom[i] void CoinAbcScatterTo(const double * regionFrom, double * regionTo, const int * index,int number); /// regionTo[i]=regionFrom[index[i]] void CoinAbcGatherFrom(const double * regionFrom, double * regionTo, const int * index,int number); /// regionTo[index[i]]=0.0 void CoinAbcScatterZeroTo(double * regionTo, const int * index,int number); /// regionTo[indexScatter[indexList[i]]]=regionFrom[indexList[i]] void CoinAbcScatterToList(const double * regionFrom, double * regionTo, const int * indexList, const int * indexScatter ,int number); /// array[i]=1.0/sqrt(array[i]) void CoinAbcInverseSqrts(double * array, int n); void CoinAbcReciprocal(double * array, int n, const double *input); void CoinAbcMemcpyLong(double * array,const double * arrayFrom,int size); void CoinAbcMemcpyLong(int * array,const int * arrayFrom,int size); void CoinAbcMemcpyLong(unsigned char * array,const unsigned char * arrayFrom,int size); void CoinAbcMemset0Long(double * array,int size); void CoinAbcMemset0Long(int * array,int size); void CoinAbcMemset0Long(unsigned char * array,int size); void CoinAbcMemmove(double * array,const double * arrayFrom,int size); void CoinAbcMemmove(int * array,const int * arrayFrom,int size); void CoinAbcMemmove(unsigned char * array,const unsigned char * arrayFrom,int size); /// This moves down and zeroes out end void CoinAbcMemmoveAndZero(double * array,double * arrayFrom,int size); /// This compacts several sections and zeroes out end (returns number) int CoinAbcCompact(int numberSections,int alreadyDone,double * array,const int * starts, const int * lengths); /// This compacts several sections (returns number) int CoinAbcCompact(int numberSections,int alreadyDone,int * array,const int * starts, const int * lengths); #endif #if ABC_CREATE_SCATTER_FUNCTION SCATTER_ATTRIBUTE void functionName(ScatterUpdate1)(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==1); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element+1); int iColumn0=thisColumn[0]; double value0=region[iColumn0]; value0 OPERATION multiplier*element[0]; region[iColumn0]=value0; } SCATTER_ATTRIBUTE void functionName(ScatterUpdate2)(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==2); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element+2); #if NEW_CHUNK_SIZE==2 int nFull=2&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element); } #endif #if NEW_CHUNK_SIZE==4 int iColumn0=thisColumn[0]; int iColumn1=thisColumn[1]; CoinFactorizationDouble value0=region[iColumn0]; CoinFactorizationDouble value1=region[iColumn1]; value0 OPERATION multiplier*element[0]; value1 OPERATION multiplier*element[1]; region[iColumn0]=value0; region[iColumn1]=value1; #endif } SCATTER_ATTRIBUTE void functionName(ScatterUpdate3)(int numberIn, CoinFactorizationDouble multiplier, const CoinFactorizationDouble * COIN_RESTRICT element, CoinFactorizationDouble * COIN_RESTRICT region) { #ifndef NDEBUG assert (numberIn==3); #endif const int * COIN_RESTRICT thisColumn = reinterpret_cast(element+3); #if AVX2==1 double temp[2]; #endif #if NEW_CHUNK_SIZE==2 int nFull=3&(~(NEW_CHUNK_SIZE-1)); for (int j=0;j(element+4); int nFull=4&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+5); int nFull=5&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+6); int nFull=6&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+7); int nFull=7&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+8); int nFull=8&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+numberIn); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+numberIn); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+numberIn); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j(element+numberIn); int nFull=numberIn&(~(NEW_CHUNK_SIZE-1)); #if AVX2==1 double temp[4]; #endif for (int j=0;j.., * where each of major, minor, and release are nonnegative integers. * For a checkout of the Clp stable branch, release is 9999. * For a checkout of the Clp development branch, major, minor, and release are 9999. */ /*@{*/ /** Clp library version number as string. */ COINLIBAPI const char* COINLINKAGE Clp_Version(void); /** Major number of Clp library version. */ COINLIBAPI int COINLINKAGE Clp_VersionMajor(void); /** Minor number of Clp library version. */ COINLIBAPI int COINLINKAGE Clp_VersionMinor(void); /** Release number of Clp library version. */ COINLIBAPI int COINLINKAGE Clp_VersionRelease(void); /*@}*/ /**@name Constructors and destructor These do not have an exact analogue in C++. The user does not need to know structure of Clp_Simplex or Clp_Solve. For (almost) all Clp_* functions outside this group there is an exact C++ analogue created by taking the first parameter out, removing the Clp_ from name and applying the method to an object of type ClpSimplex. Similarly, for all ClpSolve_* functions there is an exact C++ analogue created by taking the first parameter out, removing the ClpSolve_ from name and applying the method to an object of type ClpSolve. */ /*@{*/ /** Default constructor */ COINLIBAPI Clp_Simplex * COINLINKAGE Clp_newModel(void); /** Destructor */ COINLIBAPI void COINLINKAGE Clp_deleteModel(Clp_Simplex * model); /** Default constructor */ COINLIBAPI Clp_Solve * COINLINKAGE ClpSolve_new(); /** Destructor */ COINLIBAPI void COINLINKAGE ClpSolve_delete(Clp_Solve * solve); /*@}*/ /**@name Load model - loads some stuff and initializes others */ /*@{*/ /** 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 Clp_loadProblem (Clp_Simplex * 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 quadratic part of the objective (the matrix part) */ COINLIBAPI void COINLINKAGE Clp_loadQuadraticObjective(Clp_Simplex * model, const int numberColumns, const CoinBigIndex * start, const int * column, const double * element); /** Read an mps file from the given filename */ COINLIBAPI int COINLINKAGE Clp_readMps(Clp_Simplex * model, const char *filename, int keepNames, int ignoreErrors); /** Copy in integer informations */ COINLIBAPI void COINLINKAGE Clp_copyInIntegerInformation(Clp_Simplex * model, const char * information); /** Drop integer informations */ COINLIBAPI void COINLINKAGE Clp_deleteIntegerInformation(Clp_Simplex * model); /** Resizes rim part of model */ COINLIBAPI void COINLINKAGE Clp_resize (Clp_Simplex * model, int newNumberRows, int newNumberColumns); /** Deletes rows */ COINLIBAPI void COINLINKAGE Clp_deleteRows(Clp_Simplex * model, int number, const int * which); /** Add rows */ COINLIBAPI void COINLINKAGE Clp_addRows(Clp_Simplex * model, int number, const double * rowLower, const double * rowUpper, const int * rowStarts, const int * columns, const double * elements); /** Deletes columns */ COINLIBAPI void COINLINKAGE Clp_deleteColumns(Clp_Simplex * model, int number, const int * which); /** Add columns */ COINLIBAPI void COINLINKAGE Clp_addColumns(Clp_Simplex * model, int number, const double * columnLower, const double * columnUpper, const double * objective, const int * columnStarts, const int * rows, const double * elements); /** Change row lower bounds */ COINLIBAPI void COINLINKAGE Clp_chgRowLower(Clp_Simplex * model, const double * rowLower); /** Change row upper bounds */ COINLIBAPI void COINLINKAGE Clp_chgRowUpper(Clp_Simplex * model, const double * rowUpper); /** Change column lower bounds */ COINLIBAPI void COINLINKAGE Clp_chgColumnLower(Clp_Simplex * model, const double * columnLower); /** Change column upper bounds */ COINLIBAPI void COINLINKAGE Clp_chgColumnUpper(Clp_Simplex * model, const double * columnUpper); /** Change objective coefficients */ COINLIBAPI void COINLINKAGE Clp_chgObjCoefficients(Clp_Simplex * model, const double * objIn); /** Drops names - makes lengthnames 0 and names empty */ COINLIBAPI void COINLINKAGE Clp_dropNames(Clp_Simplex * model); /** Copies in names */ COINLIBAPI void COINLINKAGE Clp_copyNames(Clp_Simplex * model, const char * const * rowNames, const char * const * columnNames); /*@}*/ /**@name gets and sets - you will find some synonyms at the end of this file */ /*@{*/ /** Number of rows */ COINLIBAPI int COINLINKAGE Clp_numberRows(Clp_Simplex * model); /** Number of columns */ COINLIBAPI int COINLINKAGE Clp_numberColumns(Clp_Simplex * model); /** Primal tolerance to use */ COINLIBAPI double COINLINKAGE Clp_primalTolerance(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setPrimalTolerance(Clp_Simplex * model, double value) ; /** Dual tolerance to use */ COINLIBAPI double COINLINKAGE Clp_dualTolerance(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setDualTolerance(Clp_Simplex * model, double value) ; /** Dual objective limit */ COINLIBAPI double COINLINKAGE Clp_dualObjectiveLimit(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setDualObjectiveLimit(Clp_Simplex * model, double value); /** Objective offset */ COINLIBAPI double COINLINKAGE Clp_objectiveOffset(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setObjectiveOffset(Clp_Simplex * model, double value); /** Fills in array with problem name */ COINLIBAPI void COINLINKAGE Clp_problemName(Clp_Simplex * model, int maxNumberCharacters, char * array); /* Sets problem name. Must have \0 at end. */ COINLIBAPI int COINLINKAGE Clp_setProblemName(Clp_Simplex * model, int maxNumberCharacters, char * array); /** Number of iterations */ COINLIBAPI int COINLINKAGE Clp_numberIterations(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setNumberIterations(Clp_Simplex * model, int numberIterations); /** Maximum number of iterations */ COINLIBAPI int maximumIterations(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setMaximumIterations(Clp_Simplex * model, int value); /** Maximum time in seconds (from when set called) */ COINLIBAPI double COINLINKAGE Clp_maximumSeconds(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setMaximumSeconds(Clp_Simplex * model, double value); /** Returns true if hit maximum iterations (or time) */ COINLIBAPI int COINLINKAGE Clp_hitMaximumIterations(Clp_Simplex * model); /** Status of problem: 0 - optimal 1 - primal infeasible 2 - dual infeasible 3 - stopped on iterations etc 4 - stopped due to errors */ COINLIBAPI int COINLINKAGE Clp_status(Clp_Simplex * model); /** Set problem status */ COINLIBAPI void COINLINKAGE Clp_setProblemStatus(Clp_Simplex * model, int problemStatus); /** Secondary status of problem - may get extended 0 - none 1 - primal infeasible because dual limit reached 2 - scaled problem optimal - unscaled has primal infeasibilities 3 - scaled problem optimal - unscaled has dual infeasibilities 4 - scaled problem optimal - unscaled has both dual and primal infeasibilities */ COINLIBAPI int COINLINKAGE Clp_secondaryStatus(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setSecondaryStatus(Clp_Simplex * model, int status); /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI double COINLINKAGE Clp_optimizationDirection(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setOptimizationDirection(Clp_Simplex * model, double value); /** Primal row solution */ COINLIBAPI double * COINLINKAGE Clp_primalRowSolution(Clp_Simplex * model); /** Primal column solution */ COINLIBAPI double * COINLINKAGE Clp_primalColumnSolution(Clp_Simplex * model); /** Dual row solution */ COINLIBAPI double * COINLINKAGE Clp_dualRowSolution(Clp_Simplex * model); /** Reduced costs */ COINLIBAPI double * COINLINKAGE Clp_dualColumnSolution(Clp_Simplex * model); /** Row lower */ COINLIBAPI double* COINLINKAGE Clp_rowLower(Clp_Simplex * model); /** Row upper */ COINLIBAPI double* COINLINKAGE Clp_rowUpper(Clp_Simplex * model); /** Objective */ COINLIBAPI double * COINLINKAGE Clp_objective(Clp_Simplex * model); /** Column Lower */ COINLIBAPI double * COINLINKAGE Clp_columnLower(Clp_Simplex * model); /** Column Upper */ COINLIBAPI double * COINLINKAGE Clp_columnUpper(Clp_Simplex * model); /** Number of elements in matrix */ COINLIBAPI int COINLINKAGE Clp_getNumElements(Clp_Simplex * model); /* Column starts in matrix */ COINLIBAPI const CoinBigIndex * COINLINKAGE Clp_getVectorStarts(Clp_Simplex * model); /* Row indices in matrix */ COINLIBAPI const int * COINLINKAGE Clp_getIndices(Clp_Simplex * model); /* Column vector lengths in matrix */ COINLIBAPI const int * COINLINKAGE Clp_getVectorLengths(Clp_Simplex * model); /* Element values in matrix */ COINLIBAPI const double * COINLINKAGE Clp_getElements(Clp_Simplex * model); /** Objective value */ COINLIBAPI double COINLINKAGE Clp_objectiveValue(Clp_Simplex * model); /** Integer information */ COINLIBAPI char * COINLINKAGE Clp_integerInformation(Clp_Simplex * model); /** Gives Infeasibility ray. * * Use Clp_freeRay to free the returned array. * * @return infeasibility ray, or NULL returned if none/wrong. */ COINLIBAPI double * COINLINKAGE Clp_infeasibilityRay(Clp_Simplex * model); /** Gives ray in which the problem is unbounded. * * Use Clp_freeRay to free the returned array. * * @return unbounded ray, or NULL returned if none/wrong. */ COINLIBAPI double * COINLINKAGE Clp_unboundedRay(Clp_Simplex * model); /** Frees a infeasibility or unbounded ray. */ COINLIBAPI void COINLINKAGE Clp_freeRay(Clp_Simplex * model, double * ray); /** See if status array exists (partly for OsiClp) */ COINLIBAPI int COINLINKAGE Clp_statusExists(Clp_Simplex * model); /** Return address of status array (char[numberRows+numberColumns]) */ COINLIBAPI unsigned char * COINLINKAGE Clp_statusArray(Clp_Simplex * model); /** Copy in status vector */ COINLIBAPI void COINLINKAGE Clp_copyinStatus(Clp_Simplex * model, const unsigned char * statusArray); /* status values are as in ClpSimplex.hpp i.e. 0 - free, 1 basic, 2 at upper, 3 at lower, 4 superbasic, (5 fixed) */ /* Get variable basis info */ COINLIBAPI int COINLINKAGE Clp_getColumnStatus(Clp_Simplex * model, int sequence); /* Get row basis info */ COINLIBAPI int COINLINKAGE Clp_getRowStatus(Clp_Simplex * model, int sequence); /* Set variable basis info (and value if at bound) */ COINLIBAPI void COINLINKAGE Clp_setColumnStatus(Clp_Simplex * model, int sequence, int value); /* Set row basis info (and value if at bound) */ COINLIBAPI void COINLINKAGE Clp_setRowStatus(Clp_Simplex * model, int sequence, int value); /** User pointer for whatever reason */ COINLIBAPI void COINLINKAGE Clp_setUserPointer (Clp_Simplex * model, void * pointer); COINLIBAPI void * COINLINKAGE Clp_getUserPointer (Clp_Simplex * model); /*@}*/ /**@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 Clp_registerCallBack(Clp_Simplex * model, clp_callback userCallBack); /** Unset Callback function */ COINLIBAPI void COINLINKAGE Clp_clearCallBack(Clp_Simplex * model); /** 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 */ COINLIBAPI void COINLINKAGE Clp_setLogLevel(Clp_Simplex * model, int value); COINLIBAPI int COINLINKAGE Clp_logLevel(Clp_Simplex * model); /** length of names (0 means no names0 */ COINLIBAPI int COINLINKAGE Clp_lengthNames(Clp_Simplex * model); /** Fill in array (at least lengthNames+1 long) with a row name */ COINLIBAPI void COINLINKAGE Clp_rowName(Clp_Simplex * model, int iRow, char * name); /** Fill in array (at least lengthNames+1 long) with a column name */ COINLIBAPI void COINLINKAGE Clp_columnName(Clp_Simplex * model, int iColumn, char * name); /*@}*/ /**@name Functions most useful to user */ /*@{*/ /** General solve algorithm which can do presolve. See ClpSolve.hpp for options */ COINLIBAPI int COINLINKAGE Clp_initialSolve(Clp_Simplex * model); /** Pass solve options. (Exception to direct analogue rule) */ COINLIBAPI int COINLINKAGE Clp_initialSolveWithOptions(Clp_Simplex * model, Clp_Solve *); /** Dual initial solve */ COINLIBAPI int COINLINKAGE Clp_initialDualSolve(Clp_Simplex * model); /** Primal initial solve */ COINLIBAPI int COINLINKAGE Clp_initialPrimalSolve(Clp_Simplex * model); /** Barrier initial solve */ COINLIBAPI int COINLINKAGE Clp_initialBarrierSolve(Clp_Simplex * model); /** Barrier initial solve, no crossover */ COINLIBAPI int COINLINKAGE Clp_initialBarrierNoCrossSolve(Clp_Simplex * model); /** Dual algorithm - see ClpSimplexDual.hpp for method */ COINLIBAPI int COINLINKAGE Clp_dual(Clp_Simplex * model, int ifValuesPass); /** Primal algorithm - see ClpSimplexPrimal.hpp for method */ COINLIBAPI int COINLINKAGE Clp_primal(Clp_Simplex * model, int ifValuesPass); #ifndef SLIM_CLP /** Solve the problem with the idiot code */ COINLIBAPI void COINLINKAGE Clp_idiot(Clp_Simplex * model, int tryhard); #endif /** Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ COINLIBAPI void COINLINKAGE Clp_scaling(Clp_Simplex * model, int mode); /** Gets scalingFlag */ COINLIBAPI int COINLINKAGE Clp_scalingFlag(Clp_Simplex * model); /** Crash - at present just aimed at dual, returns -2 if dual preferred and crash basis created -1 if dual preferred and all slack basis preferred 0 if basis going in was not all slack 1 if primal preferred and all slack basis preferred 2 if primal preferred and crash basis created. if gap between bounds <="gap" variables can be flipped If "pivot" is 0 No pivoting (so will just be choice of algorithm) 1 Simple pivoting e.g. gub 2 Mini iterations */ COINLIBAPI int COINLINKAGE Clp_crash(Clp_Simplex * model, double gap, int pivot); /*@}*/ /**@name most useful gets and sets */ /*@{*/ /** If problem is primal feasible */ COINLIBAPI int COINLINKAGE Clp_primalFeasible(Clp_Simplex * model); /** If problem is dual feasible */ COINLIBAPI int COINLINKAGE Clp_dualFeasible(Clp_Simplex * model); /** Dual bound */ COINLIBAPI double COINLINKAGE Clp_dualBound(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setDualBound(Clp_Simplex * model, double value); /** Infeasibility cost */ COINLIBAPI double COINLINKAGE Clp_infeasibilityCost(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setInfeasibilityCost(Clp_Simplex * model, double value); /** Perturbation: 50 - switch on perturbation 100 - auto perturb if takes too long (1.0e-6 largest nonzero) 101 - we are perturbed 102 - don't try perturbing again default is 100 others are for playing */ COINLIBAPI int COINLINKAGE Clp_perturbation(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setPerturbation(Clp_Simplex * model, int value); /** Current (or last) algorithm */ COINLIBAPI int COINLINKAGE Clp_algorithm(Clp_Simplex * model); /** Set algorithm */ COINLIBAPI void COINLINKAGE Clp_setAlgorithm(Clp_Simplex * model, int value); /** Sum of dual infeasibilities */ COINLIBAPI double COINLINKAGE Clp_sumDualInfeasibilities(Clp_Simplex * model); /** Number of dual infeasibilities */ COINLIBAPI int COINLINKAGE Clp_numberDualInfeasibilities(Clp_Simplex * model); /** Sum of primal infeasibilities */ COINLIBAPI double COINLINKAGE Clp_sumPrimalInfeasibilities(Clp_Simplex * model); /** Number of primal infeasibilities */ COINLIBAPI int COINLINKAGE Clp_numberPrimalInfeasibilities(Clp_Simplex * model); /** Save model to file, returns 0 if success. This is designed for use outside algorithms so does not save iterating arrays etc. It does not save any messaging information. Does not save scaling values. It does not know about all types of virtual functions. */ COINLIBAPI int COINLINKAGE Clp_saveModel(Clp_Simplex * model, const char * fileName); /** Restore model from file, returns 0 if success, deletes current model */ COINLIBAPI int COINLINKAGE Clp_restoreModel(Clp_Simplex * model, const char * fileName); /** Just check solution (for external use) - sets sum of infeasibilities etc */ COINLIBAPI void COINLINKAGE Clp_checkSolution(Clp_Simplex * model); /*@}*/ /******************** End of most useful part **************/ /**@name gets and sets - some synonyms */ /*@{*/ /** Number of rows */ COINLIBAPI int COINLINKAGE Clp_getNumRows(Clp_Simplex * model); /** Number of columns */ COINLIBAPI int COINLINKAGE Clp_getNumCols(Clp_Simplex * model); /** Number of iterations */ COINLIBAPI int COINLINKAGE Clp_getIterationCount(Clp_Simplex * model); /** Are there a numerical difficulties? */ COINLIBAPI int COINLINKAGE Clp_isAbandoned(Clp_Simplex * model); /** Is optimality proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenOptimal(Clp_Simplex * model); /** Is primal infeasiblity proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenPrimalInfeasible(Clp_Simplex * model); /** Is dual infeasiblity proven? */ COINLIBAPI int COINLINKAGE Clp_isProvenDualInfeasible(Clp_Simplex * model); /** Is the given primal objective limit reached? */ COINLIBAPI int COINLINKAGE Clp_isPrimalObjectiveLimitReached(Clp_Simplex * model) ; /** Is the given dual objective limit reached? */ COINLIBAPI int COINLINKAGE Clp_isDualObjectiveLimitReached(Clp_Simplex * model) ; /** Iteration limit reached? */ COINLIBAPI int COINLINKAGE Clp_isIterationLimitReached(Clp_Simplex * model); /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI double COINLINKAGE Clp_getObjSense(Clp_Simplex * model); /** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ COINLIBAPI void COINLINKAGE Clp_setObjSense(Clp_Simplex * model, double objsen); /** Primal row solution */ COINLIBAPI const double * COINLINKAGE Clp_getRowActivity(Clp_Simplex * model); /** Primal column solution */ COINLIBAPI const double * COINLINKAGE Clp_getColSolution(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setColSolution(Clp_Simplex * model, const double * input); /** Dual row solution */ COINLIBAPI const double * COINLINKAGE Clp_getRowPrice(Clp_Simplex * model); /** Reduced costs */ COINLIBAPI const double * COINLINKAGE Clp_getReducedCost(Clp_Simplex * model); /** Row lower */ COINLIBAPI const double* COINLINKAGE Clp_getRowLower(Clp_Simplex * model); /** Row upper */ COINLIBAPI const double* COINLINKAGE Clp_getRowUpper(Clp_Simplex * model); /** Objective */ COINLIBAPI const double * COINLINKAGE Clp_getObjCoefficients(Clp_Simplex * model); /** Column Lower */ COINLIBAPI const double * COINLINKAGE Clp_getColLower(Clp_Simplex * model); /** Column Upper */ COINLIBAPI const double * COINLINKAGE Clp_getColUpper(Clp_Simplex * model); /** Objective value */ COINLIBAPI double COINLINKAGE Clp_getObjValue(Clp_Simplex * model); /** Print model for debugging purposes */ COINLIBAPI void COINLINKAGE Clp_printModel(Clp_Simplex * model, const char * prefix); /* Small element value - elements less than this set to zero, default is 1.0e-20 */ COINLIBAPI double COINLINKAGE Clp_getSmallElementValue(Clp_Simplex * model); COINLIBAPI void COINLINKAGE Clp_setSmallElementValue(Clp_Simplex * model, double value); /*@}*/ /**@name Get and set ClpSolve options */ /*@{*/ COINLIBAPI void COINLINKAGE ClpSolve_setSpecialOption(Clp_Solve *, int which, int value, int extraInfo); COINLIBAPI int COINLINKAGE ClpSolve_getSpecialOption(Clp_Solve *, int which); /** method: (see ClpSolve::SolveType) 0 - dual simplex 1 - primal simplex 2 - primal or sprint 3 - barrier 4 - barrier no crossover 5 - automatic 6 - not implemented -- pass extraInfo == -1 for default behavior */ COINLIBAPI void COINLINKAGE ClpSolve_setSolveType(Clp_Solve *, int method, int extraInfo); COINLIBAPI int COINLINKAGE ClpSolve_getSolveType(Clp_Solve *); /** amount: (see ClpSolve::PresolveType) 0 - presolve on 1 - presolve off 2 - presolve number 3 - presolve number cost -- pass extraInfo == -1 for default behavior */ COINLIBAPI void COINLINKAGE ClpSolve_setPresolveType(Clp_Solve *, int amount, int extraInfo); COINLIBAPI int COINLINKAGE ClpSolve_getPresolveType(Clp_Solve *); COINLIBAPI int COINLINKAGE ClpSolve_getPresolvePasses(Clp_Solve *); COINLIBAPI int COINLINKAGE ClpSolve_getExtraInfo(Clp_Solve *, int which); COINLIBAPI void COINLINKAGE ClpSolve_setInfeasibleReturn(Clp_Solve *, int trueFalse); COINLIBAPI int COINLINKAGE ClpSolve_infeasibleReturn(Clp_Solve *); COINLIBAPI int COINLINKAGE ClpSolve_doDual(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoDual(Clp_Solve *, int doDual); COINLIBAPI int COINLINKAGE ClpSolve_doSingleton(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoSingleton(Clp_Solve *, int doSingleton); COINLIBAPI int COINLINKAGE ClpSolve_doDoubleton(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoDoubleton(Clp_Solve *, int doDoubleton); COINLIBAPI int COINLINKAGE ClpSolve_doTripleton(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoTripleton(Clp_Solve *, int doTripleton); COINLIBAPI int COINLINKAGE ClpSolve_doTighten(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoTighten(Clp_Solve *, int doTighten); COINLIBAPI int COINLINKAGE ClpSolve_doForcing(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoForcing(Clp_Solve *, int doForcing); COINLIBAPI int COINLINKAGE ClpSolve_doImpliedFree(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoImpliedFree(Clp_Solve *, int doImpliedFree); COINLIBAPI int COINLINKAGE ClpSolve_doDupcol(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoDupcol(Clp_Solve *, int doDupcol); COINLIBAPI int COINLINKAGE ClpSolve_doDuprow(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoDuprow(Clp_Solve *, int doDuprow); COINLIBAPI int COINLINKAGE ClpSolve_doSingletonColumn(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setDoSingletonColumn(Clp_Solve *, int doSingleton); COINLIBAPI int COINLINKAGE ClpSolve_presolveActions(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setPresolveActions(Clp_Solve *, int action); COINLIBAPI int COINLINKAGE ClpSolve_substitution(Clp_Solve *); COINLIBAPI void COINLINKAGE ClpSolve_setSubstitution(Clp_Solve *, int value); /*@}*/ #ifdef __cplusplus } #endif #endif Clp-1.15.10/src/ClpSimplexOther.cpp0000644000076600007660000131510512323005416015432 0ustar coincoin/* $Id: ClpSimplexOther.cpp 2029 2014-04-14 16:21:34Z 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 "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpSimplexOther.hpp" #include "ClpSimplexDual.hpp" #include "ClpSimplexPrimal.hpp" #include "ClpEventHandler.hpp" #include "ClpHelperFunctions.hpp" #include "ClpFactorization.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpNonLinearCost.hpp" #include "ClpDynamicMatrix.hpp" #include "CoinPackedMatrix.hpp" #include "CoinIndexedVector.hpp" #include "CoinBuild.hpp" #include "CoinMpsIO.hpp" #include "CoinFloatEqual.hpp" #include "ClpMessage.hpp" #include #include #include #include #include #ifdef INT_IS_8 #define COIN_ANY_BITS_PER_INT 64 #define COIN_ANY_SHIFT_PER_INT 6 #define COIN_ANY_MASK_PER_INT 0x3f #else #define COIN_ANY_BITS_PER_INT 32 #define COIN_ANY_SHIFT_PER_INT 5 #define COIN_ANY_MASK_PER_INT 0x1f #endif /* Dual ranging. This computes increase/decrease in cost for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For non-basic variables the sequence number will be that of the non-basic variables. Up to user to provide correct length arrays. */ void ClpSimplexOther::dualRanging(int numberCheck, const int * which, double * costIncreased, int * sequenceIncreased, double * costDecreased, int * sequenceDecreased, double * valueIncrease, double * valueDecrease) { rowArray_[1]->clear(); columnArray_[1]->clear(); // long enough for rows+columns assert(rowArray_[3]->capacity() >= numberRows_ + numberColumns_); rowArray_[3]->clear(); int * backPivot = rowArray_[3]->getIndices(); int i; for ( i = 0; i < numberRows_ + numberColumns_; i++) { backPivot[i] = -1; } for (i = 0; i < numberRows_; i++) { int iSequence = pivotVariable_[i]; backPivot[iSequence] = i; } // dualTolerance may be zero if from CBC. In fact use that fact bool inCBC = !dualTolerance_; if (inCBC) assert (integerType_); dualTolerance_ = dblParam_[ClpDualTolerance]; double * arrayX = rowArray_[0]->denseVector(); for ( i = 0; i < numberCheck; i++) { rowArray_[0]->clear(); //rowArray_[0]->checkClear(); //rowArray_[1]->checkClear(); //columnArray_[1]->checkClear(); columnArray_[0]->clear(); //columnArray_[0]->checkClear(); int iSequence = which[i]; if (iSequence < 0) { costIncreased[i] = 0.0; sequenceIncreased[i] = -1; costDecreased[i] = 0.0; sequenceDecreased[i] = -1; continue; } double costIncrease = COIN_DBL_MAX; double costDecrease = COIN_DBL_MAX; int sequenceIncrease = -1; int sequenceDecrease = -1; if (valueIncrease) { assert (valueDecrease); valueIncrease[i] = iSequence < numberColumns_ ? columnActivity_[iSequence] : rowActivity_[iSequence-numberColumns_]; valueDecrease[i] = valueIncrease[i]; } switch(getStatus(iSequence)) { case basic: { // non-trvial // Get pivot row int iRow = backPivot[iSequence]; assert (iRow >= 0); #ifndef COIN_FAC_NEW double plusOne = 1.0; rowArray_[0]->createPacked(1, &iRow, &plusOne); #else rowArray_[0]->createOneUnpackedElement( iRow, 1.0); #endif factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]); // put row of tableau in rowArray[0] and columnArray[0] matrix_->transposeTimes(this, -1.0, rowArray_[0], columnArray_[1], columnArray_[0]); #ifdef COIN_FAC_NEW assert (!rowArray_[0]->packedMode()); #endif double alphaIncrease; double alphaDecrease; // do ratio test up and down checkDualRatios(rowArray_[0], columnArray_[0], costIncrease, sequenceIncrease, alphaIncrease, costDecrease, sequenceDecrease, alphaDecrease); if (!inCBC) { if (valueIncrease) { if (sequenceIncrease >= 0) valueIncrease[i] = primalRanging1(sequenceIncrease, iSequence); if (sequenceDecrease >= 0) valueDecrease[i] = primalRanging1(sequenceDecrease, iSequence); } } else { int number = rowArray_[0]->getNumElements(); #ifdef COIN_FAC_NEW const int * index = rowArray_[0]->getIndices(); #endif double scale2 = 0.0; int j; for (j = 0; j < number; j++) { #ifndef COIN_FAC_NEW scale2 += arrayX[j] * arrayX[j]; #else int iRow=index[j]; scale2 += arrayX[iRow] * arrayX[iRow]; #endif } scale2 = 1.0 / sqrt(scale2); //valueIncrease[i] = scale2; if (sequenceIncrease >= 0) { double djValue = dj_[sequenceIncrease]; if (fabs(djValue) > 10.0 * dualTolerance_) { // we are going to use for cutoff so be exact costIncrease = fabs(djValue / alphaIncrease); /* Not sure this is good idea as I don't think correct e.g. suppose a continuous variable has dj slightly greater. */ if(false && sequenceIncrease < numberColumns_ && integerType_[sequenceIncrease]) { // can improve double movement = (columnScale_ == NULL) ? 1.0 : rhsScale_ * inverseColumnScale_[sequenceIncrease]; costIncrease = CoinMax(fabs(djValue * movement), costIncrease); } } else { costIncrease = 0.0; } } if (sequenceDecrease >= 0) { double djValue = dj_[sequenceDecrease]; if (fabs(djValue) > 10.0 * dualTolerance_) { // we are going to use for cutoff so be exact costDecrease = fabs(djValue / alphaDecrease); if(sequenceDecrease < numberColumns_ && integerType_[sequenceDecrease]) { // can improve double movement = (columnScale_ == NULL) ? 1.0 : rhsScale_ * inverseColumnScale_[sequenceDecrease]; costDecrease = CoinMax(fabs(djValue * movement), costDecrease); } } else { costDecrease = 0.0; } } costIncrease *= scale2; costDecrease *= scale2; } } break; case isFixed: break; case isFree: case superBasic: costIncrease = 0.0; costDecrease = 0.0; sequenceIncrease = iSequence; sequenceDecrease = iSequence; break; case atUpperBound: costIncrease = CoinMax(0.0, -dj_[iSequence]); sequenceIncrease = iSequence; if (valueIncrease) valueIncrease[i] = primalRanging1(iSequence, iSequence); break; case atLowerBound: costDecrease = CoinMax(0.0, dj_[iSequence]); sequenceDecrease = iSequence; if (valueIncrease) valueDecrease[i] = primalRanging1(iSequence, iSequence); break; } double scaleFactor; if (rowScale_) { if (iSequence < numberColumns_) scaleFactor = 1.0 / (objectiveScale_ * columnScale_[iSequence]); else scaleFactor = rowScale_[iSequence-numberColumns_] / objectiveScale_; } else { scaleFactor = 1.0 / objectiveScale_; } if (costIncrease < 1.0e30) costIncrease *= scaleFactor; if (costDecrease < 1.0e30) costDecrease *= scaleFactor; if (optimizationDirection_ == 1.0) { costIncreased[i] = costIncrease; sequenceIncreased[i] = sequenceIncrease; costDecreased[i] = costDecrease; sequenceDecreased[i] = sequenceDecrease; } else if (optimizationDirection_ == -1.0) { costIncreased[i] = costDecrease; sequenceIncreased[i] = sequenceDecrease; costDecreased[i] = costIncrease; sequenceDecreased[i] = sequenceIncrease; if (valueIncrease) { double temp = valueIncrease[i]; valueIncrease[i] = valueDecrease[i]; valueDecrease[i] = temp; } } else if (optimizationDirection_ == 0.0) { // !!!!!! ??? costIncreased[i] = COIN_DBL_MAX; sequenceIncreased[i] = -1; costDecreased[i] = COIN_DBL_MAX; sequenceDecreased[i] = -1; } else { abort(); } } rowArray_[0]->clear(); //rowArray_[1]->clear(); //columnArray_[1]->clear(); columnArray_[0]->clear(); //rowArray_[3]->clear(); if (!optimizationDirection_) printf("*** ????? Ranging with zero optimization costs\n"); } /* Row array has row part of pivot row Column array has column part. This is used in dual ranging */ void ClpSimplexOther::checkDualRatios(CoinIndexedVector * rowArray, CoinIndexedVector * columnArray, double & costIncrease, int & sequenceIncrease, double & alphaIncrease, double & costDecrease, int & sequenceDecrease, double & alphaDecrease) { double acceptablePivot = 1.0e-9; double * work; int number; int * which; int iSection; double thetaDown = 1.0e31; double thetaUp = 1.0e31; int sequenceDown = -1; int sequenceUp = -1; double alphaDown = 0.0; double alphaUp = 0.0; int addSequence; for (iSection = 0; iSection < 2; iSection++) { int i; if (!iSection) { work = rowArray->denseVector(); number = rowArray->getNumElements(); which = rowArray->getIndices(); addSequence = numberColumns_; } else { work = columnArray->denseVector(); number = columnArray->getNumElements(); which = columnArray->getIndices(); addSequence = 0; } for (i = 0; i < number; i++) { int iSequence = which[i]; int iSequence2 = iSequence + addSequence; #ifndef COIN_FAC_NEW double alpha = work[i]; #else double alpha = !addSequence ? work[i] : work[iSequence]; #endif if (fabs(alpha) < acceptablePivot) continue; double oldValue = dj_[iSequence2]; switch(getStatus(iSequence2)) { case basic: break; case ClpSimplex::isFixed: break; case isFree: case superBasic: // treat dj as if zero thetaDown = 0.0; thetaUp = 0.0; sequenceDown = iSequence2; sequenceUp = iSequence2; break; case atUpperBound: if (alpha > 0.0) { // test up if (oldValue + thetaUp * alpha > dualTolerance_) { thetaUp = (dualTolerance_ - oldValue) / alpha; sequenceUp = iSequence2; alphaUp = alpha; } } else { // test down if (oldValue - thetaDown * alpha > dualTolerance_) { thetaDown = -(dualTolerance_ - oldValue) / alpha; sequenceDown = iSequence2; alphaDown = alpha; } } break; case atLowerBound: if (alpha < 0.0) { // test up if (oldValue + thetaUp * alpha < - dualTolerance_) { thetaUp = -(dualTolerance_ + oldValue) / alpha; sequenceUp = iSequence2; alphaUp = alpha; } } else { // test down if (oldValue - thetaDown * alpha < -dualTolerance_) { thetaDown = (dualTolerance_ + oldValue) / alpha; sequenceDown = iSequence2; alphaDown = alpha; } } break; } } } if (sequenceUp >= 0) { costIncrease = thetaUp; sequenceIncrease = sequenceUp; alphaIncrease = alphaUp; } if (sequenceDown >= 0) { costDecrease = thetaDown; sequenceDecrease = sequenceDown; alphaDecrease = alphaDown; } } /** Primal ranging. This computes increase/decrease in value for each given variable and corresponding sequence numbers which would change basis. Sequence numbers are 0..numberColumns and numberColumns.. for artificials/slacks. For basic variables the sequence number will be that of the basic variables. Up to user to provide correct length arrays. When here - guaranteed optimal */ void ClpSimplexOther::primalRanging(int numberCheck, const int * which, double * valueIncreased, int * sequenceIncreased, double * valueDecreased, int * sequenceDecreased) { rowArray_[0]->clear(); rowArray_[1]->clear(); lowerIn_ = -COIN_DBL_MAX; upperIn_ = COIN_DBL_MAX; valueIn_ = 0.0; for ( int i = 0; i < numberCheck; i++) { int iSequence = which[i]; double valueIncrease = COIN_DBL_MAX; double valueDecrease = COIN_DBL_MAX; int sequenceIncrease = -1; int sequenceDecrease = -1; switch(getStatus(iSequence)) { case basic: case isFree: case superBasic: // Easy valueDecrease = CoinMax(0.0, upper_[iSequence] - solution_[iSequence]); valueIncrease = CoinMax(0.0, solution_[iSequence] - lower_[iSequence]); sequenceDecrease = iSequence; sequenceIncrease = iSequence; break; case isFixed: case atUpperBound: case atLowerBound: { // Non trivial // Other bound is ignored #ifndef COIN_FAC_NEW unpackPacked(rowArray_[1], iSequence); #else unpack(rowArray_[1], iSequence); #endif factorization_->updateColumn(rowArray_[2], rowArray_[1]); // Get extra rows matrix_->extendUpdated(this, rowArray_[1], 0); // do ratio test checkPrimalRatios(rowArray_[1], 1); if (pivotRow_ >= 0) { valueIncrease = theta_; sequenceIncrease = pivotVariable_[pivotRow_]; } checkPrimalRatios(rowArray_[1], -1); if (pivotRow_ >= 0) { valueDecrease = theta_; sequenceDecrease = pivotVariable_[pivotRow_]; } rowArray_[1]->clear(); } break; } double scaleFactor; if (rowScale_) { if (iSequence < numberColumns_) scaleFactor = columnScale_[iSequence] / rhsScale_; else scaleFactor = 1.0 / (rowScale_[iSequence-numberColumns_] * rhsScale_); } else { scaleFactor = 1.0 / rhsScale_; } if (valueIncrease < 1.0e30) valueIncrease *= scaleFactor; else valueIncrease = COIN_DBL_MAX; if (valueDecrease < 1.0e30) valueDecrease *= scaleFactor; else valueDecrease = COIN_DBL_MAX; valueIncreased[i] = valueIncrease; sequenceIncreased[i] = sequenceIncrease; valueDecreased[i] = valueDecrease; sequenceDecreased[i] = sequenceDecrease; } } // Returns new value of whichOther when whichIn enters basis double ClpSimplexOther::primalRanging1(int whichIn, int whichOther) { rowArray_[0]->clear(); rowArray_[1]->clear(); int iSequence = whichIn; double newValue = solution_[whichOther]; double alphaOther = 0.0; Status status = getStatus(iSequence); assert (status == atLowerBound || status == atUpperBound); int wayIn = (status == atLowerBound) ? 1 : -1; switch(getStatus(iSequence)) { case basic: case isFree: case superBasic: assert (whichIn == whichOther); // Easy newValue = wayIn > 0 ? upper_[iSequence] : lower_[iSequence]; break; case isFixed: case atUpperBound: case atLowerBound: // Non trivial { // Other bound is ignored #ifndef COIN_FAC_NEW unpackPacked(rowArray_[1], iSequence); #else unpack(rowArray_[1], iSequence); #endif factorization_->updateColumn(rowArray_[2], rowArray_[1]); // Get extra rows matrix_->extendUpdated(this, rowArray_[1], 0); // do ratio test double acceptablePivot = 1.0e-7; double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); // we may need to swap sign double way = wayIn; double theta = 1.0e30; for (int iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; #ifndef COIN_FAC_NEW double alpha = work[iIndex] * way; #else double alpha = work[iRow] * way; #endif int iPivot = pivotVariable_[iRow]; if (iPivot == whichOther) { alphaOther = alpha; continue; } double oldValue = solution_[iPivot]; if (fabs(alpha) > acceptablePivot) { if (alpha > 0.0) { // basic variable going towards lower bound double bound = lower_[iPivot]; oldValue -= bound; if (oldValue - theta * alpha < 0.0) { theta = CoinMax(0.0, oldValue / alpha); } } else { // basic variable going towards upper bound double bound = upper_[iPivot]; oldValue = oldValue - bound; if (oldValue - theta * alpha > 0.0) { theta = CoinMax(0.0, oldValue / alpha); } } } } if (whichIn != whichOther) { if (theta < 1.0e30) newValue -= theta * alphaOther; else newValue = alphaOther > 0.0 ? -1.0e30 : 1.0e30; } else { newValue += theta * wayIn; } } rowArray_[1]->clear(); break; } double scaleFactor; if (rowScale_) { if (whichOther < numberColumns_) scaleFactor = columnScale_[whichOther] / rhsScale_; else scaleFactor = 1.0 / (rowScale_[whichOther-numberColumns_] * rhsScale_); } else { scaleFactor = 1.0 / rhsScale_; } if (newValue < 1.0e29) if (newValue > -1.0e29) newValue *= scaleFactor; else newValue = -COIN_DBL_MAX; else newValue = COIN_DBL_MAX; return newValue; } /* Row array has pivot column This is used in primal ranging */ void ClpSimplexOther::checkPrimalRatios(CoinIndexedVector * rowArray, int direction) { // sequence stays as row number until end pivotRow_ = -1; double acceptablePivot = 1.0e-7; double * work = rowArray->denseVector(); int number = rowArray->getNumElements(); int * which = rowArray->getIndices(); // we need to swap sign if going down double way = direction; theta_ = 1.0e30; for (int iIndex = 0; iIndex < number; iIndex++) { int iRow = which[iIndex]; #ifndef COIN_FAC_NEW double alpha = work[iIndex] * way; #else double alpha = work[iRow] * way; #endif int iPivot = pivotVariable_[iRow]; double oldValue = solution_[iPivot]; if (fabs(alpha) > acceptablePivot) { if (alpha > 0.0) { // basic variable going towards lower bound double bound = lower_[iPivot]; oldValue -= bound; if (oldValue - theta_ * alpha < 0.0) { pivotRow_ = iRow; theta_ = CoinMax(0.0, oldValue / alpha); } } else { // basic variable going towards upper bound double bound = upper_[iPivot]; oldValue = oldValue - bound; if (oldValue - theta_ * alpha > 0.0) { pivotRow_ = iRow; theta_ = CoinMax(0.0, oldValue / alpha); } } } } } /* Write the basis in MPS format to the specified file. If writeValues true writes values of structurals (and adds VALUES to end of NAME card) Row and column names may be null. formatType is
  • 0 - normal
  • 1 - extra accuracy
  • 2 - IEEE hex (later)
Returns non-zero on I/O error This is based on code contributed by Thorsten Koch */ int ClpSimplexOther::writeBasis(const char *filename, bool writeValues, int formatType) const { formatType = CoinMax(0, formatType); formatType = CoinMin(2, formatType); if (!writeValues) formatType = 0; // See if INTEL if IEEE if (formatType == 2) { // test intel here and add 1 if not intel double value = 1.0; char x[8]; memcpy(x, &value, 8); if (x[0] == 63) { formatType ++; // not intel } else { assert (x[0] == 0); } } char number[20]; FILE * fp = fopen(filename, "w"); if (!fp) return -1; // NAME card if (strcmp(strParam_[ClpProbName].c_str(), "") == 0) { fprintf(fp, "NAME BLANK "); } else { fprintf(fp, "NAME %s ", strParam_[ClpProbName].c_str()); } if (formatType >= 2) fprintf(fp, "FREEIEEE"); else if (writeValues) fprintf(fp, "VALUES"); // finish off name fprintf(fp, "\n"); int iRow = 0; for(int iColumn = 0; iColumn < numberColumns_; iColumn++) { bool printit = false; if( getColumnStatus(iColumn) == ClpSimplex::basic) { printit = true; // Find non basic row for(; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) != ClpSimplex::basic) break; } if (lengthNames_) { if (iRow != numberRows_) { fprintf(fp, " %s %-8s %s", getRowStatus(iRow) == ClpSimplex::atUpperBound ? "XU" : "XL", columnNames_[iColumn].c_str(), rowNames_[iRow].c_str()); iRow++; } else { // Allow for too many basics! fprintf(fp, " BS %-8s ", columnNames_[iColumn].c_str()); // Dummy row name if values if (writeValues) fprintf(fp, " _dummy_"); } } else { // no names if (iRow != numberRows_) { fprintf(fp, " %s C%7.7d R%7.7d", getRowStatus(iRow) == ClpSimplex::atUpperBound ? "XU" : "XL", iColumn, iRow); iRow++; } else { // Allow for too many basics! fprintf(fp, " BS C%7.7d", iColumn); // Dummy row name if values if (writeValues) fprintf(fp, " _dummy_"); } } } else { if( getColumnStatus(iColumn) == ClpSimplex::atUpperBound) { printit = true; if (lengthNames_) fprintf(fp, " UL %s", columnNames_[iColumn].c_str()); else fprintf(fp, " UL C%7.7d", iColumn); // Dummy row name if values if (writeValues) fprintf(fp, " _dummy_"); } } if (printit && writeValues) { // add value CoinConvertDouble(0, formatType, columnActivity_[iColumn], number); fprintf(fp, " %s", number); } if (printit) fprintf(fp, "\n"); } fprintf(fp, "ENDATA\n"); fclose(fp); return 0; } // Read a basis from the given filename int ClpSimplexOther::readBasis(const char *fileName) { int status = 0; if (strcmp(fileName, "-") != 0 && strcmp(fileName, "stdin") != 0) { FILE *fp = fopen(fileName, "r"); if (fp) { // can open - lets go for it fclose(fp); } else { handler_->message(CLP_UNABLE_OPEN, messages_) << fileName << CoinMessageEol; return -1; } } CoinMpsIO m; m.passInMessageHandler(handler_); *m.messagesPointer() = coinMessages(); bool savePrefix = m.messageHandler()->prefix(); m.messageHandler()->setPrefix(handler_->prefix()); status = m.readBasis(fileName, "", columnActivity_, status_ + numberColumns_, status_, columnNames_, numberColumns_, rowNames_, numberRows_); m.messageHandler()->setPrefix(savePrefix); if (status >= 0) { if (!status) { // set values int iColumn, iRow; for (iRow = 0; iRow < numberRows_; iRow++) { if (getRowStatus(iRow) == atLowerBound) rowActivity_[iRow] = rowLower_[iRow]; else if (getRowStatus(iRow) == atUpperBound) rowActivity_[iRow] = rowUpper_[iRow]; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (getColumnStatus(iColumn) == atLowerBound) columnActivity_[iColumn] = columnLower_[iColumn]; else if (getColumnStatus(iColumn) == atUpperBound) columnActivity_[iColumn] = columnUpper_[iColumn]; } } else { memset(rowActivity_, 0, numberRows_ * sizeof(double)); matrix_->times(-1.0, columnActivity_, rowActivity_); } } else { // errors handler_->message(CLP_IMPORT_ERRORS, messages_) << status << fileName << CoinMessageEol; } return status; } /* Creates dual of a problem if looks plausible (defaults will always create model) fractionRowRanges is fraction of rows allowed to have ranges fractionColumnRanges is fraction of columns allowed to have ranges */ ClpSimplex * ClpSimplexOther::dualOfModel(double fractionRowRanges, double fractionColumnRanges) const { const ClpSimplex * model2 = static_cast (this); bool changed = false; int numberChanged = 0; int numberFreeColumnsInPrimal=0; int iColumn; // check if we need to change bounds to rows for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (columnUpper_[iColumn] < 1.0e20) { if (columnLower_[iColumn] > -1.0e20) { changed = true; numberChanged++; } } else if (columnLower_[iColumn] < -1.0e20) { numberFreeColumnsInPrimal++; } } int iRow; int numberExtraRows = 0; int numberFreeColumnsInDual=0; if (numberChanged <= fractionColumnRanges * numberColumns_) { for (iRow = 0; iRow < numberRows_; iRow++) { if (rowLower_[iRow] > -1.0e20 && rowUpper_[iRow] < 1.0e20) { if (rowUpper_[iRow] != rowLower_[iRow]) numberExtraRows++; else numberFreeColumnsInDual++; } } if (numberExtraRows > fractionRowRanges * numberRows_) return NULL; } else { return NULL; } printf("would have %d free columns in primal, %d in dual\n", numberFreeColumnsInPrimal,numberFreeColumnsInDual); if (4*(numberFreeColumnsInDual-numberFreeColumnsInPrimal)> numberColumns_&&fractionRowRanges<1.0) return NULL; //dangerous (well anyway in dual) if (changed) { ClpSimplex * model3 = new ClpSimplex(*model2); CoinBuild build; double one = 1.0; int numberColumns = model3->numberColumns(); const double * columnLower = model3->columnLower(); const double * columnUpper = model3->columnUpper(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] < 1.0e20 && columnLower[iColumn] > -1.0e20) { if (fabs(columnLower[iColumn]) < fabs(columnUpper[iColumn])) { double value = columnUpper[iColumn]; model3->setColumnUpper(iColumn, COIN_DBL_MAX); build.addRow(1, &iColumn, &one, -COIN_DBL_MAX, value); } else { double value = columnLower[iColumn]; model3->setColumnLower(iColumn, -COIN_DBL_MAX); build.addRow(1, &iColumn, &one, value, COIN_DBL_MAX); } } } model3->addRows(build); model2 = model3; } int numberColumns = model2->numberColumns(); const double * columnLower = model2->columnLower(); const double * columnUpper = model2->columnUpper(); int numberRows = model2->numberRows(); double * rowLower = CoinCopyOfArray(model2->rowLower(), numberRows); double * rowUpper = CoinCopyOfArray(model2->rowUpper(), numberRows); const double * objective = model2->objective(); CoinPackedMatrix * matrix = model2->matrix(); // get transpose CoinPackedMatrix rowCopy = *matrix; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); double objOffset = 0.0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double offset = 0.0; double objValue = optimizationDirection_ * objective[iColumn]; if (columnUpper[iColumn] > 1.0e20) { if (columnLower[iColumn] > -1.0e20) offset = columnLower[iColumn]; } else if (columnLower[iColumn] < -1.0e20) { offset = columnUpper[iColumn]; } else { // taken care of before abort(); } if (offset) { objOffset += offset * objValue; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (rowLower[iRow] > -1.0e20) rowLower[iRow] -= offset * elementByColumn[j]; if (rowUpper[iRow] < 1.0e20) rowUpper[iRow] -= offset * elementByColumn[j]; } } } int * which = new int[numberRows+numberExtraRows]; rowCopy.reverseOrdering(); rowCopy.transpose(); double * fromRowsLower = new double[numberRows+numberExtraRows]; double * fromRowsUpper = new double[numberRows+numberExtraRows]; double * newObjective = new double[numberRows+numberExtraRows]; double * fromColumnsLower = new double[numberColumns]; double * fromColumnsUpper = new double[numberColumns]; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double objValue = optimizationDirection_ * objective[iColumn]; // Offset is already in if (columnUpper[iColumn] > 1.0e20) { if (columnLower[iColumn] > -1.0e20) { fromColumnsLower[iColumn] = -COIN_DBL_MAX; fromColumnsUpper[iColumn] = objValue; } else { // free fromColumnsLower[iColumn] = objValue; fromColumnsUpper[iColumn] = objValue; } } else if (columnLower[iColumn] < -1.0e20) { fromColumnsLower[iColumn] = objValue; fromColumnsUpper[iColumn] = COIN_DBL_MAX; } else { abort(); } } int kRow = 0; int kExtraRow = numberRows; for (iRow = 0; iRow < numberRows; iRow++) { if (rowLower[iRow] < -1.0e20) { assert (rowUpper[iRow] < 1.0e20); newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; } else if (rowUpper[iRow] > 1.0e20) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = 0.0; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { if (rowUpper[iRow] == rowLower[iRow]) { newObjective[kRow] = -rowLower[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX;; fromRowsUpper[kRow] = COIN_DBL_MAX; which[kRow] = iRow; kRow++; } else { // range newObjective[kRow] = -rowUpper[iRow]; fromRowsLower[kRow] = -COIN_DBL_MAX; fromRowsUpper[kRow] = 0.0; which[kRow] = iRow; kRow++; newObjective[kExtraRow] = -rowLower[iRow]; fromRowsLower[kExtraRow] = 0.0; fromRowsUpper[kExtraRow] = COIN_DBL_MAX; which[kExtraRow] = iRow; kExtraRow++; } } } if (numberExtraRows) { CoinPackedMatrix newCopy; newCopy.setExtraGap(0.0); newCopy.setExtraMajor(0.0); newCopy.submatrixOfWithDuplicates(rowCopy, kExtraRow, which); rowCopy = newCopy; } ClpSimplex * modelDual = new ClpSimplex(); modelDual->loadProblem(rowCopy, fromRowsLower, fromRowsUpper, newObjective, fromColumnsLower, fromColumnsUpper); modelDual->setObjectiveOffset(objOffset); modelDual->setDualBound(model2->dualBound()); modelDual->setInfeasibilityCost(model2->infeasibilityCost()); modelDual->setDualTolerance(model2->dualTolerance()); modelDual->setPrimalTolerance(model2->primalTolerance()); modelDual->setPerturbation(model2->perturbation()); modelDual->setSpecialOptions(model2->specialOptions()); modelDual->setMoreSpecialOptions(model2->moreSpecialOptions()); modelDual->setMaximumIterations(model2->maximumIterations()); modelDual->setFactorizationFrequency(model2->factorizationFrequency()); modelDual->setLogLevel(model2->logLevel()); delete [] fromRowsLower; delete [] fromRowsUpper; delete [] fromColumnsLower; delete [] fromColumnsUpper; delete [] newObjective; delete [] which; delete [] rowLower; delete [] rowUpper; if (changed) delete model2; modelDual->createStatus(); return modelDual; } // Restores solution from dualized problem int ClpSimplexOther::restoreFromDual(const ClpSimplex * dualProblem, bool checkAccuracy) { int returnCode = 0;; createStatus(); // Number of rows in dual problem was original number of columns assert (numberColumns_ == dualProblem->numberRows()); // If slack on d-row basic then column at bound otherwise column basic // If d-column basic then rhs tight int numberBasic = 0; int iRow, iColumn = 0; // Get number of extra rows from ranges int numberExtraRows = 0; for (iRow = 0; iRow < numberRows_; iRow++) { if (rowLower_[iRow] > -1.0e20 && rowUpper_[iRow] < 1.0e20) { if (rowUpper_[iRow] != rowLower_[iRow]) numberExtraRows++; } } const double * objective = this->objective(); const double * dualDual = dualProblem->dualRowSolution(); const double * dualDj = dualProblem->dualColumnSolution(); const double * dualSol = dualProblem->primalColumnSolution(); const double * dualActs = dualProblem->primalRowSolution(); #if 0 ClpSimplex thisCopy = *this; thisCopy.dual(); // for testing const double * primalDual = thisCopy.dualRowSolution(); const double * primalDj = thisCopy.dualColumnSolution(); const double * primalSol = thisCopy.primalColumnSolution(); const double * primalActs = thisCopy.primalRowSolution(); char ss[] = {'F', 'B', 'U', 'L', 'S', 'F'}; printf ("Dual problem row info %d rows\n", dualProblem->numberRows()); for (iRow = 0; iRow < dualProblem->numberRows(); iRow++) printf("%d at %c primal %g dual %g\n", iRow, ss[dualProblem->getRowStatus(iRow)], dualActs[iRow], dualDual[iRow]); printf ("Dual problem column info %d columns\n", dualProblem->numberColumns()); for (iColumn = 0; iColumn < dualProblem->numberColumns(); iColumn++) printf("%d at %c primal %g dual %g\n", iColumn, ss[dualProblem->getColumnStatus(iColumn)], dualSol[iColumn], dualDj[iColumn]); printf ("Primal problem row info %d rows\n", thisCopy.numberRows()); for (iRow = 0; iRow < thisCopy.numberRows(); iRow++) printf("%d at %c primal %g dual %g\n", iRow, ss[thisCopy.getRowStatus(iRow)], primalActs[iRow], primalDual[iRow]); printf ("Primal problem column info %d columns\n", thisCopy.numberColumns()); for (iColumn = 0; iColumn < thisCopy.numberColumns(); iColumn++) printf("%d at %c primal %g dual %g\n", iColumn, ss[thisCopy.getColumnStatus(iColumn)], primalSol[iColumn], primalDj[iColumn]); #endif // position at bound information int jColumn = numberRows_; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double objValue = optimizationDirection_ * objective[iColumn]; Status status = dualProblem->getRowStatus(iColumn); double otherValue = COIN_DBL_MAX; if (columnUpper_[iColumn] < 1.0e20 && columnLower_[iColumn] > -1.0e20) { if (fabs(columnLower_[iColumn]) < fabs(columnUpper_[iColumn])) { otherValue = columnUpper_[iColumn] + dualDj[jColumn]; } else { otherValue = columnLower_[iColumn] + dualDj[jColumn]; } jColumn++; } if (status == basic) { // column is at bound if (otherValue == COIN_DBL_MAX) { reducedCost_[iColumn] = objValue - dualActs[iColumn]; if (columnUpper_[iColumn] > 1.0e20) { if (columnLower_[iColumn] > -1.0e20) { if (columnUpper_[iColumn] > columnLower_[iColumn]) setColumnStatus(iColumn, atLowerBound); else setColumnStatus(iColumn, isFixed); columnActivity_[iColumn] = columnLower_[iColumn]; } else { // free setColumnStatus(iColumn, isFree); columnActivity_[iColumn] = 0.0; } } else { setColumnStatus(iColumn, atUpperBound); columnActivity_[iColumn] = columnUpper_[iColumn]; } } else { reducedCost_[iColumn] = objValue - dualActs[iColumn]; //printf("other dual sol %g\n",otherValue); if (fabs(otherValue - columnLower_[iColumn]) < 1.0e-5) { if (columnUpper_[iColumn] > columnLower_[iColumn]) setColumnStatus(iColumn, atLowerBound); else setColumnStatus(iColumn, isFixed); columnActivity_[iColumn] = columnLower_[iColumn]; } else if (fabs(otherValue - columnUpper_[iColumn]) < 1.0e-5) { if (columnUpper_[iColumn] > columnLower_[iColumn]) setColumnStatus(iColumn, atUpperBound); else setColumnStatus(iColumn, isFixed); columnActivity_[iColumn] = columnUpper_[iColumn]; } else { abort(); } } } else { if (otherValue == COIN_DBL_MAX) { // column basic setColumnStatus(iColumn, basic); numberBasic++; if (columnLower_[iColumn] > -1.0e20) { columnActivity_[iColumn] = -dualDual[iColumn] + columnLower_[iColumn]; } else if (columnUpper_[iColumn] < 1.0e20) { columnActivity_[iColumn] = -dualDual[iColumn] + columnUpper_[iColumn]; } else { columnActivity_[iColumn] = -dualDual[iColumn]; } reducedCost_[iColumn] = 0.0; } else { // may be at other bound //printf("xx %d %g jcol %d\n",iColumn,otherValue,jColumn-1); if (dualProblem->getColumnStatus(jColumn - 1) != basic) { // column basic setColumnStatus(iColumn, basic); numberBasic++; //printf("Col %d otherV %g dualDual %g\n",iColumn, // otherValue,dualDual[iColumn]); columnActivity_[iColumn] = -dualDual[iColumn]; columnActivity_[iColumn] = otherValue; reducedCost_[iColumn] = 0.0; } else { reducedCost_[iColumn] = objValue - dualActs[iColumn]; if (fabs(otherValue - columnLower_[iColumn]) < 1.0e-5) { if (columnUpper_[iColumn] > columnLower_[iColumn]) setColumnStatus(iColumn, atLowerBound); else setColumnStatus(iColumn, isFixed); columnActivity_[iColumn] = columnLower_[iColumn]; } else if (fabs(otherValue - columnUpper_[iColumn]) < 1.0e-5) { if (columnUpper_[iColumn] > columnLower_[iColumn]) setColumnStatus(iColumn, atUpperBound); else setColumnStatus(iColumn, isFixed); columnActivity_[iColumn] = columnUpper_[iColumn]; } else { abort(); } } } } } // now rows int kExtraRow = jColumn; int numberRanges = 0; for (iRow = 0; iRow < numberRows_; iRow++) { Status status = dualProblem->getColumnStatus(iRow); if (status == basic) { // row is at bound dual_[iRow] = dualSol[iRow];; } else { // row basic setRowStatus(iRow, basic); numberBasic++; dual_[iRow] = 0.0; } if (rowLower_[iRow] < -1.0e20) { if (status == basic) { rowActivity_[iRow] = rowUpper_[iRow]; setRowStatus(iRow, atUpperBound); } else { // might be stopped assert (dualDj[iRow] < 1.0e-5); rowActivity_[iRow] = rowUpper_[iRow] + dualDj[iRow]; } } else if (rowUpper_[iRow] > 1.0e20) { if (status == basic) { rowActivity_[iRow] = rowLower_[iRow]; setRowStatus(iRow, atLowerBound); } else { rowActivity_[iRow] = rowLower_[iRow] + dualDj[iRow]; // might be stopped assert (dualDj[iRow] > -1.0e-5); } } else { if (rowUpper_[iRow] == rowLower_[iRow]) { rowActivity_[iRow] = rowLower_[iRow]; if (status == basic) { setRowStatus(iRow, isFixed); } } else { // range numberRanges++; Status statusL = dualProblem->getColumnStatus(kExtraRow); //printf("range row %d (%d), extra %d (%d) - dualSol %g,%g dualDj %g,%g\n", // iRow,status,kExtraRow,statusL, dualSol[iRow], // dualSol[kExtraRow],dualDj[iRow],dualDj[kExtraRow]); if (status == basic) { // might be stopped assert (statusL != basic); rowActivity_[iRow] = rowUpper_[iRow]; setRowStatus(iRow, atUpperBound); } else if (statusL == basic) { numberBasic--; // already counted rowActivity_[iRow] = rowLower_[iRow]; setRowStatus(iRow, atLowerBound); dual_[iRow] = dualSol[kExtraRow];; } else { rowActivity_[iRow] = rowLower_[iRow] - dualDj[iRow]; // might be stopped assert (dualDj[iRow] < 1.0e-5); // row basic //setRowStatus(iRow,basic); //numberBasic++; dual_[iRow] = 0.0; } kExtraRow++; } } } if (numberBasic != numberRows_) { printf("Bad basis - ranges - coding needed\n"); assert (numberRanges); abort(); } if (optimizationDirection_ < 0.0) { for (iRow = 0; iRow < numberRows_; iRow++) { dual_[iRow] = -dual_[iRow]; } } // redo row activities memset(rowActivity_, 0, numberRows_ * sizeof(double)); matrix_->times(1.0, columnActivity_, rowActivity_); // redo reduced costs memcpy(reducedCost_, this->objective(), numberColumns_ * sizeof(double)); matrix_->transposeTimes(-1.0, dual_, reducedCost_); checkSolutionInternal(); if (sumDualInfeasibilities_ > 1.0e-5 || sumPrimalInfeasibilities_ > 1.0e-5) { returnCode = 1; #ifdef CLP_INVESTIGATE printf("There are %d dual infeasibilities summing to %g ", numberDualInfeasibilities_, sumDualInfeasibilities_); printf("and %d primal infeasibilities summing to %g\n", numberPrimalInfeasibilities_, sumPrimalInfeasibilities_); #endif } // Below will go to ..DEBUG later #if 1 //ndef NDEBUG if (checkAccuracy) { // Check if correct double * columnActivity = CoinCopyOfArray(columnActivity_, numberColumns_); double * rowActivity = CoinCopyOfArray(rowActivity_, numberRows_); double * reducedCost = CoinCopyOfArray(reducedCost_, numberColumns_); double * dual = CoinCopyOfArray(dual_, numberRows_); this->dual(); //primal(); CoinRelFltEq eq(1.0e-5); for (iRow = 0; iRow < numberRows_; iRow++) { assert(eq(dual[iRow], dual_[iRow])); } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { assert(eq(columnActivity[iColumn], columnActivity_[iColumn])); } for (iRow = 0; iRow < numberRows_; iRow++) { assert(eq(rowActivity[iRow], rowActivity_[iRow])); } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { assert(eq(reducedCost[iColumn], reducedCost_[iColumn])); } delete [] columnActivity; delete [] rowActivity; delete [] reducedCost; delete [] dual; } #endif return returnCode; } /* Does very cursory presolve. rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns */ ClpSimplex * ClpSimplexOther::crunch(double * rhs, int * whichRow, int * whichColumn, int & nBound, bool moreBounds, bool tightenBounds) { //#define CHECK_STATUS #ifdef CHECK_STATUS { int n = 0; int i; for (i = 0; i < numberColumns_; i++) if (getColumnStatus(i) == ClpSimplex::basic) n++; for (i = 0; i < numberRows_; i++) if (getRowStatus(i) == ClpSimplex::basic) n++; assert (n == numberRows_); } #endif const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); CoinZeroN(rhs, numberRows_); int iColumn; int iRow; CoinZeroN(whichRow, numberRows_); int * backColumn = whichColumn + numberColumns_; int numberRows2 = 0; int numberColumns2 = 0; double offset = 0.0; const double * objective = this->objective(); double * solution = columnActivity_; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; if (upper > lower || getColumnStatus(iColumn) == ClpSimplex::basic) { backColumn[iColumn] = numberColumns2; whichColumn[numberColumns2++] = iColumn; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; int n = whichRow[iRow]; if (n == 0 && element[j]) whichRow[iRow] = -iColumn - 1; else if (n < 0) whichRow[iRow] = 2; } } else { // fixed backColumn[iColumn] = -1; solution[iColumn] = upper; if (upper) { offset += objective[iColumn] * upper; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; rhs[iRow] += upper * value; } } } } int returnCode = 0; double tolerance = primalTolerance(); nBound = 2 * numberRows_; for (iRow = 0; iRow < numberRows_; iRow++) { int n = whichRow[iRow]; if (n > 0) { whichRow[numberRows2++] = iRow; } else if (n < 0) { //whichRow[numberRows2++]=iRow; //continue; // Can only do in certain circumstances as we don't know current value if (rowLower_[iRow] == rowUpper_[iRow] || getRowStatus(iRow) == ClpSimplex::basic) { // save row and column for bound whichRow[--nBound] = iRow; whichRow[nBound+numberRows_] = -n - 1; } else if (moreBounds) { // save row and column for bound whichRow[--nBound] = iRow; whichRow[nBound+numberRows_] = -n - 1; } else { whichRow[numberRows2++] = iRow; } } else { // empty double rhsValue = rhs[iRow]; if (rhsValue < rowLower_[iRow] - tolerance || rhsValue > rowUpper_[iRow] + tolerance) { returnCode = 1; // infeasible } } } ClpSimplex * small = NULL; if (!returnCode) { //printf("CRUNCH from (%d,%d) to (%d,%d)\n", // numberRows_,numberColumns_,numberRows2,numberColumns2); small = new ClpSimplex(this, numberRows2, whichRow, numberColumns2, whichColumn, true, false); #if 0 ClpPackedMatrix * rowCopy = dynamic_cast(rowCopy_); if (rowCopy) { assert(!small->rowCopy()); small->setNewRowCopy(new ClpPackedMatrix(*rowCopy, numberRows2, whichRow, numberColumns2, whichColumn)); } #endif // Set some stuff small->setDualBound(dualBound_); small->setInfeasibilityCost(infeasibilityCost_); small->setSpecialOptions(specialOptions_); small->setPerturbation(perturbation_); small->defaultFactorizationFrequency(); small->setAlphaAccuracy(alphaAccuracy_); // If no rows left then no tightening! if (!numberRows2 || !numberColumns2) tightenBounds = false; int numberElements = getNumElements(); int numberElements2 = small->getNumElements(); small->setObjectiveOffset(objectiveOffset() - offset); handler_->message(CLP_CRUNCH_STATS, messages_) << numberRows2 << -(numberRows_ - numberRows2) << numberColumns2 << -(numberColumns_ - numberColumns2) << numberElements2 << -(numberElements - numberElements2) << CoinMessageEol; // And set objective value to match small->setObjectiveValue(this->objectiveValue()); double * rowLower2 = small->rowLower(); double * rowUpper2 = small->rowUpper(); int jRow; for (jRow = 0; jRow < numberRows2; jRow++) { iRow = whichRow[jRow]; if (rowLower2[jRow] > -1.0e20) rowLower2[jRow] -= rhs[iRow]; if (rowUpper2[jRow] < 1.0e20) rowUpper2[jRow] -= rhs[iRow]; } // and bounds double * columnLower2 = small->columnLower(); double * columnUpper2 = small->columnUpper(); const char * integerInformation = integerType_; for (jRow = nBound; jRow < 2 * numberRows_; jRow++) { iRow = whichRow[jRow]; iColumn = whichRow[jRow+numberRows_]; double lowerRow = rowLower_[iRow]; if (lowerRow > -1.0e20) lowerRow -= rhs[iRow]; double upperRow = rowUpper_[iRow]; if (upperRow < 1.0e20) upperRow -= rhs[iRow]; int jColumn = backColumn[iColumn]; double lower = columnLower2[jColumn]; double upper = columnUpper2[jColumn]; double value = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (iRow == row[j]) { value = element[j]; break; } } assert (value); // convert rowLower and Upper to implied bounds on column double newLower = -COIN_DBL_MAX; double newUpper = COIN_DBL_MAX; if (value > 0.0) { if (lowerRow > -1.0e20) newLower = lowerRow / value; if (upperRow < 1.0e20) newUpper = upperRow / value; } else { if (upperRow < 1.0e20) newLower = upperRow / value; if (lowerRow > -1.0e20) newUpper = lowerRow / value; } if (integerInformation && integerInformation[iColumn]) { if (newLower - floor(newLower) < 10.0 * tolerance) newLower = floor(newLower); else newLower = ceil(newLower); if (ceil(newUpper) - newUpper < 10.0 * tolerance) newUpper = ceil(newUpper); else newUpper = floor(newUpper); } newLower = CoinMax(lower, newLower); newUpper = CoinMin(upper, newUpper); if (newLower > newUpper + tolerance) { //printf("XXYY inf on bound\n"); returnCode = 1; } columnLower2[jColumn] = newLower; columnUpper2[jColumn] = CoinMax(newLower, newUpper); if (getRowStatus(iRow) != ClpSimplex::basic) { if (getColumnStatus(iColumn) == ClpSimplex::basic) { if (columnLower2[jColumn] == columnUpper2[jColumn]) { // can only get here if will be fixed small->setColumnStatus(jColumn, ClpSimplex::isFixed); } else { // solution is valid if (fabs(columnActivity_[iColumn] - columnLower2[jColumn]) < fabs(columnActivity_[iColumn] - columnUpper2[jColumn])) small->setColumnStatus(jColumn, ClpSimplex::atLowerBound); else small->setColumnStatus(jColumn, ClpSimplex::atUpperBound); } } else { //printf("what now neither basic\n"); } } } if (returnCode) { delete small; small = NULL; } else if (tightenBounds && integerInformation) { // See if we can tighten any bounds // use rhs for upper and small duals for lower double * up = rhs; double * lo = small->dualRowSolution(); const double * element = small->clpMatrix()->getElements(); const int * row = small->clpMatrix()->getIndices(); const CoinBigIndex * columnStart = small->clpMatrix()->getVectorStarts(); //const int * columnLength = small->clpMatrix()->getVectorLengths(); CoinZeroN(lo, numberRows2); CoinZeroN(up, numberRows2); for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { double upper = columnUpper2[iColumn]; double lower = columnLower2[iColumn]; //assert (columnLength[iColumn]==columnStart[iColumn+1]-columnStart[iColumn]); for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { if (upper < 1.0e20) up[iRow] += upper * value; else up[iRow] = COIN_DBL_MAX; if (lower > -1.0e20) lo[iRow] += lower * value; else lo[iRow] = -COIN_DBL_MAX; } else { if (upper < 1.0e20) lo[iRow] += upper * value; else lo[iRow] = -COIN_DBL_MAX; if (lower > -1.0e20) up[iRow] += lower * value; else up[iRow] = COIN_DBL_MAX; } } } double * rowLower2 = small->rowLower(); double * rowUpper2 = small->rowUpper(); bool feasible = true; // make safer for (int iRow = 0; iRow < numberRows2; iRow++) { double lower = lo[iRow]; if (lower > rowUpper2[iRow] + tolerance) { feasible = false; break; } else { lo[iRow] = CoinMin(lower - rowUpper2[iRow], 0.0) - tolerance; } double upper = up[iRow]; if (upper < rowLower2[iRow] - tolerance) { feasible = false; break; } else { up[iRow] = CoinMax(upper - rowLower2[iRow], 0.0) + tolerance; } } if (!feasible) { delete small; small = NULL; } else { // and tighten for (int iColumn = 0; iColumn < numberColumns2; iColumn++) { if (integerInformation[whichColumn[iColumn]]) { double upper = columnUpper2[iColumn]; double lower = columnLower2[iColumn]; double newUpper = upper; double newLower = lower; double difference = upper - lower; if (lower > -1000.0 && upper < 1000.0) { for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { double upWithOut = up[iRow] - value * difference; if (upWithOut < 0.0) { newLower = CoinMax(newLower, lower - (upWithOut + tolerance) / value); } double lowWithOut = lo[iRow] + value * difference; if (lowWithOut > 0.0) { newUpper = CoinMin(newUpper, upper - (lowWithOut - tolerance) / value); } } else { double upWithOut = up[iRow] + value * difference; if (upWithOut < 0.0) { newUpper = CoinMin(newUpper, upper - (upWithOut + tolerance) / value); } double lowWithOut = lo[iRow] - value * difference; if (lowWithOut > 0.0) { newLower = CoinMax(newLower, lower - (lowWithOut - tolerance) / value); } } } if (newLower > lower || newUpper < upper) { if (fabs(newUpper - floor(newUpper + 0.5)) > 1.0e-6) newUpper = floor(newUpper); else newUpper = floor(newUpper + 0.5); if (fabs(newLower - ceil(newLower - 0.5)) > 1.0e-6) newLower = ceil(newLower); else newLower = ceil(newLower - 0.5); // change may be too small - check if (newLower > lower || newUpper < upper) { if (newUpper >= newLower) { // Could also tighten in this //printf("%d bounds %g %g tightened to %g %g\n", // iColumn,columnLower2[iColumn],columnUpper2[iColumn], // newLower,newUpper); #if 1 columnUpper2[iColumn] = newUpper; columnLower2[iColumn] = newLower; columnUpper_[whichColumn[iColumn]] = newUpper; columnLower_[whichColumn[iColumn]] = newLower; #endif // and adjust bounds on rows newUpper -= upper; newLower -= lower; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn+1]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { up[iRow] += newUpper * value; lo[iRow] += newLower * value; } else { lo[iRow] += newUpper * value; up[iRow] += newLower * value; } } } else { // infeasible //printf("%d bounds infeasible %g %g tightened to %g %g\n", // iColumn,columnLower2[iColumn],columnUpper2[iColumn], // newLower,newUpper); #if 1 delete small; small = NULL; break; #endif } } } } } } } } } #if 0 if (small) { static int which = 0; which++; char xxxx[20]; sprintf(xxxx, "bad%d.mps", which); small->writeMps(xxxx, 0, 1); sprintf(xxxx, "largebad%d.mps", which); writeMps(xxxx, 0, 1); printf("bad%d %x old size %d %d new %d %d\n", which, small, numberRows_, numberColumns_, small->numberRows(), small->numberColumns()); #if 0 for (int i = 0; i < numberColumns_; i++) printf("Bound %d %g %g\n", i, columnLower_[i], columnUpper_[i]); for (int i = 0; i < numberRows_; i++) printf("Row bound %d %g %g\n", i, rowLower_[i], rowUpper_[i]); #endif } #endif #ifdef CHECK_STATUS { int n = 0; int i; for (i = 0; i < small->numberColumns(); i++) if (small->getColumnStatus(i) == ClpSimplex::basic) n++; for (i = 0; i < small->numberRows(); i++) if (small->getRowStatus(i) == ClpSimplex::basic) n++; assert (n == small->numberRows()); } #endif return small; } /* After very cursory presolve. rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. */ void ClpSimplexOther::afterCrunch(const ClpSimplex & small, const int * whichRow, const int * whichColumn, int nBound) { #ifndef NDEBUG for (int i = 0; i < small.numberRows(); i++) assert (whichRow[i] >= 0 && whichRow[i] < numberRows_); for (int i = 0; i < small.numberColumns(); i++) assert (whichColumn[i] >= 0 && whichColumn[i] < numberColumns_); #endif getbackSolution(small, whichRow, whichColumn); // and deal with status for bounds const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); double tolerance = primalTolerance(); double djTolerance = dualTolerance(); for (int jRow = nBound; jRow < 2 * numberRows_; jRow++) { int iRow = whichRow[jRow]; int iColumn = whichRow[jRow+numberRows_]; if (getColumnStatus(iColumn) != ClpSimplex::basic) { double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; double value = columnActivity_[iColumn]; double djValue = reducedCost_[iColumn]; dual_[iRow] = 0.0; if (upper > lower) { if (value < lower + tolerance && djValue > -djTolerance) { setColumnStatus(iColumn, ClpSimplex::atLowerBound); setRowStatus(iRow, ClpSimplex::basic); } else if (value > upper - tolerance && djValue < djTolerance) { setColumnStatus(iColumn, ClpSimplex::atUpperBound); setRowStatus(iRow, ClpSimplex::basic); } else { // has to be basic setColumnStatus(iColumn, ClpSimplex::basic); reducedCost_[iColumn] = 0.0; double value = 0.0; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { if (iRow == row[j]) { value = element[j]; break; } } dual_[iRow] = djValue / value; if (rowUpper_[iRow] > rowLower_[iRow]) { if (fabs(rowActivity_[iRow] - rowLower_[iRow]) < fabs(rowActivity_[iRow] - rowUpper_[iRow])) setRowStatus(iRow, ClpSimplex::atLowerBound); else setRowStatus(iRow, ClpSimplex::atUpperBound); } else { setRowStatus(iRow, ClpSimplex::isFixed); } } } else { // row can always be basic setRowStatus(iRow, ClpSimplex::basic); } } else { // row can always be basic setRowStatus(iRow, ClpSimplex::basic); } } //#ifndef NDEBUG #if 0 if (small.status() == 0) { int n = 0; int i; for (i = 0; i < numberColumns; i++) if (getColumnStatus(i) == ClpSimplex::basic) n++; for (i = 0; i < numberRows; i++) if (getRowStatus(i) == ClpSimplex::basic) n++; assert (n == numberRows); } #endif } /* Tightens integer bounds - returns number tightened or -1 if infeasible */ int ClpSimplexOther::tightenIntegerBounds(double * rhsSpace) { // See if we can tighten any bounds // use rhs for upper and small duals for lower double * up = rhsSpace; double * lo = dual_; const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); CoinZeroN(lo, numberRows_); CoinZeroN(up, numberRows_); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double upper = columnUpper_[iColumn]; double lower = columnLower_[iColumn]; //assert (columnLength[iColumn]==columnStart[iColumn+1]-columnStart[iColumn]); for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { if (upper < 1.0e20) up[iRow] += upper * value; else up[iRow] = COIN_DBL_MAX; if (lower > -1.0e20) lo[iRow] += lower * value; else lo[iRow] = -COIN_DBL_MAX; } else { if (upper < 1.0e20) lo[iRow] += upper * value; else lo[iRow] = -COIN_DBL_MAX; if (lower > -1.0e20) up[iRow] += lower * value; else up[iRow] = COIN_DBL_MAX; } } } bool feasible = true; // make safer double tolerance = primalTolerance(); for (int iRow = 0; iRow < numberRows_; iRow++) { double lower = lo[iRow]; if (lower > rowUpper_[iRow] + tolerance) { feasible = false; break; } else { lo[iRow] = CoinMin(lower - rowUpper_[iRow], 0.0) - tolerance; } double upper = up[iRow]; if (upper < rowLower_[iRow] - tolerance) { feasible = false; break; } else { up[iRow] = CoinMax(upper - rowLower_[iRow], 0.0) + tolerance; } } int numberTightened = 0; if (!feasible) { return -1; } else if (integerType_) { // and tighten for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { if (integerType_[iColumn]) { double upper = columnUpper_[iColumn]; double lower = columnLower_[iColumn]; double newUpper = upper; double newLower = lower; double difference = upper - lower; if (lower > -1000.0 && upper < 1000.0) { for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { double upWithOut = up[iRow] - value * difference; if (upWithOut < 0.0) { newLower = CoinMax(newLower, lower - (upWithOut + tolerance) / value); } double lowWithOut = lo[iRow] + value * difference; if (lowWithOut > 0.0) { newUpper = CoinMin(newUpper, upper - (lowWithOut - tolerance) / value); } } else { double upWithOut = up[iRow] + value * difference; if (upWithOut < 0.0) { newUpper = CoinMin(newUpper, upper - (upWithOut + tolerance) / value); } double lowWithOut = lo[iRow] - value * difference; if (lowWithOut > 0.0) { newLower = CoinMax(newLower, lower - (lowWithOut - tolerance) / value); } } } if (newLower > lower || newUpper < upper) { if (fabs(newUpper - floor(newUpper + 0.5)) > 1.0e-6) newUpper = floor(newUpper); else newUpper = floor(newUpper + 0.5); if (fabs(newLower - ceil(newLower - 0.5)) > 1.0e-6) newLower = ceil(newLower); else newLower = ceil(newLower - 0.5); // change may be too small - check if (newLower > lower || newUpper < upper) { if (newUpper >= newLower) { numberTightened++; //printf("%d bounds %g %g tightened to %g %g\n", // iColumn,columnLower_[iColumn],columnUpper_[iColumn], // newLower,newUpper); columnUpper_[iColumn] = newUpper; columnLower_[iColumn] = newLower; // and adjust bounds on rows newUpper -= upper; newLower -= lower; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; double value = element[j]; if (value > 0.0) { up[iRow] += newUpper * value; lo[iRow] += newLower * value; } else { lo[iRow] += newUpper * value; up[iRow] += newLower * value; } } } else { // infeasible //printf("%d bounds infeasible %g %g tightened to %g %g\n", // iColumn,columnLower_[iColumn],columnUpper_[iColumn], // newLower,newUpper); return -1; } } } } } } } return numberTightened; } /* Parametrics This is an initial slow version. The code uses current bounds + theta * change (if change array not NULL) and similarly for objective. It starts at startingTheta and returns ending theta in endingTheta. If reportIncrement 0.0 it will report on any movement If reportIncrement >0.0 it will report at startingTheta+k*reportIncrement. If it can not reach input endingTheta return code will be 1 for infeasible, 2 for unbounded, if error on ranges -1, otherwise 0. Normal report is just theta and objective but if event handler exists it may do more On exit endingTheta is maximum reached (can be used for next startingTheta) */ int ClpSimplexOther::parametrics(double startingTheta, double & endingTheta, double reportIncrement, const double * lowerChangeBound, const double * upperChangeBound, const double * lowerChangeRhs, const double * upperChangeRhs, const double * changeObjective) { bool needToDoSomething = true; bool canTryQuick = (reportIncrement) ? true : false; // Save copy of model ClpSimplex copyModel = *this; int savePerturbation = perturbation_; perturbation_ = 102; // switch off while (needToDoSomething) { needToDoSomething = false; algorithm_ = -1; // save data ClpDataSave data = saveData(); // Dantzig ClpDualRowPivot * savePivot = dualRowPivot_; dualRowPivot_ = new ClpDualRowDantzig(); dualRowPivot_->setModel(this); int returnCode = reinterpret_cast (this)->startupSolve(0, NULL, 0); int iRow, iColumn; double * chgUpper = NULL; double * chgLower = NULL; double * chgObjective = NULL; if (!returnCode) { // Find theta when bounds will cross over and create arrays int numberTotal = numberRows_ + numberColumns_; chgLower = new double[numberTotal]; memset(chgLower, 0, numberTotal * sizeof(double)); chgUpper = new double[numberTotal]; memset(chgUpper, 0, numberTotal * sizeof(double)); chgObjective = new double[numberTotal]; memset(chgObjective, 0, numberTotal * sizeof(double)); assert (!rowScale_); double maxTheta = 1.0e50; if (lowerChangeRhs || upperChangeRhs) { for (iRow = 0; iRow < numberRows_; iRow++) { double lower = rowLower_[iRow]; double upper = rowUpper_[iRow]; if (lower > upper) { maxTheta = -1.0; break; } double lowerChange = (lowerChangeRhs) ? lowerChangeRhs[iRow] : 0.0; double upperChange = (upperChangeRhs) ? upperChangeRhs[iRow] : 0.0; if (lower > -1.0e20 && upper < 1.0e20) { if (lower + maxTheta * lowerChange > upper + maxTheta * upperChange) { maxTheta = (upper - lower) / (lowerChange - upperChange); } } if (lower > -1.0e20) { lower_[numberColumns_+iRow] += startingTheta * lowerChange; chgLower[numberColumns_+iRow] = lowerChange; } if (upper < 1.0e20) { upper_[numberColumns_+iRow] += startingTheta * upperChange; chgUpper[numberColumns_+iRow] = upperChange; } } } if (maxTheta > 0.0) { if (lowerChangeBound || upperChangeBound) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; if (lower > upper) { maxTheta = -1.0; break; } double lowerChange = (lowerChangeBound) ? lowerChangeBound[iColumn] : 0.0; double upperChange = (upperChangeBound) ? upperChangeBound[iColumn] : 0.0; if (lower > -1.0e20 && upper < 1.0e20) { if (lower + maxTheta * lowerChange > upper + maxTheta * upperChange) { maxTheta = (upper - lower) / (lowerChange - upperChange); } } if (lower > -1.0e20) { lower_[iColumn] += startingTheta * lowerChange; chgLower[iColumn] = lowerChange; } if (upper < 1.0e20) { upper_[iColumn] += startingTheta * upperChange; chgUpper[iColumn] = upperChange; } } } if (maxTheta == 1.0e50) maxTheta = COIN_DBL_MAX; } if (maxTheta < 0.0) { // bad ranges or initial returnCode = -1; } if (maxTheta < endingTheta) { char line[100]; sprintf(line,"Crossover considerations reduce ending theta from %g to %g\n", endingTheta,maxTheta); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; endingTheta = maxTheta; } if (endingTheta < startingTheta) { // bad initial returnCode = -2; } } double saveEndingTheta = endingTheta; if (!returnCode) { if (changeObjective) { for (iColumn = 0; iColumn < numberColumns_; iColumn++) { chgObjective[iColumn] = changeObjective[iColumn]; cost_[iColumn] += startingTheta * changeObjective[iColumn]; } } double * saveDuals = NULL; reinterpret_cast (this)->gutsOfDual(0, saveDuals, -1, data); assert (!problemStatus_); for (int i=0;imessage(CLP_PARAMETRICS_STATS, messages_) << startingTheta << objectiveValue() << CoinMessageEol; while (!returnCode) { //assert (reportIncrement); parametricsData paramData; paramData.startingTheta=startingTheta; paramData.endingTheta=endingTheta; paramData.maxTheta=COIN_DBL_MAX; paramData.lowerChange = chgLower; paramData.upperChange = chgUpper; returnCode = parametricsLoop(paramData, reportIncrement, chgLower, chgUpper, chgObjective, data, canTryQuick); startingTheta=paramData.startingTheta; endingTheta=paramData.endingTheta; if (!returnCode) { //double change = endingTheta-startingTheta; startingTheta = endingTheta; endingTheta = saveEndingTheta; //for (int i=0;imessage(CLP_PARAMETRICS_STATS, messages_) << startingTheta << objectiveValue() << CoinMessageEol; if (startingTheta >= endingTheta) break; } else if (returnCode == -1) { // trouble - do external solve needToDoSomething = true; } else if (problemStatus_==1) { // can't move any further if (!canTryQuick) { handler_->message(CLP_PARAMETRICS_STATS, messages_) << endingTheta << objectiveValue() << CoinMessageEol; problemStatus_=0; } } else { abort(); } } } reinterpret_cast (this)->finishSolve(0); delete dualRowPivot_; dualRowPivot_ = savePivot; // Restore any saved stuff restoreData(data); if (needToDoSomething) { double saveStartingTheta = startingTheta; // known to be feasible int cleanedUp = 1; while (cleanedUp) { // tweak if (cleanedUp == 1) { if (!reportIncrement) startingTheta = CoinMin(startingTheta + 1.0e-5, saveEndingTheta); else startingTheta = CoinMin(startingTheta + reportIncrement, saveEndingTheta); } else { // restoring to go slowly startingTheta = saveStartingTheta; } // only works if not scaled int i; const double * obj1 = objective(); double * obj2 = copyModel.objective(); const double * lower1 = columnLower_; double * lower2 = copyModel.columnLower(); const double * upper1 = columnUpper_; double * upper2 = copyModel.columnUpper(); for (i = 0; i < numberColumns_; i++) { obj2[i] = obj1[i] + startingTheta * chgObjective[i]; lower2[i] = lower1[i] + startingTheta * chgLower[i]; upper2[i] = upper1[i] + startingTheta * chgUpper[i]; } lower1 = rowLower_; lower2 = copyModel.rowLower(); upper1 = rowUpper_; upper2 = copyModel.rowUpper(); for (i = 0; i < numberRows_; i++) { lower2[i] = lower1[i] + startingTheta * chgLower[i+numberColumns_]; upper2[i] = upper1[i] + startingTheta * chgUpper[i+numberColumns_]; } copyModel.dual(); if (copyModel.problemStatus()) { char line[100]; sprintf(line,"Can not get to theta of %g\n", startingTheta); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; canTryQuick = false; // do slowly to get exact amount // back to last known good if (cleanedUp == 1) cleanedUp = 2; else abort(); } else { // and move stuff back int numberTotal = numberRows_ + numberColumns_; CoinMemcpyN(copyModel.statusArray(), numberTotal, status_); CoinMemcpyN(copyModel.primalColumnSolution(), numberColumns_, columnActivity_); CoinMemcpyN(copyModel.primalRowSolution(), numberRows_, rowActivity_); cleanedUp = 0; } } } delete [] chgLower; delete [] chgUpper; delete [] chgObjective; } perturbation_ = savePerturbation; char line[100]; sprintf(line,"Ending theta %g\n", endingTheta); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; return problemStatus_; } /* Version of parametrics which reads from file See CbcClpParam.cpp for details of format Returns -2 if unable to open file */ int ClpSimplexOther::parametrics(const char * dataFile) { int returnCode=-2; FILE *fp = fopen(dataFile, "r"); char line[200]; if (!fp) { handler_->message(CLP_UNABLE_OPEN, messages_) << dataFile << CoinMessageEol; return -2; } if (!fgets(line, 200, fp)) { sprintf(line,"Empty parametrics file %s?",dataFile); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; fclose(fp); return -2; } 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; double startTheta=0.0; double endTheta=0.0; double intervalTheta=COIN_DBL_MAX; int detail=0; bool good = true; while (good) { good=false; // check ROWS char * comma = strchr(pos, ','); if (!comma) break; *comma = '\0'; if (strcmp(pos,"rows")) break; *comma = ','; pos = comma+1; // check lower theta comma = strchr(pos, ','); if (!comma) break; *comma = '\0'; startTheta = atof(pos); *comma = ','; pos = comma+1; // check upper theta comma = strchr(pos, ','); good=true; if (comma) *comma = '\0'; endTheta = atof(pos); if (comma) { *comma = ','; pos = comma+1; comma = strchr(pos, ','); if (comma) *comma = '\0'; intervalTheta = atof(pos); if (comma) { *comma = ','; pos = comma+1; comma = strchr(pos, ','); if (comma) *comma = '\0'; detail = atoi(pos); if (comma) *comma = ','; } } break; } if (good) { if (startTheta<0.0|| startTheta>endTheta|| intervalTheta<0.0) good=false; if (detail<0||detail>1) good=false; } if (intervalTheta>=endTheta) intervalTheta=0.0; if (!good) { sprintf(line,"Odd first line %s on file %s?",line,dataFile); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; fclose(fp); return -2; } if (!fgets(line, 200, fp)) { sprintf(line,"Not enough records on parametrics file %s?",dataFile); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; fclose(fp); return -2; } double * lowerRowMove = NULL; double * upperRowMove = NULL; double * lowerColumnMove = NULL; double * upperColumnMove = NULL; double * objectiveMove = NULL; char saveLine[200]; saveLine[0]='\0'; std::string headingsRow[] = {"name", "number", "lower", "upper", "rhs"}; int gotRow[] = { -1, -1, -1, -1, -1}; int orderRow[5]; assert(sizeof(gotRow) == sizeof(orderRow)); int nAcross = 0; pos = line; put = line; while (*pos >= ' ' && *pos != '\n') { if (*pos != ' ' && *pos != '\t') { *put = static_cast(tolower(*pos)); put++; } pos++; } *put = '\0'; pos = line; int i; good = true; if (strncmp(line,"column",6)) { while (pos) { char * comma = strchr(pos, ','); if (comma) *comma = '\0'; for (i = 0; i < static_cast (sizeof(gotRow) / sizeof(int)); i++) { if (headingsRow[i] == pos) { if (gotRow[i] < 0) { orderRow[nAcross] = i; gotRow[i] = nAcross++; } else { // duplicate good = false; } break; } } if (i == static_cast (sizeof(gotRow) / sizeof(int))) good = false; if (comma) { *comma = ','; pos = comma + 1; } else { break; } } if (gotRow[0] < 0 && gotRow[1] < 0) good = false; if (gotRow[0] >= 0 && gotRow[1] >= 0) good = false; if (gotRow[0] >= 0 && !lengthNames()) good = false; if (gotRow[4]<0) { if (gotRow[2] < 0 && gotRow[3] >= 0) good = false; else if (gotRow[3] < 0 && gotRow[2] >= 0) good = false; } else if (gotRow[2]>=0||gotRow[3]>=0) { good = false; } if (good) { char ** rowNames = new char * [numberRows_]; int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { rowNames[iRow] = CoinStrdup(rowName(iRow).c_str()); } lowerRowMove = new double [numberRows_]; memset(lowerRowMove,0,numberRows_*sizeof(double)); upperRowMove = new double [numberRows_]; memset(upperRowMove,0,numberRows_*sizeof(double)); int nLine = 0; int nBadLine = 0; int nBadName = 0; while (fgets(line, 200, fp)) { if (!strncmp(line, "ENDATA", 6)|| !strncmp(line, "COLUMN",6)) break; nLine++; iRow = -1; double upper = 0.0; double lower = 0.0; char * pos = line; char * put = line; 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 (orderRow[i]) { // name case 0: // For large problems this could be slow for (iRow = 0; iRow < numberRows_; iRow++) { if (!strcmp(rowNames[iRow], pos)) break; } if (iRow == numberRows_) iRow = -1; break; // number case 1: iRow = atoi(pos); if (iRow < 0 || iRow >= numberRows_) iRow = -1; break; // lower case 2: upper = atof(pos); break; // upper case 3: lower = atof(pos); break; // rhs case 4: lower = atof(pos); upper = lower; break; } if (comma) { *comma = ','; pos = comma + 1; } } if (iRow >= 0) { if (rowLower_[iRow]>-1.0e20) lowerRowMove[iRow] = lower; else lowerRowMove[iRow]=0.0; if (rowUpper_[iRow]<1.0e20) upperRowMove[iRow] = upper; else upperRowMove[iRow] = lower; } else { nBadName++; if(saveLine[0]=='\0') strcpy(saveLine,line); } } sprintf(line,"%d Row fields and %d records", nAcross, nLine); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; if (nBadName) { sprintf(line," ** %d records did not match on name/sequence, first bad %s", nBadName,saveLine); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; returnCode=-1; good=false; } for (iRow = 0; iRow < numberRows_; iRow++) { free(rowNames[iRow]); } delete [] rowNames; } else { sprintf(line,"Duplicate or unknown keyword - or name/number fields wrong"); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; returnCode=-1; good=false; } } if (good&&(!strncmp(line, "COLUMN",6)||!strncmp(line, "column",6))) { if (!fgets(line, 200, fp)) { sprintf(line,"Not enough records on parametrics file %s after COLUMNS?",dataFile); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; fclose(fp); return -2; } std::string headingsColumn[] = {"name", "number", "lower", "upper", "objective"}; saveLine[0]='\0'; int gotColumn[] = { -1, -1, -1, -1, -1}; int orderColumn[5]; assert(sizeof(gotColumn) == sizeof(orderColumn)); nAcross = 0; pos = line; put = line; while (*pos >= ' ' && *pos != '\n') { if (*pos != ' ' && *pos != '\t') { *put = static_cast(tolower(*pos)); put++; } pos++; } *put = '\0'; pos = line; int i; if (strncmp(line,"endata",6)&&good) { while (pos) { char * comma = strchr(pos, ','); if (comma) *comma = '\0'; for (i = 0; i < static_cast (sizeof(gotColumn) / sizeof(int)); i++) { if (headingsColumn[i] == pos) { if (gotColumn[i] < 0) { orderColumn[nAcross] = i; gotColumn[i] = nAcross++; } else { // duplicate good = false; } break; } } if (i == static_cast (sizeof(gotColumn) / sizeof(int))) good = false; if (comma) { *comma = ','; pos = comma + 1; } else { break; } } if (gotColumn[0] < 0 && gotColumn[1] < 0) good = false; if (gotColumn[0] >= 0 && gotColumn[1] >= 0) good = false; if (gotColumn[0] >= 0 && !lengthNames()) good = false; if (good) { char ** columnNames = new char * [numberColumns_]; int iColumn; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { columnNames[iColumn] = CoinStrdup(columnName(iColumn).c_str()); } lowerColumnMove = reinterpret_cast (malloc(numberColumns_ * sizeof(double))); memset(lowerColumnMove,0,numberColumns_*sizeof(double)); upperColumnMove = reinterpret_cast (malloc(numberColumns_ * sizeof(double))); memset(upperColumnMove,0,numberColumns_*sizeof(double)); objectiveMove = reinterpret_cast (malloc(numberColumns_ * sizeof(double))); memset(objectiveMove,0,numberColumns_*sizeof(double)); int nLine = 0; int nBadLine = 0; int nBadName = 0; while (fgets(line, 200, fp)) { if (!strncmp(line, "ENDATA", 6)) break; nLine++; iColumn = -1; double upper = 0.0; double lower = 0.0; double obj =0.0; char * pos = line; char * put = line; 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 (orderColumn[i]) { // name case 0: // For large problems this could be slow 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; // lower case 2: upper = atof(pos); break; // upper case 3: lower = atof(pos); break; // objective case 4: obj = atof(pos); upper = lower; break; } if (comma) { *comma = ','; pos = comma + 1; } } if (iColumn >= 0) { if (columnLower_[iColumn]>-1.0e20) lowerColumnMove[iColumn] = lower; else lowerColumnMove[iColumn]=0.0; if (columnUpper_[iColumn]<1.0e20) upperColumnMove[iColumn] = upper; else upperColumnMove[iColumn] = lower; objectiveMove[iColumn] = obj; } else { nBadName++; if(saveLine[0]=='\0') strcpy(saveLine,line); } } sprintf(line,"%d Column fields and %d records", nAcross, nLine); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; if (nBadName) { sprintf(line," ** %d records did not match on name/sequence, first bad %s", nBadName,saveLine); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; returnCode=-1; good=false; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { free(columnNames[iColumn]); } delete [] columnNames; } else { sprintf(line,"Duplicate or unknown keyword - or name/number fields wrong"); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; returnCode=-1; good=false; } } } returnCode=-1; if (good) { // clean arrays if (lowerRowMove) { bool empty=true; for (int i=0;ilogLevel(); if (detail>0&&!intervalTheta) handler_->setLogLevel(3); else handler_->setLogLevel(1); returnCode = parametrics(startTheta,endTheta,intervalTheta, lowerColumnMove,upperColumnMove, lowerRowMove,upperRowMove, objectiveMove); scalingFlag_ = saveScaling; handler_->setLogLevel(saveLogLevel); } delete [] lowerRowMove; delete [] upperRowMove; delete [] lowerColumnMove; delete [] upperColumnMove; delete [] objectiveMove; fclose(fp); return returnCode; } int ClpSimplexOther::parametricsLoop(parametricsData & paramData,double reportIncrement, const double * lowerChange, const double * upperChange, const double * changeObjective, ClpDataSave & data, bool canTryQuick) { double startingTheta = paramData.startingTheta; double & endingTheta = paramData.endingTheta; // stuff is already at starting // For this crude version just try and go to end double change = 0.0; if (reportIncrement && canTryQuick) { endingTheta = CoinMin(endingTheta, startingTheta + reportIncrement); change = endingTheta - startingTheta; } int numberTotal = numberRows_ + numberColumns_; int i; for ( i = 0; i < numberTotal; i++) { lower_[i] += change * lowerChange[i]; upper_[i] += change * upperChange[i]; switch(getStatus(i)) { case basic: case isFree: case superBasic: break; case isFixed: case atUpperBound: solution_[i] = upper_[i]; break; case atLowerBound: solution_[i] = lower_[i]; break; } cost_[i] += change * changeObjective[i]; } problemStatus_ = -1; // This says whether to restore things etc // startup will have factorized so can skip int factorType = 0; // Start check for cycles progress_.startCheck(); // Say change made on first iteration changeMade_ = 1; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 4; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // may factorize, checks if problem finished statusOfProblemInParametrics(factorType, data); // Say good factorization factorType = 1; if (data.sparseThreshold_) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } // exit if victory declared if (problemStatus_ >= 0 && (canTryQuick || startingTheta>=endingTheta-1.0e-7) ) break; // test for maximum iterations if (hitMaximumIterations()) { problemStatus_ = 3; break; } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } // Do iterations problemStatus_=-1; if (canTryQuick) { double * saveDuals = NULL; reinterpret_cast (this)->whileIterating(saveDuals, 0); } else { whileIterating(paramData, reportIncrement, changeObjective); startingTheta = endingTheta; } } if (!problemStatus_) { theta_ = change + startingTheta; eventHandler_->event(ClpEventHandler::theta); return 0; } else if (problemStatus_ == 10) { return -1; } else { return problemStatus_; } } /* Parametrics The code uses current bounds + theta * change (if change array not NULL) It starts at startingTheta and returns ending theta in endingTheta. If it can not reach input endingTheta return code will be 1 for infeasible, 2 for unbounded, if error on ranges -1, otherwise 0. Event handler may do more On exit endingTheta is maximum reached (can be used for next startingTheta) */ int ClpSimplexOther::parametrics(double startingTheta, double & endingTheta, const double * lowerChangeBound, const double * upperChangeBound, const double * lowerChangeRhs, const double * upperChangeRhs) { int savePerturbation = perturbation_; perturbation_ = 102; // switch off algorithm_ = -1; // extra region int maximumPivots = factorization_->maximumPivots(); int numberDense = factorization_->numberDense(); int length = numberRows_ + numberDense + maximumPivots; assert (!rowArray_[4]); rowArray_[4]=new CoinIndexedVector(length); assert (!rowArray_[5]); rowArray_[5]=new CoinIndexedVector(length); // save data ClpDataSave data = saveData(); int numberTotal = numberRows_ + numberColumns_; int ratio = (2*sizeof(int))/sizeof(double); assert (ratio==1||ratio==2); // allow for unscaled - even if not needed int lengthArrays = 4*numberTotal+(3*numberTotal+2)*ratio+2*numberRows_+1; int unscaledChangesOffset=lengthArrays; // need extra copy of change lengthArrays += numberTotal; /* Save information and modify */ double * saveLower = new double [lengthArrays]; double * saveUpper = new double [lengthArrays]; double * lowerCopy = saveLower+2*numberTotal; double * upperCopy = saveUpper+2*numberTotal; double * lowerChange = saveLower+numberTotal; double * upperChange = saveUpper+numberTotal; double * lowerGap = saveLower+4*numberTotal; double * lowerCoefficient = lowerGap+numberRows_; double * upperGap = saveUpper+4*numberTotal; double * upperCoefficient = upperGap+numberRows_; int * lowerList = (reinterpret_cast(saveLower+4*numberTotal+2*numberRows_))+2; int * upperList = (reinterpret_cast(saveUpper+4*numberTotal+2*numberRows_))+2; int * lowerActive = lowerList+numberTotal+1; int * upperActive = upperList+numberTotal+1; // To mark as odd char * markDone = reinterpret_cast(lowerActive+numberTotal); //memset(markDone,0,numberTotal); int * backwardBasic = upperActive+numberTotal; parametricsData paramData; paramData.lowerChange = lowerChange; paramData.lowerList=lowerList; paramData.upperChange = upperChange; paramData.upperList=upperList; paramData.markDone=markDone; paramData.backwardBasic=backwardBasic; paramData.lowerActive = lowerActive; paramData.lowerGap = lowerGap; paramData.lowerCoefficient = lowerCoefficient; paramData.upperActive = upperActive; paramData.upperGap = upperGap; paramData.upperCoefficient = upperCoefficient; paramData.unscaledChangesOffset = unscaledChangesOffset-numberTotal; paramData.firstIteration=true; // Find theta when bounds will cross over and create arrays memset(lowerChange, 0, numberTotal * sizeof(double)); memset(upperChange, 0, numberTotal * sizeof(double)); if (lowerChangeBound) memcpy(lowerChange,lowerChangeBound,numberColumns_*sizeof(double)); if (upperChangeBound) memcpy(upperChange,upperChangeBound,numberColumns_*sizeof(double)); if (lowerChangeRhs) memcpy(lowerChange+numberColumns_, lowerChangeRhs,numberRows_*sizeof(double)); if (upperChangeRhs) memcpy(upperChange+numberColumns_, upperChangeRhs,numberRows_*sizeof(double)); // clean for (int iRow = 0; iRow < numberRows_; iRow++) { double lower = rowLower_[iRow]; double upper = rowUpper_[iRow]; if (lower<-1.0e30) lowerChange[numberColumns_+iRow]=0.0; if (upper>1.0e30) upperChange[numberColumns_+iRow]=0.0; } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; if (lower<-1.0e30) lowerChange[iColumn]=0.0; if (upper>1.0e30) upperChange[iColumn]=0.0; } // save unscaled version of changes memcpy(saveLower+unscaledChangesOffset,lowerChange,numberTotal*sizeof(double)); memcpy(saveUpper+unscaledChangesOffset,upperChange,numberTotal*sizeof(double)); int nLowerChange=0; int nUpperChange=0; for (int i=0;isetModel(this); #else ClpDualRowPivot * savePivot = NULL; #endif if (!returnCode) { assert (objective_->type()==1); objective_->setType(2); // in case matrix empty returnCode = reinterpret_cast (this)->startupSolve(0, NULL, 0); objective_->setType(1); if (!returnCode) { double saveDualBound=dualBound_; dualBound_=CoinMax(dualBound_,1.0e15); swapped=true; double * temp; memcpy(saveLower,lower_,numberTotal*sizeof(double)); temp=saveLower; saveLower=lower_; lower_=temp; //columnLowerWork_ = lower_; //rowLowerWork_ = lower_ + numberColumns_; memcpy(saveUpper,upper_,numberTotal*sizeof(double)); temp=saveUpper; saveUpper=upper_; upper_=temp; //columnUpperWork_ = upper_; //rowUpperWork_ = upper_ + numberColumns_; if (rowScale_) { // scale saved and change arrays double * lowerChange = lower_+numberTotal; double * upperChange = upper_+numberTotal; double * lowerSave = lowerChange+numberTotal; double * upperSave = upperChange+numberTotal; for (int i=0;i-1.0e20) lowerSave[i] *= multiplier; if (upperSave[i]<1.0e20) upperSave[i] *= multiplier; lowerChange[i] *= multiplier; upperChange[i] *= multiplier; } lowerChange += numberColumns_; upperChange += numberColumns_; lowerSave += numberColumns_; upperSave += numberColumns_; for (int i=0;i-1.0e20) lowerSave[i] *= multiplier; if (upperSave[i]<1.0e20) upperSave[i] *= multiplier; lowerChange[i] *= multiplier; upperChange[i] *= multiplier; } } //double saveEndingTheta = endingTheta; double * saveDuals = NULL; reinterpret_cast (this)->gutsOfDual(0, saveDuals, -1, data); if (numberPrimalInfeasibilities_&&sumPrimalInfeasibilities_<1.0e-4) { // probably can get rid of this if we adjust every change in theta //printf("INFEAS_A %d %g\n",numberPrimalInfeasibilities_, // sumPrimalInfeasibilities_); int pass=100; while(sumPrimalInfeasibilities_) { pass--; if (!pass) break; problemStatus_=-1; for (int iSequence=numberColumns_;iSequenceupper_[iSequence]+1.0e-9) { upperCopy[iSequence]+=value-upper_[iSequence]; upper_[iSequence]=value; } } reinterpret_cast (this)->gutsOfDual(1, saveDuals, -1, data); } } if (!problemStatus_) { if (nLowerChange||nUpperChange) { #ifndef ALL_DANTZIG // Dantzig savePivot = dualRowPivot_; dualRowPivot_ = new ClpDualRowDantzig(); dualRowPivot_->setModel(this); #endif //for (int i=0;imessage(CLP_PARAMETRICS_STATS, messages_) << startingTheta << objectiveValue() << CoinMessageEol; bool canSkipFactorization=true; while (!returnCode) { paramData.startingTheta=startingTheta; paramData.endingTheta=endingTheta; returnCode = parametricsLoop(paramData, data,canSkipFactorization); startingTheta=paramData.startingTheta; endingTheta=paramData.endingTheta; canSkipFactorization=false; if (!returnCode) { //startingTheta = endingTheta; //endingTheta = saveEndingTheta; handler_->message(CLP_PARAMETRICS_STATS, messages_) << startingTheta << objectiveValue() << CoinMessageEol; if (startingTheta >= endingTheta-primalTolerance_ ||problemStatus_==2) break; } else if (returnCode == -1) { // trouble - do external solve abort(); //needToDoSomething = true; } else if (problemStatus_==1) { // can't move any further handler_->message(CLP_PARAMETRICS_STATS, messages_) << endingTheta << objectiveValue() << CoinMessageEol; problemStatus_=0; } } } dualBound_ = saveDualBound; //reinterpret_cast (this)->gutsOfDual(0, saveDuals, -1, data); } else { // check if empty //if (!numberRows_||!matrix_->getNumElements()) { // success #ifdef CLP_USER_DRIVEN //theta_ = endingTheta; //eventHandler_->event(ClpEventHandler::theta); #endif //} } } if (problemStatus_==2) { delete [] ray_; ray_ = new double [numberColumns_]; } if (swapped&&lower_) { double * temp=saveLower; saveLower=lower_; lower_=temp; temp=saveUpper; saveUpper=upper_; upper_=temp; } reinterpret_cast (this)->finishSolve(0); } if (!scalingFlag_) { memcpy(columnLower_,lowerCopy,numberColumns_*sizeof(double)); memcpy(columnUpper_,upperCopy,numberColumns_*sizeof(double)); memcpy(rowLower_,lowerCopy+numberColumns_, numberRows_*sizeof(double)); memcpy(rowUpper_,upperCopy+numberColumns_, numberRows_*sizeof(double)); } else { // extra for unscaled double * unscaledCopy; unscaledCopy = lowerCopy + numberTotal; memcpy(columnLower_,unscaledCopy,numberColumns_*sizeof(double)); memcpy(rowLower_,unscaledCopy+numberColumns_, numberRows_*sizeof(double)); unscaledCopy = upperCopy + numberTotal; memcpy(columnUpper_,unscaledCopy,numberColumns_*sizeof(double)); memcpy(rowUpper_,unscaledCopy+numberColumns_, numberRows_*sizeof(double)); } delete [] saveLower; delete [] saveUpper; #ifdef ALL_DANTZIG if (savePivot) { #endif delete dualRowPivot_; dualRowPivot_ = savePivot; #ifdef ALL_DANTZIG } #endif // Restore any saved stuff restoreData(data); perturbation_ = savePerturbation; delete rowArray_[4]; rowArray_[4]=NULL; delete rowArray_[5]; rowArray_[5]=NULL; char line[100]; sprintf(line,"Ending theta %g\n", endingTheta); handler_->message(CLP_GENERAL,messages_) << line << CoinMessageEol; return problemStatus_; } int ClpSimplexOther::parametricsLoop(parametricsData & paramData, ClpDataSave & data,bool canSkipFactorization) { double & startingTheta = paramData.startingTheta; double & endingTheta = paramData.endingTheta; int numberTotal = numberRows_+numberColumns_; // stuff is already at starting const int * lowerList = paramData.lowerList; const int * upperList = paramData.upperList; problemStatus_ = -1; //double saveEndingTheta=endingTheta; // This says whether to restore things etc // startup will have factorized so can skip int factorType = 0; // Start check for cycles progress_.startCheck(); // Say change made on first iteration changeMade_ = 1; /* Status of problem: 0 - optimal 1 - infeasible 2 - unbounded -1 - iterating -2 - factorization wanted -3 - redo checking without factorization -4 - looks infeasible */ while (problemStatus_ < 0) { int iRow, iColumn; // clear for (iRow = 0; iRow < 6; iRow++) { rowArray_[iRow]->clear(); } for (iColumn = 0; iColumn < 2; iColumn++) { columnArray_[iColumn]->clear(); } // give matrix (and model costs and bounds a chance to be // refreshed (normally null) matrix_->refresh(this); // may factorize, checks if problem finished if (!canSkipFactorization) statusOfProblemInParametrics(factorType, data); canSkipFactorization=false; if (numberPrimalInfeasibilities_) { if (largestPrimalError_>1.0e3&&startingTheta>1.0e10) { // treat as success problemStatus_=0; endingTheta=startingTheta; break; } // probably can get rid of this if we adjust every change in theta //printf("INFEAS %d %g\n",numberPrimalInfeasibilities_, // sumPrimalInfeasibilities_); const double * lowerChange = lower_+numberTotal; const double * upperChange = upper_+numberTotal; const double * startLower = lowerChange+numberTotal; const double * startUpper = upperChange+numberTotal; //startingTheta -= 1.0e-7; int nLowerChange = lowerList[-1]; for (int i = 0; i < nLowerChange; i++) { int iSequence = lowerList[i]; lower_[iSequence] = startLower[iSequence] + startingTheta * lowerChange[iSequence]; } int nUpperChange = upperList[-1]; for (int i = 0; i < nUpperChange; i++) { int iSequence = upperList[i]; upper_[iSequence] = startUpper[iSequence] + startingTheta * upperChange[iSequence]; } // adjust rhs in case dual uses memcpy(columnLower_,lower_,numberColumns_*sizeof(double)); memcpy(rowLower_,lower_+numberColumns_,numberRows_*sizeof(double)); memcpy(columnUpper_,upper_,numberColumns_*sizeof(double)); memcpy(rowUpper_,upper_+numberColumns_,numberRows_*sizeof(double)); if (rowScale_) { for (int i=0;i-1.0e20) columnLower_[i] *= multiplier; if (columnUpper_[i]<1.0e20) columnUpper_[i] *= multiplier; } for (int i=0;i-1.0e20) rowLower_[i] *= multiplier; if (rowUpper_[i]<1.0e20) rowUpper_[i] *= multiplier; } } double * saveDuals = NULL; problemStatus_=-1; ClpObjective * saveObjective = objective_; reinterpret_cast (this)->gutsOfDual(0, saveDuals, -1, data); if (saveObjective!=objective_) { delete objective_; objective_=saveObjective; } int pass=100; double moved=0.0; while(sumPrimalInfeasibilities_) { //printf("INFEAS pass %d %d %g\n",100-pass,numberPrimalInfeasibilities_, // sumPrimalInfeasibilities_); pass--; if (!pass) break; problemStatus_=-1; for (int iSequence=numberColumns_;iSequenceupper_[iSequence]+1.0e-9) { moved += upper_[iSequence]-value; upper_[iSequence]=value; } } if (!moved) { for (int iSequence=0;iSequenceupper_[iSequence]+1.0e-9) { moved += upper_[iSequence]-value; upper_[iSequence]=value; } } } assert (moved); reinterpret_cast (this)->gutsOfDual(1, saveDuals, -1, data); } // adjust //printf("Should adjust - moved %g\n",moved); } // Say good factorization factorType = 1; if (data.sparseThreshold_) { // use default at present factorization_->sparseThreshold(0); factorization_->goSparse(); } // exit if victory declared if (problemStatus_ >= 0 && startingTheta>=endingTheta-1.0e-7 ) break; // test for maximum iterations if (hitMaximumIterations()) { problemStatus_ = 3; break; } #ifdef CLP_USER_DRIVEN // Check event { int status = eventHandler_->event(ClpEventHandler::endOfFactorization); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfFactorization; break; } } #endif // Do iterations problemStatus_=-1; whileIterating(paramData, 0.0, NULL); //startingTheta = endingTheta; //endingTheta = saveEndingTheta; } if (!problemStatus_/*||problemStatus_==2*/) { theta_ = endingTheta; #ifdef CLP_USER_DRIVEN { double saveTheta=theta_; theta_ = endingTheta; int status=eventHandler_->event(ClpEventHandler::theta); if (status>=0&&status<10) { endingTheta=theta_; theta_=saveTheta; problemStatus_=-1; } else { if (status>=10) { problemStatus_=status-10; startingTheta=endingTheta; } theta_=saveTheta; } } #endif return 0; } else if (problemStatus_ == 10) { return -1; } else { return problemStatus_; } } /* Checks if finished. Updates status */ void ClpSimplexOther::statusOfProblemInParametrics(int type, ClpDataSave & saveData) { if (type == 2) { // trouble - go to recovery problemStatus_ = 10; return; } if (problemStatus_ > -3 || factorization_->pivots()) { // factorize // later on we will need to recover from singularities // also we could skip if first time if (type) { // is factorization okay? if (internalFactorize(1)) { // trouble - go to recovery problemStatus_ = 10; return; } } if (problemStatus_ != -4 || factorization_->pivots() > 10) problemStatus_ = -3; } // at this stage status is -3 or -4 if looks infeasible // get primal and dual solutions gutsOfSolution(NULL, NULL); double realDualInfeasibilities = sumDualInfeasibilities_; // If bad accuracy treat as singular if ((largestPrimalError_ > 1.0e15 || largestDualError_ > 1.0e15) && numberIterations_) { // trouble - go to recovery problemStatus_ = 10; return; } else if (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7) { // Can reduce tolerance double newTolerance = CoinMax(0.99 * factorization_->pivotTolerance(), saveData.pivotTolerance_); factorization_->pivotTolerance(newTolerance); } // Check if looping int loop; if (type != 2) loop = progress_.looping(); else loop = -1; if (loop >= 0) { problemStatus_ = loop; //exit if in loop if (!problemStatus_) { // declaring victory numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } else { problemStatus_ = 10; // instead - try other algorithm } return; } else if (loop < -1) { // something may have changed gutsOfSolution(NULL, NULL); } progressFlag_ = 0; //reset progress flag if (handler_->detail(CLP_SIMPLEX_STATUS, messages_) < 100) { handler_->message(CLP_SIMPLEX_STATUS, messages_) << numberIterations_ << objectiveValue(); handler_->printing(sumPrimalInfeasibilities_ > 0.0) << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_; handler_->printing(sumDualInfeasibilities_ > 0.0) << sumDualInfeasibilities_ << numberDualInfeasibilities_; handler_->printing(numberDualInfeasibilitiesWithoutFree_ < numberDualInfeasibilities_) << numberDualInfeasibilitiesWithoutFree_; handler_->message() << CoinMessageEol; } #ifdef CLP_USER_DRIVEN if (sumPrimalInfeasibilities_&&sumPrimalInfeasibilities_<1.0e-7) { int status=eventHandler_->event(ClpEventHandler::slightlyInfeasible); if (status>=0) { // fix up for (int iSequence=0;iSequence=upper_[iSequence]+primalTolerance_) { upper_[iSequence]=value; } } numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } } #endif /* If we are primal feasible and any dual infeasibilities are on free variables then it is better to go to primal */ if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilitiesWithoutFree_ && numberDualInfeasibilities_) { problemStatus_ = 10; return; } // check optimal // give code benefit of doubt if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) { // say optimal (with these bounds etc) numberDualInfeasibilities_ = 0; sumDualInfeasibilities_ = 0.0; numberPrimalInfeasibilities_ = 0; sumPrimalInfeasibilities_ = 0.0; } if (dualFeasible() || problemStatus_ == -4) { progress_.modifyObjective(objectiveValue_ - sumDualInfeasibilities_ * dualBound_); } if (numberPrimalInfeasibilities_) { if (problemStatus_ == -4 || problemStatus_ == -5) { problemStatus_ = 1; // infeasible } } else if (numberDualInfeasibilities_) { // clean up problemStatus_ = 10; } else { problemStatus_ = 0; } lastGoodIteration_ = numberIterations_; if (problemStatus_ < 0) { sumDualInfeasibilities_ = realDualInfeasibilities; // back to say be careful if (sumDualInfeasibilities_) numberDualInfeasibilities_ = 1; } // Allow matrices to be sorted etc int fake = -999; // signal sort matrix_->correctSequence(this, fake, fake); } //static double lastThetaX=0.0; /* This has the flow between re-factorizations Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations +4 accuracy problems */ int ClpSimplexOther::whileIterating(parametricsData & paramData, double /*reportIncrement*/, const double * /*changeObjective*/) { double & startingTheta = paramData.startingTheta; double & endingTheta = paramData.endingTheta; const double * lowerChange = paramData.lowerChange; const double * upperChange = paramData.upperChange; int numberTotal = numberColumns_ + numberRows_; const int * lowerList = paramData.lowerList; const int * upperList = paramData.upperList; //#define CLP_PARAMETRIC_DENSE_ARRAYS 2 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS double * lowerGap = paramData.lowerGap; double * upperGap = paramData.upperGap; double * lowerCoefficient = paramData.lowerCoefficient; double * upperCoefficient = paramData.upperCoefficient; #endif // do basic pointers int * backwardBasic = paramData.backwardBasic; for (int i=0;iclear(); } for (i = 0; i < 2; i++) { columnArray_[i]->clear(); } } // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) factorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0)); else factorization_->relaxAccuracyCheck(1.0); // status stays at -1 while iterating, >=0 finished, -2 to invert // status -3 to go to top without an invert int returnCode = -1; double lastTheta = startingTheta; double useTheta = startingTheta; while (problemStatus_ == -1) { double increaseTheta = CoinMin(endingTheta - lastTheta, 1.0e50); // Get theta for bounds - we know can't crossover int pivotType = nextTheta(1, increaseTheta, paramData, NULL); useTheta += theta_; double change = useTheta - lastTheta; if (paramData.firstIteration) { // redo rhs etc to make as accurate as possible paramData.firstIteration=false; if (change>1.0e-14) { startingTheta=useTheta; lastTheta=startingTheta; change=0.0; // restore rhs const double * saveLower = paramData.lowerChange+2*numberTotal; memcpy(columnLower_,saveLower,numberColumns_*sizeof(double)); memcpy(rowLower_,saveLower+numberColumns_,numberRows_*sizeof(double)); const double * saveUpper = paramData.upperChange+2*numberTotal; memcpy(columnUpper_,saveUpper,numberColumns_*sizeof(double)); memcpy(rowUpper_,saveUpper+numberColumns_,numberRows_*sizeof(double)); paramData.startingTheta=startingTheta; computeRhsEtc(paramData); redoInternalArrays(); // Update solution rowArray_[4]->clear(); for (int i=0;i1.0e-14) { int n; n=lowerList[-1]; for (int i=0;i ( this)->changeBound(iSequence); //ClpTraceDebug (fabs(lower_[iSequence]-newValue)<1.0e-5); } #endif } n=upperList[-1]; for (int i=0;i ( this)->changeBound(iSequence); //ClpTraceDebug (fabs(upper_[iSequence]-newValue)<1.0e-5); } } } sequenceIn_=-1; if (pivotType) { if (useTheta>lastTheta+1.0e-9) { handler_->message(CLP_PARAMETRICS_STATS, messages_) << useTheta << objectiveValue() << CoinMessageEol; lastTheta = useTheta; } problemStatus_ = -2; if (!factorization_->pivots()&&pivotRow_<0) problemStatus_=2; #ifdef CLP_USER_DRIVEN { double saveTheta=theta_; theta_ = endingTheta; if (problemStatus_==2&&theta_>paramData.acceptableMaxTheta) theta_=COIN_DBL_MAX; // we have finished int status=eventHandler_->event(ClpEventHandler::theta); if (status>=0&&status<10) { endingTheta=theta_; problemStatus_=-1; continue; } else { if (status>=10) problemStatus_=status-10; if (status<0) startingTheta = useTheta; } theta_=saveTheta; } #else startingTheta = useTheta; #endif return 4; } // choose row to go out //reinterpret_cast ( this)->dualRow(-1); if (pivotRow_ >= 0) { // we found a pivot row if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) { handler_->message(CLP_SIMPLEX_PIVOTROW, messages_) << pivotRow_ << CoinMessageEol; } // check accuracy of weights dualRowPivot_->checkAccuracy(); // do ratio test for normal iteration double bestPossiblePivot = bestPivot(); if (sequenceIn_ >= 0) { // normal iteration // update the incoming column double btranAlpha = -alpha_ * directionOut_; // for check #ifndef COIN_FAC_NEW unpackPacked(rowArray_[1]); #else unpack(rowArray_[1]); #endif // and update dual weights (can do in parallel - with extra array) rowArray_[2]->clear(); alpha_ = dualRowPivot_->updateWeights(rowArray_[0], rowArray_[2], rowArray_[3], rowArray_[1]); // see if update stable #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_); #endif double checkValue = 1.0e-7; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha << alpha_ << CoinMessageEol; // clear arrays rowArray_[4]->clear(); if (factorization_->pivots()) { dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); returnCode = -2; break; } else { // take on more relaxed criterion double test; if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 1.0e-4 * (1.0 + fabs(alpha_)); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) { dualRowPivot_->unrollWeights(); // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; setFlagged(sequenceOut_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha) < 1.0e-8 && numberIterations_ > 100) { //printf("I think should declare infeasible\n"); problemStatus_ = 1; returnCode = 1; break; } continue; } } } // update duals BEFORE replaceColumn so can do updateColumn double objectiveChange = 0.0; // do duals first as variables may flip bounds // rowArray_[0] and columnArray_[0] may have flips // so use rowArray_[3] for work array from here on int nswapped = 0; //rowArray_[0]->cleanAndPackSafe(1.0e-60); //columnArray_[0]->cleanAndPackSafe(1.0e-60); #if CLP_CAN_HAVE_ZERO_OBJ if ((specialOptions_&2097152)==0) { #endif nswapped = reinterpret_cast ( this)->updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[2], theta_, objectiveChange, false); assert (!nswapped); #if CLP_CAN_HAVE_ZERO_OBJ } else { rowArray_[0]->clear(); rowArray_[2]->clear(); columnArray_[0]->clear(); } #endif // which will change basic solution if (nswapped) { abort(); //needs testing factorization_->updateColumn(rowArray_[3], rowArray_[2]); dualRowPivot_->updatePrimalSolution(rowArray_[2], 1.0, objectiveChange); // recompute dualOut_ valueOut_ = solution_[sequenceOut_]; if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } } // amount primal will move double movement = -dualOut_ * directionOut_ / alpha_; // so objective should increase by fabs(dj)*movement // but we already have objective change - so check will be good if (objectiveChange + fabs(movement * dualIn_) < -1.0e-5) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("movement %g, swap change %g, rest %g * %g\n", objectiveChange + fabs(movement * dualIn_), objectiveChange, movement, dualIn_); #endif assert (objectiveChange + fabs(movement * dualIn_) >= -1.0e-5); if(factorization_->pivots()) { // going backwards - factorize dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now returnCode = -2; break; } } CoinAssert(fabs(dualOut_) < 1.0e50); // if stable replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_); // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { problemStatus_ = -2; // factorize now returnCode = -3; } } else if (updateStatus == 2) { // major error dualRowPivot_->unrollWeights(); // later we may need to unwind more e.g. fake bounds if (factorization_->pivots()) { problemStatus_ = -2; // factorize now returnCode = -2; break; } else { // need to reject something char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; setFlagged(sequenceOut_); progress_.clearBadTimes(); lastBadIteration_ = numberIterations_; // say be more cautious rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); // make sure dual feasible // look at all rows and columns double objectiveChange = 0.0; reinterpret_cast ( this)->updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1], 0.0, objectiveChange, true); continue; } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); problemStatus_ = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } #ifdef CLP_PARAMETRIC_DENSE_ARRAYS int * lowerActive = paramData.lowerActive; int * upperActive = paramData.upperActive; #endif // update change vector { double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); assert (!rowArray_[4]->packedMode()); #ifndef COIN_FAC_NEW assert (rowArray_[1]->packedMode()); #else assert (!rowArray_[1]->packedMode()); #endif double pivotValue = rowArray_[4]->denseVector()[pivotRow_]; double multiplier = -pivotValue/alpha_; double * array=rowArray_[4]->denseVector(); #ifdef CLP_PARAMETRIC_DENSE_ARRAYS int lowerN=lowerActive[-1]; int upperN=upperActive[-1]; #endif if (multiplier) { for (int i = 0; i < number; i++) { int iRow = which[i]; #ifndef COIN_FAC_NEW double alpha=multiplier*work[i]; #else double alpha=multiplier*work[iRow]; #endif #ifdef CLP_PARAMETRIC_DENSE_ARRAYS double alpha3 = alpha+array[iRow]; int iSequence = pivotVariable_[iRow]; double oldLower = lowerCoefficient[iRow]; double oldUpper = upperCoefficient[iRow]; if (lower_[iSequence]>-1.0e30) { //lowerGap[iRow]=value-lower_[iSequence]; double alpha2 = alpha3 + lowerChange[iSequence]; if (alpha2>1.0e-8) { lowerCoefficient[iRow]=alpha2; if (!oldLower) lowerActive[lowerN++]=iRow; } else { if (oldLower) lowerCoefficient[iRow]=COIN_DBL_MIN; } } else { if (oldLower) lowerCoefficient[iRow]=COIN_DBL_MIN; } if (upper_[iSequence]<1.0e30) { //upperGap[iRow]=-(value-upper_[iSequence]); double alpha2 = -(alpha3+upperChange[iSequence]); if (alpha2>1.0e-8) { upperCoefficient[iRow]=alpha2; if (!oldUpper) upperActive[upperN++]=iRow; } else { if (oldUpper) upperCoefficient[iRow]=COIN_DBL_MIN; } } else { if (oldUpper) upperCoefficient[iRow]=COIN_DBL_MIN; } #endif rowArray_[4]->quickAdd(iRow,alpha); } } pivotValue = array[pivotRow_]; // we want pivot to be -multiplier rowArray_[4]->quickAdd(pivotRow_,-multiplier-pivotValue); #ifdef CLP_PARAMETRIC_DENSE_ARRAYS assert (lowerN>=0&&lowerN<=numberRows_); lowerActive[-1]=lowerN; upperActive[-1]=upperN; #endif } // update primal solution #if CLP_CAN_HAVE_ZERO_OBJ if ((specialOptions_&2097152)!=0) theta_=0.0; #endif if (theta_ < 0.0) { #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("negative theta %g\n", theta_); #endif theta_ = 0.0; } // do actual flips reinterpret_cast ( this)->flipBounds(rowArray_[0], columnArray_[0]); //rowArray_[1]->expand(); #ifndef CLP_PARAMETRIC_DENSE_ARRAYS dualRowPivot_->updatePrimalSolution(rowArray_[1], movement, objectiveChange); #else // do by hand { double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); int i; if (rowArray_[1]->packedMode()) { for (i = 0; i < number; i++) { int iRow = which[i]; int iSequence = pivotVariable_[iRow]; double value = solution_[iSequence]; double change = movement * work[i]; value -= change; if (lower_[iSequence]>-1.0e30) lowerGap[iRow]=value-lower_[iSequence]; if (upper_[iSequence]<1.0e30) upperGap[iRow]=-(value-upper_[iSequence]); solution_[iSequence] = value; objectiveChange -= change * cost_[iSequence]; work[i] = 0.0; } } else { for (i = 0; i < number; i++) { int iRow = which[i]; int iSequence = pivotVariable_[iRow]; double value = solution_[iSequence]; double change = movement * work[iRow]; value -= change; solution_[iSequence] = value; objectiveChange -= change * cost_[iSequence]; work[iRow] = 0.0; } } rowArray_[1]->setNumElements(0); } #endif // modify dualout dualOut_ /= alpha_; dualOut_ *= -directionOut_; //setStatus(sequenceIn_,basic); dj_[sequenceIn_] = 0.0; //double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound valueIn_ = upperIn_ + dualOut_; } else { // as if from lower bound valueIn_ = lowerIn_ + dualOut_; } objectiveChange = 0.0; #if CLP_CAN_HAVE_ZERO_OBJ if ((specialOptions_&2097152)==0) { #endif for (int i=0;i 0) { valueOut_ = lowerOut_; dj_[sequenceOut_] = theta_; #if CLP_CAN_HAVE_ZERO_OBJ>1 #ifdef COIN_REUSE_RANDOM if ((specialOptions_&2097152)!=0) { dj_[sequenceOut_] = 1.0e-9*(1.0+CoinDrand48());; } #endif #endif } else { valueOut_ = upperOut_; dj_[sequenceOut_] = -theta_; #if CLP_CAN_HAVE_ZERO_OBJ>1 #ifdef COIN_REUSE_RANDOM if ((specialOptions_&2097152)!=0) { dj_[sequenceOut_] = -1.0e-9*(1.0+CoinDrand48());; } #endif #endif } solution_[sequenceOut_] = valueOut_; int whatNext = housekeeping(objectiveChange); reinterpret_cast(this)->originalBound(sequenceIn_); assert (backwardBasic[sequenceOut_]==pivotRow_); backwardBasic[sequenceOut_]=-1; backwardBasic[sequenceIn_]=pivotRow_; #ifdef CLP_PARAMETRIC_DENSE_ARRAYS double value = solution_[sequenceIn_]; double alpha = rowArray_[4]->denseVector()[pivotRow_]; double oldLower = lowerCoefficient[pivotRow_]; double oldUpper = upperCoefficient[pivotRow_]; if (lower_[sequenceIn_]>-1.0e30) { lowerGap[pivotRow_]=value-lower_[sequenceIn_]; double alpha2 = alpha + lowerChange[sequenceIn_]; if (alpha2>1.0e-8) { lowerCoefficient[pivotRow_]=alpha2; if (!oldLower) { int lowerN=lowerActive[-1]; assert (lowerN>=0&&lowerN1.0e-8) { upperCoefficient[pivotRow_]=alpha2; if (!oldUpper) { int upperN=upperActive[-1]; assert (upperN>=0&&upperNmessage(CLP_PARAMETRICS_STATS2, messages_) << useTheta << objectiveValue() << in << out << CoinMessageEol; } if (useTheta>lastTheta+1.0e-9) { handler_->message(CLP_PARAMETRICS_STATS, messages_) << useTheta << objectiveValue() << CoinMessageEol; lastTheta = useTheta; } // and set bounds correctly originalBound(sequenceIn_,useTheta,lowerChange,upperChange); reinterpret_cast ( this)->changeBound(sequenceOut_); if (whatNext == 1) { problemStatus_ = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; break; } #ifdef CLP_USER_DRIVEN // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 4; break; } } #endif } else { // no incoming column is valid #ifdef CLP_USER_DRIVEN rowArray_[0]->clear(); columnArray_[0]->clear(); theta_ = useTheta; lastTheta = useTheta; int action = eventHandler_->event(ClpEventHandler::noTheta); if (action>=0) { endingTheta=theta_; theta_ = 0.0; //adjust [4] from handler - but //rowArray_[4]->clear(); // temp if (action>=0&&action<10) problemStatus_=-1; // carry on else if (action==15) problemStatus_ =5; // say stopped returnCode = 1; if (action==0||action>=10) break; else continue; } else { theta_ = 0.0; } #endif pivotRow_ = -1; #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no column pivot\n"); #endif if (factorization_->pivots() < 10) { // If we have just factorized and infeasibility reasonable say infeas if (((specialOptions_ & 4096) != 0 || bestPossiblePivot < 1.0e-11) && dualBound_ > 1.0e8) { if (valueOut_ > upperOut_ + 1.0e-3 || valueOut_ < lowerOut_ - 1.0e-3 || (specialOptions_ & 64) == 0) { // say infeasible problemStatus_ = 1; // unless primal feasible!!!! //printf("%d %g %d %g\n",numberPrimalInfeasibilities_,sumPrimalInfeasibilities_, // numberDualInfeasibilities_,sumDualInfeasibilities_); if (numberDualInfeasibilities_) problemStatus_ = 10; rowArray_[0]->clear(); columnArray_[0]->clear(); } } // If special option set - put off as long as possible if ((specialOptions_ & 64) == 0) { problemStatus_ = -4; //say looks infeasible } else { // flag char x = isColumn(sequenceOut_) ? 'C' : 'R'; handler_->message(CLP_SIMPLEX_FLAG, messages_) << x << sequenceWithin(sequenceOut_) << CoinMessageEol; setFlagged(sequenceOut_); if (!factorization_->pivots()) { rowArray_[0]->clear(); columnArray_[0]->clear(); continue; } } } rowArray_[0]->clear(); columnArray_[0]->clear(); returnCode = 1; break; } } else { // no pivot row #ifdef CLP_USER_DRIVEN { double saveTheta=theta_; theta_ = endingTheta; int status=eventHandler_->event(ClpEventHandler::theta); if (status>=0&&status<10) { endingTheta=theta_; theta_=saveTheta; continue; } else { theta_=saveTheta; } } #endif #ifdef CLP_DEBUG if (handler_->logLevel() & 32) printf("** no row pivot\n"); #endif int numberPivots = factorization_->pivots(); bool specialCase; int useNumberFake; returnCode = 0; if (numberPivots < 20 && (specialOptions_ & 2048) != 0 && !numberChanged_ && perturbation_ >= 100 && dualBound_ > 1.0e8) { specialCase = true; // as dual bound high - should be okay useNumberFake = 0; } else { specialCase = false; useNumberFake = numberFake_; } if (!numberPivots || specialCase) { // may have crept through - so may be optimal // check any flagged variables int iRow; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; if (flagged(iPivot)) break; } if (iRow < numberRows_ && numberPivots) { // try factorization returnCode = -2; } if (useNumberFake || numberDualInfeasibilities_) { // may be dual infeasible problemStatus_ = -5; } else { if (iRow < numberRows_) { problemStatus_ = -5; } else { if (numberPivots) { // objective may be wrong objectiveValue_ = innerProduct(cost_, numberColumns_ + numberRows_, solution_); objectiveValue_ += objective_->nonlinearOffset(); objectiveValue_ /= (objectiveScale_ * rhsScale_); if ((specialOptions_ & 16384) == 0) { // and dual_ may be wrong (i.e. for fixed or basic) CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); int iRow; double * array = arrayVector->denseVector(); /* Use dual_ instead of array Even though dual_ is only numberRows_ long this is okay as gets permuted to longer rowArray_[2] */ arrayVector->setDenseVector(dual_); int * index = arrayVector->getIndices(); int number = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int iPivot = pivotVariable_[iRow]; double value = cost_[iPivot]; dual_[iRow] = value; if (value) { index[number++] = iRow; } } arrayVector->setNumElements(number); // Extended duals before "updateTranspose" matrix_->dualExpanded(this, arrayVector, NULL, 0); // Btran basic costs rowArray_[2]->clear(); factorization_->updateColumnTranspose(rowArray_[2], arrayVector); // and return vector arrayVector->setDenseVector(array); } } problemStatus_ = 0; sumPrimalInfeasibilities_ = 0.0; if ((specialOptions_&(1024 + 16384)) != 0) { CoinIndexedVector * arrayVector = rowArray_[1]; arrayVector->clear(); double * rhs = arrayVector->denseVector(); times(1.0, solution_, rhs); bool bad2 = false; int i; for ( i = 0; i < numberRows_; i++) { if (rhs[i] < rowLowerWork_[i] - primalTolerance_ || rhs[i] > rowUpperWork_[i] + primalTolerance_) { bad2 = true; } else if (fabs(rhs[i] - rowActivityWork_[i]) > 1.0e-3) { } rhs[i] = 0.0; } for ( i = 0; i < numberColumns_; i++) { if (solution_[i] < columnLowerWork_[i] - primalTolerance_ || solution_[i] > columnUpperWork_[i] + primalTolerance_) { bad2 = true; } } if (bad2) { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = factorization_->pivots(); forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } } } } } else { problemStatus_ = -3; returnCode = -2; // Force to re-factorize early next time int numberPivots = factorization_->pivots(); forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1); } break; } } startingTheta = lastTheta+theta_; return returnCode; } // Compute new rowLower_ etc (return negative if infeasible - otherwise largest change) double ClpSimplexOther::computeRhsEtc( parametricsData & paramData) { double maxTheta = COIN_DBL_MAX; double largestChange=0.0; double startingTheta = paramData.startingTheta; const double * lowerChange = paramData.lowerChange+ paramData.unscaledChangesOffset; const double * upperChange = paramData.upperChange+ paramData.unscaledChangesOffset; for (int iRow = 0; iRow < numberRows_; iRow++) { double lower = rowLower_[iRow]; double upper = rowUpper_[iRow]; double chgLower = lowerChange[numberColumns_+iRow]; largestChange=CoinMax(largestChange,fabs(chgLower)); double chgUpper = upperChange[numberColumns_+iRow]; largestChange=CoinMax(largestChange,fabs(chgUpper)); if (lower > -1.0e30 && upper < 1.0e30) { if (lower + maxTheta * chgLower > upper + maxTheta * chgUpper) { maxTheta = (upper - lower) / (chgLower - chgUpper); } } lower+=startingTheta*chgLower; upper+=startingTheta*chgUpper; #ifndef CLP_USER_DRIVEN if (lower > upper) { maxTheta = -1.0; break; } #endif rowLower_[iRow]=lower; rowUpper_[iRow]=upper; } for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; double chgLower = lowerChange[iColumn]; largestChange=CoinMax(largestChange,fabs(chgLower)); double chgUpper = upperChange[iColumn]; largestChange=CoinMax(largestChange,fabs(chgUpper)); if (lower > -1.0e30 && upper < 1.0e30) { if (lower + maxTheta * chgLower > upper + maxTheta * chgUpper) { maxTheta = (upper - lower) / (chgLower - chgUpper); } } lower+=startingTheta*chgLower; upper+=startingTheta*chgUpper; #ifndef CLP_USER_DRIVEN if (lower > upper) { maxTheta = -1.0; break; } #endif columnLower_[iColumn]=lower; columnUpper_[iColumn]=upper; } #ifndef CLP_USER_DRIVEN paramData.maxTheta=maxTheta; if (maxTheta<0) largestChange=-1.0; // signal infeasible #else // maxTheta already set /* given largest change element choose acceptable end be safe and make sure difference < 0.1*tolerance */ double acceptableDifference=0.1*primalTolerance_/ CoinMax(largestChange,1.0); paramData.acceptableMaxTheta=maxTheta-acceptableDifference; #endif return largestChange; } // Redo lower_ from rowLower_ etc void ClpSimplexOther::redoInternalArrays() { double * lowerSave = lower_; double * upperSave = upper_; memcpy(lowerSave,columnLower_,numberColumns_*sizeof(double)); memcpy(lowerSave+numberColumns_,rowLower_,numberRows_*sizeof(double)); memcpy(upperSave,columnUpper_,numberColumns_*sizeof(double)); memcpy(upperSave+numberColumns_,rowUpper_,numberRows_*sizeof(double)); if (rowScale_) { // scale arrays for (int i=0;i-1.0e20) lowerSave[i] *= multiplier; if (upperSave[i]<1.0e20) upperSave[i] *= multiplier; } lowerSave += numberColumns_; upperSave += numberColumns_; for (int i=0;i-1.0e20) lowerSave[i] *= multiplier; if (upperSave[i]<1.0e20) upperSave[i] *= multiplier; } } } #if 0 static int zzzzzz=0; int zzzzzzOther=0; #endif // Finds best possible pivot double ClpSimplexOther::bestPivot(bool justColumns) { // Get good size for pivot // Allow first few iterations to take tiny double acceptablePivot = 1.0e-9; if (numberIterations_ > 100) acceptablePivot = 1.0e-8; if (factorization_->pivots() > 10 || (factorization_->pivots() && sumDualInfeasibilities_)) acceptablePivot = 1.0e-5; // if we have iterated be more strict else if (factorization_->pivots() > 5) acceptablePivot = 1.0e-6; // if we have iterated be slightly more strict else if (factorization_->pivots()) acceptablePivot = 1.0e-8; // relax double bestPossiblePivot = 1.0; // get sign for finding row of tableau // normal iteration // create as packed double direction = directionOut_; #ifndef COIN_FAC_NEW rowArray_[0]->createPacked(1, &pivotRow_, &direction); #else rowArray_[0]->createOneUnpackedElement(pivotRow_, direction); #endif factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]); // put row of tableau in rowArray[0] and columnArray[0] matrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[3], columnArray_[0]); sequenceIn_=-1; if (justColumns) rowArray_[0]->clear(); // do ratio test for normal iteration bestPossiblePivot = reinterpret_cast ( this)->dualColumn(rowArray_[0], columnArray_[0], columnArray_[1], rowArray_[3], acceptablePivot, NULL); return bestPossiblePivot; } // Computes next theta and says if objective or bounds (0= bounds, 1 objective, -1 none) int ClpSimplexOther::nextTheta(int /*type*/, double maxTheta, parametricsData & paramData, const double * /*changeObjective*/) { const double * lowerChange = paramData.lowerChange; const double * upperChange = paramData.upperChange; const int * lowerList = paramData.lowerList; const int * upperList = paramData.upperList; int iSequence; bool toLower = false; //assert (type==1); // may need to decide based on model? bool needFullUpdate = rowArray_[4]->getNumElements()==0; double * array = rowArray_[4]->denseVector(); //rowArray_[4]->checkClean(); const int * row = matrix_->getIndices(); const int * columnLength = matrix_->getVectorLengths(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const double * elementByColumn = matrix_->getElements(); #if 0 double tempArray[5000]; bool checkIt=false; if (factorization_->pivots()&&!needFullUpdate&&sequenceIn_<0) { memcpy(tempArray,array,numberRows_*sizeof(double)); checkIt=true; needFullUpdate=true; } #endif #ifdef CLP_PARAMETRIC_DENSE_ARRAYS double * lowerGap = paramData.lowerGap; double * upperGap = paramData.upperGap; double * lowerCoefficient = paramData.lowerCoefficient; double * upperCoefficient = paramData.upperCoefficient; int * lowerActive=paramData.lowerActive; int * upperActive=paramData.upperActive; #endif if (!factorization_->pivots()||needFullUpdate) { //zzzzzz=0; rowArray_[4]->clear(); // get change if (!rowScale_) { int n; n=lowerList[-2]; int i; for (i=0;iquickAdd(row[j], elementByColumn[j]*value); } } } n=lowerList[-1]; const double * change = lowerChange+numberColumns_; for (;i=0); if (getRowStatus(iSequence)==atLowerBound) { double value=change[iSequence]; rowArray_[4]->quickAdd(iSequence, -value); } } n=upperList[-2]; for (i=0;iquickAdd(row[j], elementByColumn[j]*value); } } } n=upperList[-1]; change = upperChange+numberColumns_; for (;i=0); if (getRowStatus(iSequence)==atUpperBound) { double value=change[iSequence]; rowArray_[4]->quickAdd(iSequence, -value); } } } else { int n; n=lowerList[-2]; int i; for (i=0;iquickAdd(iRow, elementByColumn[j]*scale * rowScale_[iRow]*value); } } } n=lowerList[-1]; const double * change = lowerChange+numberColumns_; for (;i=0); if (getRowStatus(iSequence)==atLowerBound) { double value=change[iSequence]; rowArray_[4]->quickAdd(iSequence, -value); } } n=upperList[-2]; for (i=0;iquickAdd(iRow, elementByColumn[j]*scale * rowScale_[iRow]*value); } } } n=upperList[-1]; change = upperChange+numberColumns_; for (;i=0); if (getRowStatus(iSequence)==atUpperBound) { double value=change[iSequence]; rowArray_[4]->quickAdd(iSequence, -value); } } } // ftran it factorization_->updateColumn(rowArray_[0], rowArray_[4]); #if 0 if (checkIt) { for (int i=0;i 1.0e-8&&lower_[iSequence]>-1.0e30) { double currentLower = lower_[iSequence]; ClpTraceDebug (currentSolution >= currentLower - 100.0*primalTolerance_); double gap=currentSolution-currentLower; lowerGap[iRow]=gap; lowerCoefficient[iRow]=thetaCoefficientLower; lowerActive[lowerN++]=iRow; //} else { //lowerCoefficient[iRow]=0.0; } if (thetaCoefficientUpper < -1.0e-8&&upper_[iSequence]<1.0e30) { double currentUpper = upper_[iSequence]; ClpTraceDebug (currentSolution <= currentUpper + 100.0*primalTolerance_); double gap2=-(currentSolution-currentUpper); //positive upperGap[iRow]=gap2; upperCoefficient[iRow]=-thetaCoefficientUpper; upperActive[upperN++]=iRow; } } assert (lowerN>=0&&lowerN<=numberRows_); lowerActive[-1]=lowerN; upperActive[-1]=upperN; #endif } else if (sequenceIn_>=0) { //assert (sequenceIn_>=0); assert (sequenceOut_>=0); assert (sequenceIn_!=sequenceOut_); double change = (directionIn_>0) ? -lowerChange[sequenceIn_] : -upperChange[sequenceIn_]; int needed=0; assert (!rowArray_[5]->getNumElements()); if (change) { if (sequenceIn_quickAdd(row[i], elementByColumn[i]*change); } } else { // apply scaling double scale = columnScale_[sequenceIn_]; for (CoinBigIndex i = columnStart[sequenceIn_]; i < columnStart[sequenceIn_] + columnLength[sequenceIn_]; i++) { int iRow = row[i]; rowArray_[5]->quickAdd(iRow, elementByColumn[i]*scale * rowScale_[iRow]*change); } } } else { rowArray_[5]->insert(sequenceIn_-numberColumns_,-change); } needed++; } if (getStatus(sequenceOut_)==atLowerBound) change=lowerChange[sequenceOut_]; else change=upperChange[sequenceOut_]; if (change) { if (sequenceOut_quickAdd(row[i], elementByColumn[i]*change); } } else { // apply scaling double scale = columnScale_[sequenceOut_]; for (CoinBigIndex i = columnStart[sequenceOut_]; i < columnStart[sequenceOut_] + columnLength[sequenceOut_]; i++) { int iRow = row[i]; rowArray_[5]->quickAdd(iRow, elementByColumn[i]*scale * rowScale_[iRow]*change); } } } else { rowArray_[5]->quickAdd(sequenceOut_-numberColumns_,-change); } needed++; } //printf("seqin %d seqout %d needed %d\n", // sequenceIn_,sequenceOut_,needed); if (needed) { // ftran it factorization_->updateColumn(rowArray_[0], rowArray_[5]); // add double * array5 = rowArray_[5]->denseVector(); int * index5 = rowArray_[5]->getIndices(); int number5 = rowArray_[5]->getNumElements(); #ifdef CLP_PARAMETRIC_DENSE_ARRAYS int lowerN=lowerActive[-1]; int upperN=upperActive[-1]; int nIn4=rowArray_[4]->getNumElements(); int * index4 = rowArray_[4]->getIndices(); #endif for (int i = 0; i < number5; i++) { int iPivot = index5[i]; #ifndef CLP_PARAMETRIC_DENSE_ARRAYS rowArray_[4]->quickAdd(iPivot,array5[iPivot]); #else /* later for sparse - modify here */ int iSequence = pivotVariable_[iPivot]; double currentSolution = solution_[iSequence]; double currentAlpha = array[iPivot]; double alpha5 = array5[iPivot]; double alpha = currentAlpha+alpha5; if (currentAlpha) { if (alpha) { array[iPivot] = alpha; } else { array[iPivot] = COIN_DBL_MIN; } } else { index4[nIn4++] = iPivot; array[iPivot] = alpha; } double thetaCoefficientLower = lowerChange[iSequence] + alpha; double thetaCoefficientUpper = upperChange[iSequence] + alpha; double oldLower = lowerCoefficient[iPivot]; double oldUpper = upperCoefficient[iPivot]; if (thetaCoefficientLower > 1.0e-8&&lower_[iSequence]>-1.0e30) { double currentLower = lower_[iSequence]; ClpTraceDebug (currentSolution >= currentLower - 100.0*primalTolerance_); double gap=currentSolution-currentLower; lowerGap[iPivot]=gap; lowerCoefficient[iPivot]=thetaCoefficientLower; if (!oldLower) lowerActive[lowerN++]=iPivot; } else { if (oldLower) lowerCoefficient[iPivot]=COIN_DBL_MIN; } if (thetaCoefficientUpper < -1.0e-8&&upper_[iSequence]<1.0e30) { double currentUpper = upper_[iSequence]; ClpTraceDebug (currentSolution <= currentUpper + 100.0*primalTolerance_); double gap2=-(currentSolution-currentUpper); //positive upperGap[iPivot]=gap2; upperCoefficient[iPivot]=-thetaCoefficientUpper; if (!oldUpper) upperActive[upperN++]=iPivot; } else { if (oldUpper) upperCoefficient[iPivot]=COIN_DBL_MIN; } #endif array5[iPivot]=0.0; } rowArray_[5]->setNumElements(0); #ifdef CLP_PARAMETRIC_DENSE_ARRAYS rowArray_[4]->setNumElements(nIn4); assert (lowerN>=0&&lowerN<=numberRows_); lowerActive[-1]=lowerN; upperActive[-1]=upperN; #endif } } const int * index = rowArray_[4]->getIndices(); int number = rowArray_[4]->getNumElements(); #define TESTXX 0 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX int * markDone = reinterpret_cast(paramData.markDone); int nToZero=(numberRows_+numberColumns_+COIN_ANY_BITS_PER_INT-1)>>COIN_ANY_SHIFT_PER_INT; memset(markDone,0,nToZero*sizeof(int)); const int * backwardBasic = paramData.backwardBasic; #endif // first ones with alpha double theta1=maxTheta; int pivotRow1=-1; #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX int pivotRow2=-1; double theta2=maxTheta; #endif #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX for (int i=0;i> COIN_ANY_SHIFT_PER_INT; int bit = iSequence & COIN_ANY_MASK_PER_INT; markDone[word] |= ( 1 << bit ); // solution value will be sol - theta*alpha // bounds will be bounds + change *theta double currentSolution = solution_[iSequence]; double alpha = array[iPivot]; double thetaCoefficientLower = lowerChange[iSequence] + alpha; double thetaCoefficientUpper = upperChange[iSequence] + alpha; if (thetaCoefficientLower > 1.0e-8) { double currentLower = lower_[iSequence]; ClpTraceDebug (currentSolution >= currentLower - 100.0*primalTolerance_); assert (currentSolution >= currentLower - 100.0*primalTolerance_); double gap=currentSolution-currentLower; if (thetaCoefficientLower*theta1>gap) { theta1 = gap/thetaCoefficientLower; //toLower=true; pivotRow1=iPivot; } } if (thetaCoefficientUpper < -1.0e-8) { double currentUpper = upper_[iSequence]; ClpTraceDebug (currentSolution <= currentUpper + 100.0*primalTolerance_); assert (currentSolution <= currentUpper + 100.0*primalTolerance_); double gap2=currentSolution-currentUpper; //negative if (thetaCoefficientUpper*theta2> COIN_ANY_SHIFT_PER_INT; int bit = iSequence & COIN_ANY_MASK_PER_INT; if (getColumnStatus(iSequence)==basic&&(markDone[word]&(1<= currentLower - 100.0*primalTolerance_); double thetaCoefficient = lowerChange[iSequence]; if (thetaCoefficient > 0.0) { double gap=currentSolution-currentLower; if (thetaCoefficient*theta1>gap) { theta1 = gap/thetaCoefficient; //toLower=true; pivotRow1 = backwardBasic[iSequence]; } } } } nLook=upperList[-1]; for (int i=0;i> COIN_ANY_SHIFT_PER_INT; int bit = iSequence & COIN_ANY_MASK_PER_INT; if (getColumnStatus(iSequence)==basic&&(markDone[word]&(1< 1.0e-8&&lower_[iSequence]>-1.0e30) { assert(fabs(checkArray[iRow]-thetaCoefficient)<1.0e-5); if(fabs(checkArray[iRow]-thetaCoefficient)>1.0e-5) { abort(); } } else { assert (fabs(checkArray[iRow])<1.0e-12); if (fabs(checkArray[iRow])>1.0e-12) { abort(); } } checkArray[iRow]=0.0; } for (int i=0;i 1.0e-8&&upper_[iSequence]<1.0e30) { assert(fabs(checkArray[iRow]-thetaCoefficient)<1.0e-5); if(fabs(checkArray[iRow]-thetaCoefficient)>1.0e-5) { abort(); } } else { assert (fabs(checkArray[iRow])<1.0e-12); if (fabs(checkArray[iRow])>1.0e-12) { abort(); } } checkArray[iRow]=0.0; } for (int i=0;igap-1.0e-8); if (lowerC*theta3gap&&lowerC!=COIN_DBL_MIN) { theta3 = gap/lowerC; pivotRow3=iRow; } } int pivotRow4=pivotRow3; double theta4=theta3; int upperN=upperActive[-1]; for (int i=0;igap-1.0e-8); if (upperC*theta3gap&&upperC!=COIN_DBL_MIN) { theta4 = gap/upperC; pivotRow4=iRow; } } bool toLower3; if (theta41.0e-8) abort(); if (toLower!=toLower3||pivotRow_!=pivotRow3) { printf("bad piv - good %d %g %s, bad %d %g %s\n",pivotRow_,theta_,toLower ? "toLower" : "toUpper", pivotRow3,theta3,toLower3 ? "toLower" : "toUpper"); //zzzzzz++; if (true/*zzzzzz>zzzzzzOther*/) { printf("Swapping\n"); pivotRow_=pivotRow3; theta_=theta3; toLower=toLower3; } } #endif #endif #else #if 0 //CLP_PARAMETRIC_DENSE_ARRAYS==2 { double * checkArray = new double[numberRows_]; memcpy(checkArray,lowerCoefficient,numberRows_*sizeof(double)); int lowerN=lowerActive[-1]; for (int i=0;igap&&lowerC!=COIN_DBL_MIN) { theta1 = gap/lowerC; pivotRow1=iRow; } } pivotRow_=pivotRow1; theta_=theta1; int upperN=upperActive[-1]; for (int i=0;igap&&upperC!=COIN_DBL_MIN) { theta1 = gap/upperC; pivotRow1=iRow; } } if (theta11.0e-15) { // update solution for (int iRow = 0; iRow < number; iRow++) { int iPivot = index[iRow]; iSequence = pivotVariable_[iPivot]; // solution value will be sol - theta*alpha double alpha = array[iPivot]; double currentSolution = solution_[iSequence] - theta_ * alpha; solution_[iSequence] =currentSolution; #ifdef CLP_PARAMETRIC_DENSE_ARRAYS if (lower_[iSequence]>-1.0e30) lowerGap[iPivot]=currentSolution-lower_[iSequence]; if (upper_[iSequence]<1.0e30) upperGap[iPivot]=-(currentSolution-upper_[iSequence]); #endif } } #ifdef CLP_PARAMETRIC_DENSE_ARRAYS if (pivotRow_>=0&&false) { double oldValue = upperCoefficient[pivotRow_]; double value = array[pivotRow_]; if (value) { if (!oldValue) { int upperN=upperActive[-1]; assert (upperN>=0&&upperN= 0) { sequenceOut_ = pivotVariable_[pivotRow_]; valueOut_ = solution_[sequenceOut_]; lowerOut_ = lower_[sequenceOut_]+theta_*lowerChange[sequenceOut_]; upperOut_ = upper_[sequenceOut_]+theta_*upperChange[sequenceOut_]; if (!toLower) { directionOut_ = -1; dualOut_ = valueOut_ - upperOut_; } else { directionOut_ = 1; dualOut_ = lowerOut_ - valueOut_; } return 0; } else { //theta_=0.0; return -1; } } // Restores bound to original bound void ClpSimplexOther::originalBound(int iSequence, double theta, const double * lowerChange, const double * upperChange) { if (getFakeBound(iSequence) != noFake) { numberFake_--; setFakeBound(iSequence, noFake); if (iSequence >= numberColumns_) { // rows int iRow = iSequence - numberColumns_; rowLowerWork_[iRow] = rowLower_[iRow]+theta*lowerChange[iSequence]; rowUpperWork_[iRow] = rowUpper_[iRow]+theta*upperChange[iSequence]; if (rowScale_) { if (rowLowerWork_[iRow] > -1.0e50) rowLowerWork_[iRow] *= rowScale_[iRow] * rhsScale_; if (rowUpperWork_[iRow] < 1.0e50) rowUpperWork_[iRow] *= rowScale_[iRow] * rhsScale_; } else if (rhsScale_ != 1.0) { if (rowLowerWork_[iRow] > -1.0e50) rowLowerWork_[iRow] *= rhsScale_; if (rowUpperWork_[iRow] < 1.0e50) rowUpperWork_[iRow] *= rhsScale_; } } else { // columns columnLowerWork_[iSequence] = columnLower_[iSequence]+theta*lowerChange[iSequence]; columnUpperWork_[iSequence] = columnUpper_[iSequence]+theta*upperChange[iSequence]; if (rowScale_) { double multiplier = 1.0 * inverseColumnScale_[iSequence]; if (columnLowerWork_[iSequence] > -1.0e50) columnLowerWork_[iSequence] *= multiplier * rhsScale_; if (columnUpperWork_[iSequence] < 1.0e50) columnUpperWork_[iSequence] *= multiplier * rhsScale_; } else if (rhsScale_ != 1.0) { if (columnLowerWork_[iSequence] > -1.0e50) columnLowerWork_[iSequence] *= rhsScale_; if (columnUpperWork_[iSequence] < 1.0e50) columnUpperWork_[iSequence] *= rhsScale_; } } } } /* 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 ClpSimplexOther::expandKnapsack(int knapsackRow, int & numberOutput, double * buildObj, CoinBigIndex * buildStart, int * buildRow, double * buildElement, int reConstruct) const { int iRow; int iColumn; // Get column copy CoinPackedMatrix * columnCopy = matrix(); // Get a row copy in standard format CoinPackedMatrix matrixByRow; matrixByRow.reverseOrderedCopyOf(*columnCopy); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); CoinBigIndex j; int * whichColumn = new int [numberColumns_]; int * whichRow = new int [numberRows_]; int numJ = 0; // Get what other columns can compensate for double * lo = new double [numberRows_]; double * high = new double [numberRows_]; { // Use to get tight column bounds ClpSimplex tempModel(*this); tempModel.tightenPrimalBounds(0.0, 0, true); // Now another model without knapsacks int nCol = 0; for (iRow = 0; iRow < numberRows_; iRow++) { whichRow[iRow] = iRow; } for (iColumn = 0; iColumn < numberColumns_; iColumn++) whichColumn[iColumn] = -1; for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) { int iColumn = column[j]; if (columnUpper_[iColumn] > columnLower_[iColumn]) { whichColumn[iColumn] = 0; } else { assert (!columnLower_[iColumn]); // fix later } } for (iColumn = 0; iColumn < numberColumns_; iColumn++) { if (whichColumn[iColumn] < 0) whichColumn[nCol++] = iColumn; } ClpSimplex tempModel2(&tempModel, numberRows_, whichRow, nCol, whichColumn, false, false, false); // Row copy CoinPackedMatrix matrixByRow; matrixByRow.reverseOrderedCopyOf(*tempModel2.matrix()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); const double * columnLower = tempModel2.getColLower(); const double * columnUpper = tempModel2.getColUpper(); for (iRow = 0; iRow < numberRows_; iRow++) { lo[iRow] = -COIN_DBL_MAX; high[iRow] = COIN_DBL_MAX; if (rowLower_[iRow] > -1.0e20 || rowUpper_[iRow] < 1.0e20) { // possible row int infiniteUpper = 0; int infiniteLower = 0; double maximumUp = 0.0; double maximumDown = 0.0; CoinBigIndex rStart = rowStart[iRow]; CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow]; CoinBigIndex j; // Compute possible lower and upper ranges for (j = rStart; j < rEnd; ++j) { double value = elementByRow[j]; iColumn = column[j]; if (value > 0.0) { if (columnUpper[iColumn] >= 1.0e20) { ++infiniteUpper; } else { maximumUp += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -1.0e20) { ++infiniteLower; } else { maximumDown += columnLower[iColumn] * value; } } else if (value < 0.0) { if (columnUpper[iColumn] >= 1.0e20) { ++infiniteLower; } else { maximumDown += columnUpper[iColumn] * value; } if (columnLower[iColumn] <= -1.0e20) { ++infiniteUpper; } else { maximumUp += columnLower[iColumn] * value; } } } // Build in a margin of error maximumUp += 1.0e-8 * fabs(maximumUp) + 1.0e-7; maximumDown -= 1.0e-8 * fabs(maximumDown) + 1.0e-7; // we want to save effective rhs double up = (infiniteUpper) ? COIN_DBL_MAX : maximumUp; double down = (infiniteLower) ? -COIN_DBL_MAX : maximumDown; if (up == COIN_DBL_MAX || rowLower_[iRow] == -COIN_DBL_MAX) { // However low we go it doesn't matter lo[iRow] = -COIN_DBL_MAX; } else { // If we go below this then can not be feasible lo[iRow] = rowLower_[iRow] - up; } if (down == -COIN_DBL_MAX || rowUpper_[iRow] == COIN_DBL_MAX) { // However high we go it doesn't matter high[iRow] = COIN_DBL_MAX; } else { // If we go above this then can not be feasible high[iRow] = rowUpper_[iRow] - down; } } } } numJ = 0; for (iColumn = 0; iColumn < numberColumns_; iColumn++) whichColumn[iColumn] = -1; int * markRow = new int [numberRows_]; for (iRow = 0; iRow < numberRows_; iRow++) markRow[iRow] = 1; for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) { int iColumn = column[j]; if (columnUpper_[iColumn] > columnLower_[iColumn]) { whichColumn[iColumn] = numJ; numJ++; } } /* mark rows -n in knapsack and n other variables 1 no entries n+1000 not involved in knapsack but n entries 0 only in knapsack */ for (iRow = 0; iRow < numberRows_; iRow++) { int type = 1; for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; if (whichColumn[iColumn] >= 0) { if (type == 1) { type = 0; } else if (type > 0) { assert (type > 1000); type = -(type - 1000); } } else if (type == 1) { type = 1001; } else if (type < 0) { type --; } else if (type == 0) { type = -1; } else { assert (type > 1000); type++; } } markRow[iRow] = type; if (type < 0 && type > -30 && false) printf("markrow on row %d is %d\n", iRow, markRow[iRow]); } int * bound = new int [numberColumns_+1]; int * stack = new int [numberColumns_+1]; int * flip = new int [numberColumns_+1]; double * offset = new double[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 = rowLower_[knapsackRow]; double maxSize = rowUpper_[knapsackRow]; double knapsackOffset = 0.0; for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) { int iColumn = column[j]; double lowerColumn = columnLower_[iColumn]; double upperColumn = columnUpper_[iColumn]; if (lowerColumn == upperColumn) continue; 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); if (elementByRow[j] > 0.0) { flip[numJ] = 1; offset[numJ] = lowerColumn; size[numJ++] = elementByRow[j]; } else { flip[numJ] = -1; offset[numJ] = upperColumn; size[numJ++] = -elementByRow[j]; lowerColumn = upperColumn; } knapsackOffset += elementByRow[j] * lowerColumn; } int jRow; for (iRow = 0; iRow < numberRows_; iRow++) whichRow[iRow] = iRow; ClpSimplex smallModel(this, 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; // would use for fixed? CoinZeroN(rhsOffset, numberRows_); double * rowActivity = smallModel.primalRowSolution(); CoinZeroN(rowActivity, numberRows_); maxSize -= knapsackOffset; minSize -= knapsackOffset; // now generate int i; int iStack = numJ; for (i = 0; i < numJ; i++) { stack[i] = 0; } double tooMuch = 10.0 * maxSize + 10000; stack[numJ] = 1; size[numJ] = tooMuch; bound[numJ] = 0; double sum = tooMuch; // allow for all zero being OK stack[numJ-1] = -1; sum -= size[numJ-1]; 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 = 0.0; CoinZeroN(rowActivity, numberRows_); for (iColumn = 0; iColumn < numJ; iColumn++) { int iValue = stack[iColumn]; if (iValue > bound[iColumn]) { good = false; break; } else { double realValue = offset[iColumn] + flip[iColumn] * iValue; if (realValue) { obj += objective[iColumn] * realValue; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { double value = element[j] * realValue; 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 > high[kRow] || value < lo[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]; double realValue = offset[iColumn] + flip[iColumn] * iValue; if (realValue) { buildRow[nelCreate] = whichColumn[iColumn]; buildElement[nelCreate++] = realValue; } } numberOutput = 1; for (i = 0; i < numJ; i++) { bound[i] = 0; } break; } numberOutput++; if (numberOutput > maxNumber) { nelCreate = -numberOutput; 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 [] flip; delete [] size; delete [] offset; delete [] rhsOffset; delete [] build; delete [] markRow; delete [] lo; delete [] high; return nelCreate; } // Quick try at cleaning up duals if postsolve gets wrong void ClpSimplexOther::cleanupAfterPostsolve() { // First mark singleton equality rows char * mark = new char [ numberRows_]; memset(mark, 0, numberRows_); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * element = matrix_->getElements(); for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (mark[iRow]) mark[iRow] = 2; else mark[iRow] = 1; } } // for now just == rows for (int iRow = 0; iRow < numberRows_; iRow++) { if (rowUpper_[iRow] > rowLower_[iRow]) mark[iRow] = 3; } double dualTolerance = dblParam_[ClpDualTolerance]; double primalTolerance = dblParam_[ClpPrimalTolerance]; int numberCleaned = 0; double maxmin = optimizationDirection_; for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { double dualValue = reducedCost_[iColumn] * maxmin; double primalValue = columnActivity_[iColumn]; double lower = columnLower_[iColumn]; double upper = columnUpper_[iColumn]; int way = 0; switch(getColumnStatus(iColumn)) { case basic: // dual should be zero if (dualValue > dualTolerance) { way = -1; } else if (dualValue < -dualTolerance) { way = 1; } break; case ClpSimplex::isFixed: break; case atUpperBound: // dual should not be positive if (dualValue > dualTolerance) { way = -1; } break; case atLowerBound: // dual should not be negative if (dualValue < -dualTolerance) { way = 1; } break; case superBasic: case isFree: if (primalValue < upper - primalTolerance) { // dual should not be negative if (dualValue < -dualTolerance) { way = 1; } } if (primalValue > lower + primalTolerance) { // dual should not be positive if (dualValue > dualTolerance) { way = -1; } } break; } if (way) { // see if can find singleton row for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (mark[iRow] == 1) { double value = element[j]; // dj - addDual*value == 0.0 double addDual = dualValue / value; dual_[iRow] += addDual; reducedCost_[iColumn] = 0.0; numberCleaned++; break; } } } } delete [] mark; #ifdef CLP_INVESTIGATE printf("cleanupAfterPostsolve cleaned up %d columns\n", numberCleaned); #endif // Redo memcpy(reducedCost_, this->objective(), numberColumns_ * sizeof(double)); matrix_->transposeTimes(-1.0, dual_, reducedCost_); checkSolutionInternal(); } // Returns gub version of model or NULL ClpSimplex * ClpSimplexOther::gubVersion(int * whichRows, int * whichColumns, int neededGub, int factorizationFrequency) { // find gub int numberRows = this->numberRows(); int numberColumns = this->numberColumns(); int iRow, iColumn; int * columnIsGub = new int [numberColumns]; const double * columnLower = this->columnLower(); const double * columnUpper = this->columnUpper(); int numberFixed=0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnUpper[iColumn] == columnLower[iColumn]) { columnIsGub[iColumn]=-2; numberFixed++; } else if (columnLower[iColumn]>=0) { columnIsGub[iColumn]=-1; } else { columnIsGub[iColumn]=-3; } } CoinPackedMatrix * matrix = this->matrix(); // 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(); int numberNonGub = 0; int numberEmpty = numberRows; int * rowIsGub = new int [numberRows]; int smallestGubRow=-1; int count=numberColumns+1; double * rowLower = this->rowLower(); double * rowUpper = this->rowUpper(); // make sure we can get rid of upper bounds double * fixedRow = new double [numberRows]; for (iRow = 0 ; iRow < numberRows ; iRow++) { double sumFixed=0.0; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; double value = columnLower[iColumn]; if (value) sumFixed += element[j] * value; } fixedRow[iRow]=rowUpper[iRow]-sumFixed; } for (iRow = numberRows - 1; iRow >= 0; iRow--) { bool gubRow = true; int numberInRow=0; double sumFixed=0.0; double gap = fixedRow[iRow]-1.0e-12; for (int j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int iColumn = column[j]; if (columnIsGub[iColumn]!=-2) { if (element[j] != 1.0||columnIsGub[iColumn]==-3|| columnUpper[iColumn]-columnLower[iColumn]= 0) { gubRow = false; break; } } } else { sumFixed += columnLower[iColumn]*element[j]; } } if (!gubRow) { whichRows[numberNonGub++] = iRow; rowIsGub[iRow] = -1; } else if (numberInRow) { if (numberInRowrowUpper[iRow]+1.0e-4|| sumFixed= neededGub) { sprintf(message,"%d gub rows", numberGub); handler_->message(CLP_GENERAL2, messages_) << message << CoinMessageEol; int numberNormal = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnIsGub[iColumn] < 0 && columnIsGub[iColumn] !=-2) { whichColumns[numberNormal++] = iColumn; } } if (!numberNormal) { sprintf(message,"Putting back one gub row to make non-empty"); handler_->message(CLP_GENERAL2, messages_) << message << CoinMessageEol; rowIsGub[smallestGubRow]=-1; whichRows[numberNonGub++] = smallestGubRow; for (int j = rowStart[smallestGubRow]; j < rowStart[smallestGubRow] + rowLength[smallestGubRow]; j++) { int iColumn = column[j]; if (columnIsGub[iColumn]>=0) { columnIsGub[iColumn]=-4; whichColumns[numberNormal++] = iColumn; } } } std::sort(whichRows,whichRows+numberNonGub); std::sort(whichColumns,whichColumns+numberNormal); double * lower = CoinCopyOfArray(this->rowLower(),numberRows); double * upper = CoinCopyOfArray(this->rowUpper(),numberRows); // leave empty rows at end numberEmpty = numberRows-numberEmpty; const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const double * elementByColumn = matrix->getElements(); // Fixed at end int put2 = numberColumns-numberFixed; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (columnIsGub[iColumn] ==-2) { whichColumns[put2++] = iColumn; double value = columnLower[iColumn]; for (int j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (lower[iRow]>-1.0e20) lower[iRow] -= value*element[j]; if (upper[iRow]<1.0e20) upper[iRow] -= value*element[j]; } } } int put = numberNormal; ClpSimplex * model2 = new ClpSimplex(this, numberNonGub, whichRows , numberNormal, whichColumns); // scale double * scaleArray = new double [numberRows]; for (int i=0;i-1.0e30) lower[i] *= scale; if (upper[i]<1.0e30) upper[i] *= scale; } } // scale partial matrix { CoinPackedMatrix * matrix = model2->matrix(); const int * row = matrix->getIndices(); const int * columnLength = matrix->getVectorLengths(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); double * element = matrix->getMutableElements(); for (int i=0;irowLower(); double * rowUpper = model2->rowUpper(); for (int i=0;i=0) { numberElements += columnLength[iColumn]-1; temp1[iGub]++; } } /* Optional but means can eventually simplify coding could even add in fixed slacks to deal with singularities - but should not be necessary */ int numberSlacks=0; for (int i = 0; i < numberRows; i++) { if (rowIsGub[i]>=0) { if (lower[i]=0) { rowIsGub[i]=numberGub; gubStart[numberGub+1]=gubStart[numberGub]+temp1[i]; temp1[numberGub]=0; lower[numberGub]=lower[i]; upper[numberGub]=upper[i]; whichRows[numberNonGub+numberGub]=i; numberGub++; } } int numberGubColumnsPlus = numberGubColumns + numberSlacks; double * lowerColumn2 = new double [numberGubColumnsPlus]; CoinFillN(lowerColumn2, numberGubColumnsPlus, 0.0); double * upperColumn2 = new double [numberGubColumnsPlus]; CoinFillN(upperColumn2, numberGubColumnsPlus, COIN_DBL_MAX); int * start2 = new int[numberGubColumnsPlus+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; double * cost2 = new double [numberGubColumnsPlus]; CoinFillN(cost2, numberGubColumnsPlus, 0.0); const double * cost = this->objective(); put = numberNormal; for (iColumn = 0; iColumn < numberColumns; iColumn++) { int iGub = columnIsGub[iColumn]; if (iGub>=0) { // TEMP //this->setColUpper(iColumn,COIN_DBL_MAX); iGub = rowIsGub[iGub]; assert (iGub>=0); int kPut = put+gubStart[iGub]+temp1[iGub]; temp1[iGub]++; whichColumns[kPut]=iColumn; } } for (int i = 0; i < numberRows; i++) { if (rowIsGub[i]>=0) { int iGub = rowIsGub[i]; if (lower[iGub]primal(1); // TEMP // redo rowIsGub to give lookup for (int i=0;i= 0) { row2[numberElements] = iRow; element2[numberElements++] = elementByColumn[j]*scaleBy; } } } else { // slack int iGub = iColumn-numberColumns; double slack = upper[iGub]-lower[iGub]; assert (upper[iGub]<1.0e20); lower[iGub]=upper[iGub]; cost2[i] = 0; lowerColumn2[i] = 0; upperColumn2[i] = slack; upperColumn2[i] = COIN_DBL_MAX; } start2[i+1] = numberElements; } // clean up bounds on variables for (int iSet=0;iSetnumberRows(), model2->numberColumns()); handler_->message(CLP_GENERAL2, messages_) << message << CoinMessageEol; delete [] scaleArray; delete [] temp1; model2->setFactorizationFrequency(factorizationFrequency); ClpDynamicMatrix * newMatrix = new ClpDynamicMatrix(model2, numberGub, numberGubColumnsPlus, gubStart, lower, upper, start2, row2, element2, cost2, lowerColumn2, upperColumn2); delete [] gubStart; delete [] lowerColumn2; delete [] upperColumn2; delete [] start2; delete [] row2; delete [] element2; delete [] cost2; delete [] lower; delete [] upper; model2->replaceMatrix(newMatrix,true); #ifdef EVERY_ITERATION { ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(model2->clpMatrix()); assert(gubMatrix); gubMatrix->writeMps("gub.mps"); } #endif delete [] columnIsGub; delete [] rowIsGub; newMatrix->switchOffCheck(); #ifdef EVERY_ITERATION newMatrix->setRefreshFrequency(1/*000*/); #else newMatrix->setRefreshFrequency(1000); #endif sprintf(message, "** While after adding matrix there are %d rows and %d columns", model2->numberRows(), model2->numberColumns()); handler_->message(CLP_GENERAL2, messages_) << message << CoinMessageEol; model2->setSpecialOptions(4); // exactly to bound // Scaling off (done by hand) model2->scaling(0); return model2; } else { delete [] columnIsGub; delete [] rowIsGub; return NULL; } } // Sets basis from original void ClpSimplexOther::setGubBasis(ClpSimplex &original,const int * whichRows, const int * whichColumns) { ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(clpMatrix()); assert(gubMatrix); int numberGubColumns = gubMatrix->numberGubColumns(); int numberNormal = gubMatrix->firstDynamic(); //int lastOdd = gubMatrix->firstAvailable(); //int numberTotalColumns = numberNormal + numberGubColumns; //assert (numberTotalColumns==numberColumns+numberSlacks); int numberRows = original.numberRows(); int numberColumns = original.numberColumns(); int * columnIsGub = new int [numberColumns]; int numberNonGub = gubMatrix->numberStaticRows(); //assert (firstOdd==numberNormal); double * solution = primalColumnSolution(); double * originalSolution = original.primalColumnSolution(); const double * upperSet = gubMatrix->upperSet(); // Column copy of GUB part int numberSets = gubMatrix->numberSets(); const int * startSet = gubMatrix->startSets(); const CoinBigIndex * columnStart = gubMatrix->startColumn(); const double * columnLower = gubMatrix->columnLower(); #ifdef TRY_IMPROVE const double * columnUpper = gubMatrix->columnUpper(); const double * lowerSet = gubMatrix->lowerSet(); const double * element = gubMatrix->element(); const int * row = gubMatrix->row(); bool allPositive=true; double * rowActivity = new double[numberNonGub]; memset(rowActivity, 0, numberNonGub*sizeof(double)); { // Non gub contribution const double * element = matrix_->getElements(); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); for (int i=0;isetDynamicStatus(j,ClpDynamicMatrix::atLowerBound); int iColumn = whichColumns[j+numberNormal]; if (iColumnupperSet[i]+1.0e-8) { double gap = sum-upperSet[i]; if (iSlack>=0) { double value=newSolution[iSlack]; if (value>0.0) { double down = CoinMin(gap,value); gap -= down; sum -= down; newSolution[iSlack] = value-down; } } if (gap>1.0e-8) { for (int j=startSet[i];j0.0&&iColumn=0) { double value=newSolution[iSlack]; if (value1.0e-8) { for (int j=startSet[i];j1.0e-7) printf("Sum for set %d is %g - lower %g, upper %g\n",i, sum,lowerSet[i],upperSet[i]); } if (allPositive) { // See if we can improve solution // first reduce if over double * gaps = new double [numberNonGub]; double direction = optimizationDirection_; const double * cost = gubMatrix->cost(); bool over=false; for (int i=0;irowUpper_[i]+1.0e-6) { gaps[i]=activity-rowUpper_[i]; over=true; } } double * weights = new double [numberGubColumns]; int * which = new int [numberGubColumns]; int * whichSet = new int [numberGubColumns]; if (over) { int n=0; for (int i=0;iupperSet[i]-1.0e-8) continue; double slackCost = cost[iSlack]*direction; for (int j=startSet[i];jcolumnLower[j]&&j!=iSlack) { if(thisCost=0); double move = 0.0; for (CoinBigIndex k = columnStart[j]; k < columnStart[j+1] ; k++) { int iRow = row[k]; if(rowActivity[iRow]-rowUpper_[iRow]>move*element[k]) { move = (rowActivity[iRow]-rowUpper_[iRow])/element[k]; } } move=CoinMin(move,newSolution[j]-columnLower[j]); if (move) { newSolution[j] -= move; newSolution[iSlack] += move; for (CoinBigIndex k = columnStart[j]; k < columnStart[j+1] ; k++) { int iRow = row[k]; rowActivity[iRow] -= move*element[k]; } } } } delete [] whichSet; delete [] which; delete [] weights; delete [] gaps; // redo original status! for (int i=0;icolumnLower[j]) { numberNewBasic++; j2=j; } int iOrig = whichColumns[j+numberNormal]; if (iOrigsetDynamicStatus(j,ClpDynamicMatrix::atLowerBound); int iColumn = whichColumns[j+numberNormal]; if (iColumn=0); numberKey[iRow]++; } } else { // Set slack int iSet = iOrig - numberColumns; int iRow = whichRows[iSet+numberNonGub]; if (original.getRowStatus(iRow)==ClpSimplex::basic) numberKey[iRow]++; } } /* Before going into cleanMatrix we need gub status set (inSmall just means basic and active) row status set */ for (int i = 0; i < numberSets; i++) { gubMatrix->setStatus(i,ClpSimplex::isFixed); } for (int i = 0; i < numberGubColumns; i++) { int iOrig = whichColumns[i+numberNormal]; if (iOrigsetDynamicStatus(i,ClpDynamicMatrix::atUpperBound); } else if (status==ClpSimplex::atLowerBound) { gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::atLowerBound); } else if (status==ClpSimplex::basic) { int iRow = columnIsGub[iOrig]; assert (iRow>=0); assert(numberKey[iRow]); if (numberKey[iRow]==1) gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::soloKey); else gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::inSmall); } } else { // slack int iSet = iOrig - numberColumns; int iRow = whichRows[iSet+numberNonGub]; if (original.getRowStatus(iRow)==ClpSimplex::basic #ifdef TRY_IMPROVE ||newSolution[i]>columnLower[i]+1.0e-8 #endif ) { assert(numberKey[iRow]); if (numberKey[iRow]==1) gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::soloKey); else gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::inSmall); } else { gubMatrix->setDynamicStatus(i,ClpDynamicMatrix::atLowerBound); } } } // deal with sets without key for (int i = 0; i < numberSets; i++) { int iRow = whichRows[numberNonGub+i]; if (!numberKey[iRow]) { double upper = upperSet[i]-1.0e-7; if (original.getRowStatus(iRow)==ClpSimplex::basic) gubMatrix->setStatus(i,ClpSimplex::basic); // If not at lb make key otherwise one with smallest number els double largest=0.0; int fewest=numberRows+1; int chosen=-1; for (int j=startSet[i];jupper) gubMatrix->setStatus(i,ClpSimplex::atLowerBound); } else { // slack - take value as 0.0 as will win on length value=0.0; } if (value>largest+1.0e-8) { largest=value; fewest=length; chosen=j; } else if (fabs(value-largest)<=1.0e-8&&length=0); if (gubMatrix->getStatus(i)!=ClpSimplex::basic) { // set as key for (int j=startSet[i];jsetDynamicStatus(j,ClpDynamicMatrix::atLowerBound); else gubMatrix->setDynamicStatus(j,ClpDynamicMatrix::soloKey); } } } } for (int i = 0; i < numberNormal; i++) { int iOrig = whichColumns[i]; setColumnStatus(i,original.getColumnStatus(iOrig)); solution[i]=originalSolution[iOrig]; } for (int i = 0; i < numberNonGub; i++) { int iOrig = whichRows[i]; setRowStatus(i,original.getRowStatus(iOrig)); } // Fill in current matrix gubMatrix->initialProblem(); delete [] numberKey; delete [] columnIsGub; } // Restores basis to original void ClpSimplexOther::getGubBasis(ClpSimplex &original,const int * whichRows, const int * whichColumns) const { ClpDynamicMatrix * gubMatrix = dynamic_cast< ClpDynamicMatrix*>(clpMatrix()); assert(gubMatrix); int numberGubColumns = gubMatrix->numberGubColumns(); int numberNormal = gubMatrix->firstDynamic(); //int lastOdd = gubMatrix->firstAvailable(); //int numberRows = original.numberRows(); int numberColumns = original.numberColumns(); int numberNonGub = gubMatrix->numberStaticRows(); //assert (firstOdd==numberNormal); double * solution = primalColumnSolution(); double * originalSolution = original.primalColumnSolution(); int numberSets = gubMatrix->numberSets(); const double * cost = original.objective(); int lastOdd = gubMatrix->firstAvailable(); //assert (numberTotalColumns==numberColumns+numberSlacks); int numberRows = original.numberRows(); //int numberStaticRows = gubMatrix->numberStaticRows(); const int * startSet = gubMatrix->startSets(); unsigned char * status = original.statusArray(); unsigned char * rowStatus = status+numberColumns; //assert (firstOdd==numberNormal); for (int i=0;iid(); const double * columnLower = gubMatrix->columnLower(); const double * columnUpper = gubMatrix->columnUpper(); for (int i = 0; i < numberGubColumns; i++) { int iOrig = whichColumns[i+numberNormal]; if (iOriggetDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) { originalSolution[iOrig] = columnUpper[i]; status[iOrig] = 2; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) { originalSolution[iOrig] = columnLower[i]; status[iOrig] = 3; } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) { int iSet = gubMatrix->whichSet(i); originalSolution[iOrig] = gubMatrix->keyValue(iSet); status[iOrig] = 1; } else { originalSolution[iOrig] = 0.0; status[iOrig] = 4; } } else { // slack int iSet = iOrig - numberColumns; int iRow = whichRows[iSet+numberNonGub]; if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) { original.setRowStatus(iRow,ClpSimplex::atLowerBound); } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound) { original.setRowStatus(iRow,ClpSimplex::atUpperBound); } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) { original.setRowStatus(iRow,ClpSimplex::basic); } } } for (int i = 0; i < numberNormal; i++) { int iOrig = whichColumns[i]; ClpSimplex::Status thisStatus = getStatus(i); if (thisStatus == ClpSimplex::basic) status[iOrig] = 1; else if (thisStatus == ClpSimplex::atLowerBound) status[iOrig] = 3; else if (thisStatus == ClpSimplex::atUpperBound) status[iOrig] = 2; else if (thisStatus == ClpSimplex::isFixed) status[iOrig] = 5; else abort(); originalSolution[iOrig] = solution[i]; } for (int i = numberNormal; i < lastOdd; i++) { int iOrig = whichColumns[id[i-numberNormal] + numberNormal]; if (iOrig=numberColumns are slacks (obviously no coefficients) status array is (char) Status enum */ int ClpSimplex::modifyCoefficientsAndPivot(int number, const int * which, const CoinBigIndex * start, const int * row, const double * newCoefficient, const unsigned char * newStatus, const double * newLower, const double * newUpper, const double * newObjective) { ClpPackedMatrix* clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix_); bool canPivot = lower_!=NULL && factorization_!=NULL; int returnCode=0; if (!clpMatrix) { canPivot=false; returnCode=-1; // very slow for (int i=0;imodifyCoefficient(row[j],iSequence,newCoefficient[j]); } } else { assert (start[i]==start[i+1]); } } } else { #if 0 // when in stable CoinPackedMatrix * matrix = clpMatrix->getPackedMatrix(); matrix->modifyCoefficients(number,which,start, row,newCoefficient); #else // Copy and sort which int * which2 = new int [2*number+2]; int * sort = which2+number+1; int n=0; for (int i=0;igetNumElements()) { rowVector = rowArray_[i]; break; } } bool tempVector=false; if (!rowVector) { tempVector=true; rowVector=new CoinIndexedVector(numberRows_); } CoinSort_2(which2,which2+n,sort); // Stop at end which2[n]=numberColumns_; sort[n]=n; CoinPackedMatrix * matrix = clpMatrix->getPackedMatrix(); int * rowNow = matrix->getMutableIndices(); CoinBigIndex * columnStart = matrix->getMutableVectorStarts(); int * columnLength = matrix->getMutableVectorLengths(); double * elementByColumn = matrix->getMutableElements(); double * array = rowVector->denseVector(); //int * index = rowVector->getIndices(); int needed=0; bool moveUp=false; for (int i=0;iCOIN_INDEXED_REALLY_TINY_ELEMENT) { double newValue=array[iRow]; if (oldValue!=newValue) { if (newValue) { array[iRow]=0.0; if (newValue==COIN_INDEXED_REALLY_TINY_ELEMENT) { needed--; } } } } else { nZeroOld++; } } assert (!nZeroOld); for (CoinBigIndex j=start[inWhich];j0) moveUp=true; } } } int numberElements = matrix->getNumElements(); assert (numberElements==columnStart[numberColumns_]); if (needed>0) { // need more space matrix->reserve(numberColumns_, numberElements+needed); rowNow = matrix->getMutableIndices(); elementByColumn = matrix->getMutableElements(); } if (moveUp) { // move up from top CoinBigIndex top = numberElements+needed; for (int iColumn=numberColumns_-1;iColumn>=0;iColumn--) { CoinBigIndex end = columnStart[iColumn+1]; columnStart[iColumn+1]=top; CoinBigIndex startThis = columnStart[iColumn]; for (CoinBigIndex j=end-1;j>=startThis;j--) { if (elementByColumn[j]) { top--; elementByColumn[top]=elementByColumn[j]; rowNow[top]=rowNow[j]; } } } columnStart[0]=top; } // now move down and insert CoinBigIndex put=0; int iColumn=0; for (int i=0;iCOIN_INDEXED_REALLY_TINY_ELEMENT) { rowNow[put]=iRow; elementByColumn[put++]=oldValue; } } for (CoinBigIndex j=start[inWhich];jsetNumElements(put); if (tempVector) delete rowVector; for (int i=0;ireverseOrderedCopy(); } assert (!newStatus); // do later int numberPivots = factorization_->pivots(); int needed=0; for (int i=0;istart[i]&&getStatus(iSequence)==basic) needed++; } if (needed&&numberPivots+needed<20&&needed<-2) { // update factorization int saveIn = sequenceIn_; int savePivot = pivotRow_; int nArray=0; CoinIndexedVector * vec[2]; for (int i=0;i<4;i++) { if (!rowArray_[i]->getNumElements()) { vec[nArray++]=rowArray_[i]; if (nArray==2) break; } } assert (nArray==2); // could use temp array for (int i=0;istart[i]&&getStatus(sequenceIn_)==basic) { // find pivot row for (pivotRow_=0;pivotRow_getNumElements()); #ifndef COIN_FAC_NEW unpackPacked(vec[0]); #else unpack(vec[0]); #endif // update assert(!vec[1]->getNumElements()); factorization_->updateColumnFT(vec[1], vec[0]); const double * array = vec[0]->denseVector(); #ifndef COIN_FAC_NEW // Find alpha const int * indices = vec[0]->getIndices(); int n=vec[0]->getNumElements(); alpha_=0.0; for (int i=0;i1.0e-7) updateStatus = factorization_->replaceColumn(this, vec[1], vec[0], pivotRow_, alpha_); assert(!vec[1]->getNumElements()); vec[0]->clear(); if (updateStatus) { returnCode=3; break; } } } sequenceIn_=saveIn; pivotRow_ = savePivot; if (!returnCode) returnCode=100; // say can do more } else if (needed) { returnCode=3; // refactorize } } } if (newStatus) { for (int i=0;icheckInfeasibilities(oldTolerance); delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); } gutsOfSolution(NULL,NULL,false); assert (!newStatus); printf("%d primal %d dual\n",numberPrimalInfeasibilities_, numberDualInfeasibilities_); returnCode=3; } else { // is this needed if (nonLinearCost_) { // speed up later #if 1 for (int i=0;isetOne(iSequence,solution_[iSequence], lower_[iSequence],upper_[iSequence], cost_[iSequence]); } #else //nonLinearCost_->checkInfeasibilities(oldTolerance); delete nonLinearCost_; nonLinearCost_ = new ClpNonLinearCost(this); //nonLinearCost_->checkInfeasibilities(0.0); #endif //gutsOfSolution(NULL,NULL,false); assert (!newStatus); } } } return returnCode; } /* Pivot out a variable and choose an incoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Return codes as before but -1 means no acceptable pivot */ int ClpSimplex::dualPivotResultPart1() { return static_cast (this)->pivotResultPart1(); } /* Do actual pivot state is 1,3 if got tableau column in rowArray_[1] 2,3 if got tableau row in rowArray_[0] and columnArray_[0] */ int ClpSimplex::pivotResultPart2(int algorithm,int state) { if (!(state&1)) { // update the incoming column #ifndef COIN_FAC_NEW unpackPacked(rowArray_[1]); #else unpack(rowArray_[1]); #endif factorization_->updateColumnFT(rowArray_[2], rowArray_[1]); } #define CHECK_TABLEAU 0 if (!(state&2)||CHECK_TABLEAU) { // get tableau row // create as packed double direction = directionOut_; assert (!rowArray_[2]->getNumElements()); assert (!columnArray_[1]->getNumElements()); #if CHECK_TABLEAU printf("rowArray0 old\n"); rowArray_[0]->print(); rowArray_[0]->clear(); printf("columnArray0 old\n"); columnArray_[0]->print(); columnArray_[0]->clear(); #else assert (!columnArray_[0]->getNumElements()); assert (!rowArray_[0]->getNumElements()); #endif #ifndef COIN_FAC_NEW rowArray_[0]->createPacked(1, &pivotRow_, &direction); #else rowArray_[0]->createOneUnpackedElement(pivotRow_, direction); #endif factorization_->updateColumnTranspose(rowArray_[2], rowArray_[0]); rowArray_[3]->clear(); // put row of tableau in rowArray[0] and columnArray[0] assert (!rowArray_[2]->getNumElements()); matrix_->transposeTimes(this, -1.0, rowArray_[0], rowArray_[2], columnArray_[0]); #if CHECK_TABLEAU printf("rowArray0 new\n"); rowArray_[0]->print(); printf("columnArray0 new\n"); columnArray_[0]->print(); #endif } assert (pivotRow_>=0); assert (sequenceIn_>=0); assert (sequenceOut_>=0); int returnCode=-1; if (algorithm>0) { // replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_); if (!updateStatus) { dualIn_ = cost_[sequenceIn_]; double * work = rowArray_[1]->denseVector(); int number = rowArray_[1]->getNumElements(); int * which = rowArray_[1]->getIndices(); for (int i = 0; i < number; i++) { int iRow = which[i]; #ifndef COIN_FAC_NEW double alpha = work[i]; #else double alpha = work[iRow]; #endif int iPivot = pivotVariable_[iRow]; dualIn_ -= alpha * cost_[iPivot]; } returnCode=0; double multiplier = dualIn_ / alpha_; // update column djs int i; int * index = columnArray_[0]->getIndices(); number = columnArray_[0]->getNumElements(); double * element = columnArray_[0]->denseVector(); assert (columnArray_[0]->packedMode()); for (i = 0; i < number; i++) { int iSequence = index[i]; dj_[iSequence] += multiplier*element[i]; reducedCost_[iSequence] = dj_[iSequence]; element[i] = 0.0; } columnArray_[0]->setNumElements(0); // and row djs index = rowArray_[0]->getIndices(); number = rowArray_[0]->getNumElements(); element = rowArray_[0]->denseVector(); #ifndef COIN_FAC_NEW assert (rowArray_[0]->packedMode()); for (i = 0; i < number; i++) { int iSequence = index[i]; dj_[iSequence+numberColumns_] += multiplier*element[i]; dual_[iSequence] = dj_[iSequence+numberColumns_]; element[i] = 0.0; } #else assert (!rowArray_[0]->packedMode()); for (i = 0; i < number; i++) { int iSequence = index[i]; dj_[iSequence+numberColumns_] += multiplier*element[iSequence]; dual_[iSequence] = dj_[iSequence+numberColumns_]; element[iSequence] = 0.0; } #endif rowArray_[0]->setNumElements(0); double oldCost = cost_[sequenceOut_]; // update primal solution double objectiveChange = 0.0; // after this rowArray_[1] is not empty - used to update djs static_cast(this)->updatePrimalsInPrimal(rowArray_[1], theta_, objectiveChange, 0); double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ -= fabs(theta_); } else { valueIn_ = lowerIn_; } } else { // as if from lower bound if (sequenceIn_ != sequenceOut_) { // variable becoming basic valueIn_ += fabs(theta_); } else { valueIn_ = upperIn_; } } objectiveChange += dualIn_ * (valueIn_ - oldValue); // outgoing if (sequenceIn_ != sequenceOut_) { if (directionOut_ > 0) { valueOut_ = lowerOut_; } else { valueOut_ = upperOut_; } if(valueOut_ < lower_[sequenceOut_] - primalTolerance_) valueOut_ = lower_[sequenceOut_] - 0.9 * primalTolerance_; else if (valueOut_ > upper_[sequenceOut_] + primalTolerance_) valueOut_ = upper_[sequenceOut_] + 0.9 * primalTolerance_; // may not be exactly at bound and bounds may have changed // Make sure outgoing looks feasible directionOut_ = nonLinearCost_->setOneOutgoing(sequenceOut_, valueOut_); // May have got inaccurate //if (oldCost!=cost_[sequenceOut_]) //printf("costchange on %d from %g to %g\n",sequenceOut_, // oldCost,cost_[sequenceOut_]); dj_[sequenceOut_] = cost_[sequenceOut_] - oldCost; // normally updated next iteration solution_[sequenceOut_] = valueOut_; } // change cost and bounds on incoming if primal nonLinearCost_->setOne(sequenceIn_, valueIn_); progress_.startCheck(); // make sure won't worry about cycling int whatNext = housekeeping(objectiveChange); if (whatNext == 1) { returnCode = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent returnCode = 3; } else if(numberIterations_ == lastGoodIteration_ + 2 * factorization_->maximumPivots()) { // done a lot of flips - be safe returnCode = -2; // refactorize } } else { // ? abort(); } } else { // dual // recompute dualOut_ if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } // update the incoming column double btranAlpha = -alpha_ * directionOut_; // for check rowArray_[1]->clear(); #ifndef COIN_FAC_NEW unpackPacked(rowArray_[1]); #else unpack(rowArray_[1]); #endif // moved into updateWeights - factorization_->updateColumnFT(rowArray_[2],rowArray_[1]); // and update dual weights (can do in parallel - with extra array) alpha_ = dualRowPivot_->updateWeights(rowArray_[0], rowArray_[2], rowArray_[3], rowArray_[1]); // see if update stable #ifdef CLP_DEBUG if ((handler_->logLevel() & 32)) printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_); #endif double checkValue = 1.0e-7; // if can't trust much and long way from optimal then relax if (largestPrimalError_ > 10.0) checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue*(1.0 + fabs(alpha_))) { handler_->message(CLP_DUAL_CHECK, messages_) << btranAlpha << alpha_ << CoinMessageEol; if (factorization_->pivots()) { dualRowPivot_->unrollWeights(); problemStatus_ = -2; // factorize now rowArray_[0]->clear(); rowArray_[1]->clear(); columnArray_[0]->clear(); returnCode = -2; abort(); return returnCode; } else { // take on more relaxed criterion double test; if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8) test = 1.0e-1 * fabs(alpha_); else test = 1.0e-4 * (1.0 + fabs(alpha_)); if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) { abort(); } } } // update duals BEFORE replaceColumn so can do updateColumn double objectiveChange = 0.0; // do duals first as variables may flip bounds // rowArray_[0] and columnArray_[0] may have flips // so use rowArray_[3] for work array from here on int nswapped = 0; //rowArray_[0]->cleanAndPackSafe(1.0e-60); //columnArray_[0]->cleanAndPackSafe(1.0e-60); // make sure incoming doesn't count Status saveStatus = getStatus(sequenceIn_); setStatus(sequenceIn_, basic); nswapped = static_cast(this)->updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[2], theta_, objectiveChange, false); assert (!nswapped); setStatus(sequenceIn_, saveStatus); double oldDualOut = dualOut_; // which will change basic solution if (nswapped) { if (rowArray_[2]->getNumElements()) { factorization_->updateColumn(rowArray_[3], rowArray_[2]); dualRowPivot_->updatePrimalSolution(rowArray_[2], 1.0, objectiveChange); } // recompute dualOut_ valueOut_ = solution_[sequenceOut_]; if (directionOut_ < 0) { dualOut_ = valueOut_ - upperOut_; } else { dualOut_ = lowerOut_ - valueOut_; } } // amount primal will move double movement = -dualOut_ * directionOut_ / alpha_; double movementOld = oldDualOut * directionOut_ / alpha_; // so objective should increase by fabs(dj)*movement // but we already have objective change - so check will be good if (objectiveChange + fabs(movementOld * dualIn_) < -CoinMax(1.0e-5, 1.0e-12 * fabs(objectiveValue_))) { if (handler_->logLevel() & 32) printf("movement %g, swap change %g, rest %g * %g\n", objectiveChange + fabs(movement * dualIn_), objectiveChange, movement, dualIn_); } // if stable replace in basis int updateStatus = factorization_->replaceColumn(this, rowArray_[2], rowArray_[1], pivotRow_, alpha_); // If looks like bad pivot - refactorize if (fabs(dualOut_) > 1.0e50) updateStatus = 2; // if no pivots, bad update but reasonable alpha - take and invert if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5) updateStatus = 4; if (updateStatus == 1 || updateStatus == 4) { // slight error if (factorization_->pivots() > 5 || updateStatus == 4) { problemStatus_ = -2; // factorize now returnCode = -3; } } else if (updateStatus == 2) { // major error dualRowPivot_->unrollWeights(); // later we may need to unwind more e.g. fake bounds if (factorization_->pivots() && ((moreSpecialOptions_ & 16) == 0 || factorization_->pivots() > 4)) { problemStatus_ = -2; // factorize now returnCode = -2; moreSpecialOptions_ |= 16; return returnCode; } else { // need to reject something abort(); } } else if (updateStatus == 3) { // out of memory // increase space if not many iterations if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200) factorization_->areaFactor( factorization_->areaFactor() * 1.1); problemStatus_ = -2; // factorize now } else if (updateStatus == 5) { problemStatus_ = -2; // factorize now } // update primal solution if (theta_ < 0.0) { if (handler_->logLevel() & 32) printf("negative theta %g\n", theta_); theta_ = 0.0; } // do actual flips (should not be any?) static_cast(this)->flipBounds(rowArray_[0], columnArray_[0]); //rowArray_[1]->expand(); dualRowPivot_->updatePrimalSolution(rowArray_[1], movement, objectiveChange); // modify dualout dualOut_ /= alpha_; dualOut_ *= -directionOut_; //setStatus(sequenceIn_,basic); dj_[sequenceIn_] = 0.0; double oldValue = valueIn_; if (directionIn_ == -1) { // as if from upper bound valueIn_ = upperIn_ + dualOut_; } else { // as if from lower bound valueIn_ = lowerIn_ + dualOut_; } objectiveChange += cost_[sequenceIn_] * (valueIn_ - oldValue); // outgoing // set dj to zero unless values pass if (directionOut_ > 0) { valueOut_ = lowerOut_; dj_[sequenceOut_] = theta_; } else { valueOut_ = upperOut_; dj_[sequenceOut_] = -theta_; } solution_[sequenceOut_] = valueOut_; int whatNext = housekeeping(objectiveChange); // and set bounds correctly static_cast(this)->originalBound(sequenceIn_); static_cast(this)->changeBound(sequenceOut_); if (whatNext == 1) { problemStatus_ = -2; // refactorize } else if (whatNext == 2) { // maximum iterations or equivalent problemStatus_ = 3; returnCode = 3; abort(); } } // Check event { int status = eventHandler_->event(ClpEventHandler::endOfIteration); if (status >= 0) { problemStatus_ = 5; secondaryStatus_ = ClpEventHandler::endOfIteration; returnCode = 3; } } // need to be able to refactoriza //printf("return code %d problem status %d\n", // returnCode,problemStatus_); return returnCode; } #ifdef COIN_SHORT_SORT #define USE_HASH 1 #else #define USE_HASH 0 #endif #if USE_HASH==2 static const unsigned int mmult[] = { 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247}; // Returns a hash value inline unsigned int hashValue(double value, unsigned int maxHash) { const char * name = reinterpret_cast(&value); unsigned int n = 0; for (int j = 0; j < 8; ++j ) { n += mmult[j] * name[j]; } return ( n % maxHash ); } /* */ static int sameTogether(unsigned int nin,int * which, double * weights, int * which2, double * weights2, unsigned int * hash) { if (nin<=1) return nin; // move up and fill hash unsigned int maxHash=4*nin; memset(hash,0xf0,maxHash*sizeof(int)); int * spare=which2+maxHash; int n2=0; unsigned int iNext = hashValue (weights[0],maxHash); unsigned int endMarker=0x80000000+maxHash; hash[iNext]=endMarker; unsigned int iLast=iNext; weights2[iNext]=weights[0]; which2[iNext]=which[0]; for (unsigned int i=1;i0x7fffffff) { // end if (put>savePut+1) { CoinShortSort_2(weights+savePut,weights+put,which+savePut); // keep #if 0 printf("DUP2 value %g ",weights[savePut]); for (int i=savePut;i(weights); #endif #if 0 int counts[5]={0,0,0,0,0}; int countsEq[5]={0,0,0,0,0}; #endif // get row copy CoinPackedMatrix rowCopy = *matrix(); rowCopy.reverseOrdering(); int * column = rowCopy.getMutableIndices(); CoinBigIndex * rowStart = rowCopy.getMutableVectorStarts(); int * rowLength = rowCopy.getMutableVectorLengths(); double * element = rowCopy.getMutableElements(); //double wwww[200]; //assert (numberLook<=200); //int iiii[200]; for (int i=0;i(weights2+4*numberLook); unsigned int * hash = reinterpret_cast(which2+5*numberLook); int n=sameTogether(numberLook,ind,w,which2,weights2,hash); printf("Reduced length of %d\n",n); delete [] weights2; delete [] w; delete [] ind; } #endif CoinSort_2(weights,weights+numberLook,whichRows); #if 0 { double value = weights[0]; int firstSame=-1; int lastSame=-1; for (int iLook = 1; iLook < numberLook; iLook++) { if (weights[iLook]==value) { if (firstSame<0) { /* see how many same - if >2 but < ? may be worth looking at all combinations */ firstSame=iLook-1; printf("DUPS weight %g first row %d ",value,whichRows[firstSame]); for (lastSame=iLook;lastSame(weights+i); whichRows[i]=temp->item.hash.which; weights[i]=temp->item.hash.value; //printf("iLook %d weight %g (after) - true %d %g\n", // whichRows[i],weights[i],iiii[i],wwww[i]); } #undef USE_HASH #define USE_HASH 0 #endif #else int * which2 = reinterpret_cast(weights2+4*numberLook); unsigned int * hash = reinterpret_cast(which2+5*numberLook); numberLook=sameTogether(numberLook,whichRows,weights,which2,weights2,hash); printf("Reduced length of %d\n",numberLook); #endif if (tolerance<0.0) tolerance = primalTolerance_; int nPossible=0; int nDelete=0; #if USE_HASH==1 hash * temp = reinterpret_cast(weights); int iLast=temp->item.hash.which; float value=temp->item.hash.value; #else double value = weights[0]; int iLast = whichRows[0]; #endif double inverseCleanup = (cleanUp>0.0) ? 1.0/cleanUp : 0.0; //#define PRINT_DUP #ifdef PRINT_DUP int firstSame=-1; int lastSame=-1; #endif for (int iLook = 1; iLook < numberLook; iLook++) { #if USE_HASH==1 hash * temp = reinterpret_cast(weights+iLook); int iThis=temp->item.hash.which; float valueThis=temp->item.hash.value; #else int iThis=whichRows[iLook]; double valueThis=weights[iLook]; #endif if (valueThis==value) { #ifdef PRINT_DUP if (firstSame<0) { /* see how many same - if >2 but < ? may be worth looking at all combinations */ firstSame=iLook-1; printf("DUPS weight %g first row %d ",value,whichRows[firstSame]); for (lastSame=iLook;lastSame1.0e-8) { bad=true; } #ifdef PRINT_DUP int n2=strlen(temp); if (n+n2<500) { strcat(line,temp); n += n2; } else { strcat(line,"..."); break; } #endif } } if (!bad) { #ifdef PRINT_DUP printf("%s lo (%g,%g) up (%g,%g) - multiplier %g\n",line,rowLower_[iThis],rowUpper_[iThis], rowLower_[iLast],rowUpper_[iLast],multiplier); #endif double rlo1=rowLower_[iLast]; double rup1=rowUpper_[iLast]; double rlo2=rowLower_[iThis]; double rup2=rowUpper_[iThis]; // scale rlo1 *= multiplier; rup1 *= multiplier; //swap bounds if neg if (multiplier<0.0) { double temp = rup1; rup1=rlo1; rlo1=temp; } /* now check rhs to see what is what */ #ifdef PRINT_DUP printf("duplicate row %g %g, %g %g\n", rlo1,rup1,rlo2,rup2); #endif if (!noOverlaps) { /* we always keep this and delete last later maybe keep better formed one */ rlo2 = CoinMax(rlo1,rlo2); if (rlo2<-1.0e30) rlo2=-COIN_DBL_MAX; rup2 = CoinMin(rup1,rup2); if (rup2>1.0e30) rup2=COIN_DBL_MAX; } else { /* keep better formed one */ if (rlo2>=rlo1-1.0e-8&&rup2<=rup1+1.0e-8) { // ok rlo2 = CoinMax(rlo1,rlo2); if (rlo2<-1.0e30) rlo2=-COIN_DBL_MAX; rup2 = CoinMin(rup1,rup2); if (rup2>1.0e30) rup2=COIN_DBL_MAX; } else if (rlo1>=rlo2-1.0e-8&&rup1<=rup2+1.0e-8) { rlo2 = CoinMax(rlo1,rlo2); if (rlo2<-1.0e30) rlo2=-COIN_DBL_MAX; rup2 = CoinMin(rup1,rup2); if (rup2>1.0e30) rup2=COIN_DBL_MAX; // swap int temp=iLast; iLast=iThis; iThis=temp; } else { // leave (for now) #if DEBUG_SOME>0 printf("row %d %g %g row %d %g %g\n",iLast,rlo1,rup1,iThis,rlo2,rup2); #endif iLast=iThis; continue; } } #ifdef PRINT_DUP printf("pre_duprow %dR %dR keep this\n",iLast,iThis); #endif #if 0 if (rowLength[iThis]<4) counts[rowLength[iThis]]++; else counts[4]++; #endif if (rup20.0) { /* see if close to multiple always allow integer values */ if (rlo2>-1.0e30) { double value = rlo2; double value2 = floor(value+0.5); if (fabs(value-value2)<1.0e-9) { rlo2=value2; } else { value = rlo2*inverseCleanup; value2 = floor(value+0.5); if (fabs(value-value2)<1.0e-9) rlo2=value2*cleanUp; } } if (rup2<1.0e30) { double value = rup2; double value2 = floor(value+0.5); if (fabs(value-value2)<1.0e-9) { rup2=value2; } else { value = rup2*inverseCleanup; value2 = floor(value+0.5); if (fabs(value-value2)<1.0e-9) rup2=value2*cleanUp; } } } rowLower_[iThis]=rlo2; rowUpper_[iThis]=rup2; whichRows[nDelete++]=iLast; if (getRowStatus(iLast)!=basic) { if (getRowStatus(iThis)==basic) { setRowStatus(iThis,superBasic); setRowStatus(iLast,basic); } } } else { #ifdef PRINT_DUP printf("%s lo (%g,%g) up (%g,%g) - ODD\n",line,rowLower_[iThis],rowUpper_[iThis], rowLower_[iLast],rowUpper_[iLast]); #endif } } } else { #ifdef PRINT_DUP // say no match firstSame=-1; #endif value=valueThis; } iLast=iThis; } #ifdef PRINT_DUP printf("%d possible duplicate rows - deleting %d\n", nPossible,nDelete); #endif #if 0 for (int i=0;i<5;i++) { if (counts[i]) printf("CC counts %d %d times of which %d were equalities\n",i,counts[i],countsEq[i]); } #endif delete [] weights; return nDelete; } /* Try simple crash like techniques to get closer to primal feasibility returns final sum of infeasibilities */ double ClpSimplex::moveTowardsPrimalFeasible() { memset (rowActivity_,0,numberRows_*sizeof(double)); matrix()->times(columnActivity_,rowActivity_); double sum=0.0; int * which = new int[numberRows_]; int numberLook=0; for (int iRow=0;iRowrowUpper_[iRow]+primalTolerance_) infeasibility = value-rowUpper_[iRow]; if (infeasibility) { sum += infeasibility; which[numberLook++]=iRow; } } if (numberLook) { const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * element = matrix_->getElements(); // get row copy CoinPackedMatrix rowCopy = *matrix(); rowCopy.reverseOrdering(); const int * column = rowCopy.getIndices(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); const int * rowLength = rowCopy.getVectorLengths(); const double * elementByRow = rowCopy.getElements(); double lastSum=COIN_DBL_MAX; while (sum>primalTolerance_&&numberLook) { sum =0.0; double worst=primalTolerance_; int iWorst=-1; int n=numberLook; numberLook=0; for (int iLook=0;iLookrowUpper_[iRow]+primalTolerance_) infeasibility = value-rowUpper_[iRow]; if (infeasibility) { sum += infeasibility; which[numberLook++]=iRow; if (infeasibility>worst) { worst = infeasibility; iWorst=iRow; } } } if (sum==0.0||sum>=lastSum-1.0e-8) break; lastSum=sum; double direction; if (rowActivity_[iWorst]0.0) ? 1.0 : -1.0; // but allow for column bounds double currentValue = columnActivity_[iColumn]; if (multiplier>0.0) distance = CoinMin(worst,columnUpper_[iColumn]-currentValue); else distance = CoinMin(worst,currentValue-columnLower_[iColumn]); distance /= fabs(value); for (CoinBigIndex i=columnStart[iColumn]; i0.0) { double distance2 = rowUpper_[iRow]-rowActivity_[iRow]; if (value2*distance>distance2) distance = distance2/value2; } else { double distance2 = rowLower_[iRow]-rowActivity_[iRow]; if (value2*distance1.0e-12) { worst-=distance*fabs(value); distance *= multiplier; columnActivity_[iColumn] = currentValue+distance; for (CoinBigIndex i=columnStart[iColumn]; i threshold */ void ClpSimplex::removeSuperBasicSlacks(int threshold) { // could try going both ways - for first attempt to nearer bound memset (rowActivity_,0,numberRows_*sizeof(double)); matrix()->times(columnActivity_,rowActivity_); double * distance = new double [numberRows_]; int * whichRows = new int [numberRows_]; int numberLook=0; for (int iRow=0;iRowrowLower_[iRow]+primalTolerance_&& valuethreshold) { CoinSort_2(distance,distance+numberLook,whichRows); const int * row = matrix_->getIndices(); const CoinBigIndex * columnStart = matrix_->getVectorStarts(); const int * columnLength = matrix_->getVectorLengths(); const double * element = matrix_->getElements(); // get row copy CoinPackedMatrix rowCopy = *matrix(); rowCopy.reverseOrdering(); const int * column = rowCopy.getIndices(); const CoinBigIndex * rowStart = rowCopy.getVectorStarts(); const int * rowLength = rowCopy.getVectorLengths(); const double * elementByRow = rowCopy.getElements(); int nMoved=0; for (int iLook=0;iLook0.0) ? 1.0 : -1.0; // but allow for column bounds double currentValue = columnActivity_[iColumn]; if (multiplier>0.0) distance = columnUpper_[iColumn]-currentValue; else distance = currentValue-columnLower_[iColumn]; for (CoinBigIndex i=columnStart[iColumn]; i0.0) { double distance2 = rowUpper_[iRow]-rowActivity_[iRow]; if (value2*distance>distance2) distance = distance2/value2; } else { double distance2 = rowLower_[iRow]-rowActivity_[iRow]; if (value2*distance1.0e-12) { distance *= multiplier; columnActivity_[iColumn] = currentValue+distance; for (CoinBigIndex i=columnStart[iColumn]; i0.0) { needed = rowUpper_[kRow]-rowActivity_[kRow]; } else { needed = rowActivity_[kRow]-rowLower_[kRow]; } } } if (neededmessage(CLP_GENERAL,messages_) << line << CoinMessageEol; } delete [] distance; delete [] whichRows; } /* 1 (and 4) redundant (and 8 is user) 2 sub 11 movable column 13 empty (or initially fixed) column 14 doubleton */ typedef struct { double oldRowLower; double oldRowUpper; int row; int lengthRow; } clpPresolveInfo1_4_8; // can be used instead of 1_4_8 typedef struct { double oldRowLower; double oldRowUpper; int row; int lengthRow; double * rowLowerX; double * rowUpperX; double * tempElement; int * tempIndex; int otherRow; } clpPresolveInfo8; typedef struct { double oldRowLower; double oldRowUpper; double oldColumnLower; double oldColumnUpper; double coefficient; // 2 is upper double oldRowLower2; double oldRowUpper2; double coefficient2; int row; int row2; int column; } clpPresolveInfo2; typedef struct { double oldColumnLower; double oldColumnUpper; double fixedTo; int column; int lengthColumn; } clpPresolveInfo11; typedef struct { double oldColumnLower; double oldColumnUpper; int column; } clpPresolveInfo13; typedef struct { double oldColumnLower; double oldColumnUpper; double oldColumnLower2; double oldColumnUpper2; double oldObjective2; double value1; double rhs; int type; int row; int column; int column2; int lengthColumn2; } clpPresolveInfo14; typedef struct { int infoOffset; int type; } clpPresolveInfo; typedef struct { int numberEntries; int maximumEntries; int numberInitial; clpPresolveInfo * start; } listInfo; typedef struct { char * putStuff; char * startStuff; CoinBigIndex maxStuff; } saveInfo; typedef struct { double * elements; int * indices; char * startStuff; } restoreInfo; // struct must match in handler typedef struct { ClpSimplex * model; CoinPackedMatrix * rowCopy; char * rowType; char * columnType; saveInfo * stuff; clpPresolveInfo * info; int * nActions; } clpPresolveMore; void ClpCopyToMiniSave(saveInfo & where, const char * info, unsigned int sizeInfo,int numberElements, const int * indices, const double * elements) { char * put = where.putStuff; int n = numberElements*static_cast(sizeof(int)+sizeof(double))+static_cast(sizeInfo); if (n+(put-where.startStuff)>where.maxStuff) { where.maxStuff += CoinMax(where.maxStuff/2 + 10000, 2*n); char * temp = new char[where.maxStuff]; long k = put-where.startStuff; memcpy(temp,where.startStuff,k); delete [] where.startStuff; where.startStuff=temp; put = temp+k; } memcpy(put,info,sizeInfo); put += sizeInfo; memcpy(put,indices,numberElements*sizeof(int)); put += numberElements*sizeof(int); memcpy(put,elements,numberElements*sizeof(double)); put += numberElements*sizeof(double); where.putStuff=put; } static void copyFromSave(restoreInfo & where, clpPresolveInfo & info, void * thisInfoX) { char * get = where.startStuff+info.infoOffset; int type = info.type; int n=0; switch(type) { case 1: case 4: // redundant { clpPresolveInfo1_4_8 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo1_4_8)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo1_4_8)); get += sizeof(clpPresolveInfo1_4_8); n = thisInfo.lengthRow; } break; case 8: case 9: // redundant { clpPresolveInfo8 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo8)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo8)); get += sizeof(clpPresolveInfo8); n = thisInfo.lengthRow; } break; case 2: // sub { clpPresolveInfo2 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo2)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo2)); get += sizeof(clpPresolveInfo2); } break; case 11: // movable column { clpPresolveInfo11 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo11)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo11)); get += sizeof(clpPresolveInfo11); n = thisInfo.lengthColumn; } break; case 13: // empty (or initially fixed) column { clpPresolveInfo13 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo13)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo13)); get += sizeof(clpPresolveInfo13); } break; case 14: // doubleton { clpPresolveInfo14 thisInfo; memcpy(&thisInfo,get,sizeof(clpPresolveInfo14)); memcpy(thisInfoX,get,sizeof(clpPresolveInfo14)); get += sizeof(clpPresolveInfo14); n = thisInfo.lengthColumn2; } break; } if (n) { memcpy(where.indices,get,n*sizeof(int)); get += n*sizeof(int); memcpy(where.elements,get,n*sizeof(double)); } } #define DEBUG_SOME 0 // need more space static void moveAround(int numberColumns,CoinBigIndex numberElementsOriginal, int iColumn,int lengthNeeded, int * forward,int * backward, CoinBigIndex * columnStart,int * columnLength, int * row,double * element) { // we only get here if can't fit so if iColumn is last one need shuffle int last=backward[numberColumns]; bool needCompaction=false; CoinBigIndex lastElement=columnStart[numberColumns]; //assert(lastElement==2*(numberElementsOriginal+numberColumns)); // save length int length=columnLength[iColumn]; if (iColumn!=last) { CoinBigIndex put=columnStart[last]+columnLength[last]+3; if (put+lengthNeeded<=lastElement) { // copy CoinBigIndex start = columnStart[iColumn]; columnStart[iColumn]=put; memcpy(element+put,element+start,length*sizeof(double)); memcpy(row+put,row+start,length*sizeof(int)); // forward backward int iLast=backward[iColumn]; int iNext=forward[iColumn]; forward[iLast]=iNext; backward[iNext]=iLast; forward[last]=iColumn; backward[iColumn]=last; forward[iColumn]=numberColumns; backward[numberColumns]=iColumn; } else { needCompaction=true; } } else { needCompaction=true; } if (needCompaction) { printf("compacting\n"); // size is lastElement+numberElementsOriginal #ifndef NDEBUG CoinBigIndex total=lengthNeeded-columnLength[iColumn]; for (int i=0;i=0); // copy back put=0; for (int i=0;i 0 printf("moved column %d\n",iColumn); #endif } #if DEBUG_SOME > 0 #ifndef NDEBUG static void checkBasis(ClpSimplex * model,char * rowType, char * columnType) { int numberRows=model->numberRows(); int nRowBasic=0; int nRows=0; for (int i=0;igetRowStatus(i)==ClpSimplex::basic) nRowBasic++; } } int numberColumns=model->numberColumns(); int nColumnBasic=0; for (int i=0;igetColumnStatus(i)==ClpSimplex::basic) nColumnBasic++; } ClpTraceDebug (nRowBasic+nColumnBasic==nRows); } #endif #endif #if DEBUG_SOME > 0 static int xxxxxx=2999999; #endif /* Mini presolve (faster) Char arrays must be numberRows and numberColumns long on entry second part must be filled in as follows - 0 - possible >0 - take out and do something (depending on value - TBD) 1 - redundant row 2 - sub 11 - column can be moved to bound 4 - row redundant (duplicate) 13 - empty (or initially fixed) column 14 - == row (also column deleted by row) 3 - column altered by a 14 5 - temporary marker for truly redundant sub row 8 - other -1 row/column can't vanish but can have entries removed/changed -2 don't touch at all on exit <=0 ones will be in presolved problem struct will be created and will be long enough (information on length etc in first entry) user must delete struct */ ClpSimplex * ClpSimplex::miniPresolve(char * rowType, char * columnType,void ** infoOut) { // Big enough structure int numberTotal=numberRows_+numberColumns_; CoinBigIndex lastElement = matrix_->getNumElements(); int maxInfoStuff = 5*lastElement*static_cast(sizeof(double))+numberTotal*static_cast(sizeof(clpPresolveInfo2)); clpPresolveInfo * infoA = new clpPresolveInfo[numberTotal]; char * startStuff = new char [maxInfoStuff]; memset(infoA,'B',numberTotal*sizeof(clpPresolveInfo)); memset(startStuff,'B',maxInfoStuff); int nActions=0; int * whichRows = new int [2*numberRows_+numberColumns_]; int * whichColumns = whichRows + numberRows_; int * whichRows2 = whichColumns + numberColumns_; double * array = new double [numberRows_]; memset(array,0,numberRows_*sizeof(double)); // New model (put in modification to increase size of matrix) and pack bool needExtension=numberColumns_>matrix_->getNumCols(); if (needExtension) { matrix()->reserve(numberColumns_,lastElement,true); CoinBigIndex * columnStart = matrix()->getMutableVectorStarts(); for (int i=numberColumns_;i>=0;i--) { if (columnStart[i]==0) columnStart[i]=lastElement; else break; } assert (lastElement==columnStart[numberColumns_]); } #define TWOFER #ifdef TWOFER ClpSimplex * newModel = NULL; CoinBigIndex lastPossible=3*lastElement; CoinBigIndex lastGood=2*lastElement; clpPresolveMore moreInfo; moreInfo.model=NULL; moreInfo.rowType=rowType; moreInfo.columnType=columnType; int addColumns = eventHandler_->eventWithInfo(ClpEventHandler::modifyMatrixInMiniPresolve,&moreInfo); if (moreInfo.model) { newModel = moreInfo.model; } else { newModel = new ClpSimplex(*this); newModel->matrix()->reserve(numberColumns_+addColumns,lastPossible,true); } #else ClpSimplex * newModel = new ClpSimplex(*this); //newModel->matrix()->reserve(numberColumns_,lastElement,true); #endif newModel->dropNames(); double * rowLower = newModel->rowLower(); double * rowUpper = newModel->rowUpper(); //double * rowActivity = newModel->primalRowSolution(); unsigned char * rowStatus = newModel->statusArray()+numberColumns_; // use top bit of status as marker for whichRows update for (int i=0;icolumnLower(); double * columnUpper = newModel->columnUpper(); //double * columnActivity = newModel->primalColumnSolution(); //unsigned char * columnStatus = newModel->statusArray(); // Take out marked stuff saveInfo stuff; stuff.putStuff=startStuff; stuff.startStuff=startStuff; stuff.maxStuff=maxInfoStuff; CoinPackedMatrix * matrix = newModel->matrix(); int * row = matrix->getMutableIndices(); CoinBigIndex * columnStart = matrix->getMutableVectorStarts(); int * columnLength = matrix->getMutableVectorLengths(); double * element = matrix->getMutableElements(); // get row copy CoinPackedMatrix rowCopy = *matrix; rowCopy.reverseOrdering(); int * column = rowCopy.getMutableIndices(); CoinBigIndex * rowStart = rowCopy.getMutableVectorStarts(); double * elementByRow = rowCopy.getMutableElements(); int * rowLength = rowCopy.getMutableVectorLengths(); for (int iRow=0;iRow0) { clpPresolveInfo1_4_8 thisInfo; thisInfo.row=iRow; thisInfo.oldRowLower=(rowLower_[iRow]>-1.0e30) ? rowLower_[iRow]-rowLower[iRow] : rowLower[iRow]; thisInfo.oldRowUpper=(rowUpper_[iRow]<1.0e30) ? rowUpper_[iRow]-rowUpper[iRow] : rowUpper[iRow]; int n=rowLength[iRow]; CoinBigIndex start=rowStart[iRow]; thisInfo.lengthRow=n; //thisInfo.column=-1; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=4; //rowType[iRow]; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo1_4_8), n,column+start,elementByRow+start); } } CoinBigIndex put=0; bool anyDeleted=false; for (int iColumn=0;iColumn0||(columnType[iColumn]==0&& (!length||columnLower_[iColumn]==columnUpper_[iColumn]))) { clpPresolveInfo13 thisInfo; //thisInfo.row=-1; thisInfo.oldColumnLower=columnLower[iColumn]; thisInfo.oldColumnUpper=columnUpper[iColumn]; thisInfo.column=iColumn; CoinBigIndex start=columnStart[iColumn]; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=(columnType[iColumn]>0) ? columnType[iColumn] : 13; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo13), 0,NULL,NULL); columnType[iColumn]=13; if (length) { double solValue=columnLower[iColumn]; if (solValue) { for (int j=start;j-1.0e20) rowLower[iRow]=lower-value; double upper = rowUpper[iRow]; if (upper<1.0e20) rowUpper[iRow]=upper-value; } } anyDeleted=true; length=0; } } columnStart[iColumn]=put; for (CoinBigIndex i=start;isetNumElements(put); // get row copy if changed if (anyDeleted) { rowCopy = *matrix; rowCopy.reverseOrdering(); column = rowCopy.getMutableIndices(); rowStart = rowCopy.getMutableVectorStarts(); elementByRow = rowCopy.getMutableElements(); rowLength = rowCopy.getMutableVectorLengths(); } double * objective = newModel->objective(); double offset = objectiveOffset(); int numberRowsLook=0; #ifdef TWOFER bool orderedMatrix=true; #endif int nChanged = 1; bool feasible=true; //#define CLP_NO_SUBS for (int iRow=0;iRow0 #ifndef NDEBUG checkBasis(newModel, rowType, columnType); #endif #endif int nPoss=2; #if DEBUG_SOME > 0 xxxxxx--; if (xxxxxx<=0) nPoss=1; if (xxxxxx<-1000) nPoss=-1; if (xxxxxx==1) { printf("bad\n"); } #endif if (rowLength[iRow]<=nPoss&&!rowType[iRow]) { if (rowLength[iRow]<=1) { if (rowLength[iRow]==1) { #ifndef CLP_NO_SUBS // See if already marked if ((rowStatus[iRow]&128)==0) { rowStatus[iRow] |= 128; whichRows[numberRowsLook++]=iRow; assert (numberRowsLook<=numberRows_); } #endif } else { #if DEBUG_SOME > 0 printf("Dropping null row %d (status %d) - nActions %d\n", iRow,getRowStatus(iRow),nActions); #endif if (rowLower[iRow] > primalTolerance_ || rowUpper[iRow] <-primalTolerance_) { feasible=false; nChanged=-1; numberRowsLook=0; break; } rowType[iRow]=1; clpPresolveInfo1_4_8 thisInfo; thisInfo.oldRowLower=(rowLower_[iRow]>-1.0e30) ? rowLower_[iRow]-rowLower[iRow] : rowLower[iRow]; thisInfo.oldRowUpper=(rowUpper_[iRow]<1.0e30) ? rowUpper_[iRow]-rowUpper[iRow] : rowUpper[iRow]; thisInfo.row=iRow; int n=rowLength[iRow]; CoinBigIndex start=rowStart[iRow]; thisInfo.lengthRow=n; //thisInfo.column=-1; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=1; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo1_4_8), n,column+start,elementByRow+start); } #ifdef TWOFER } else if (rowLower[iRow]==rowUpper[iRow]) { #ifndef CLP_NO_SUBS // See if already marked if ((rowStatus[iRow]&128)==0) { rowStatus[iRow] |= 128; whichRows[numberRowsLook++]=iRow; assert (numberRowsLook<=numberRows_); } #endif CoinBigIndex start = rowStart[iRow]; int iColumn1 = column[start]; double value1 = elementByRow[start]; int iColumn2 = column[start+1]; double value2 = elementByRow[start+1]; bool swap=false; double ratio = fabs(value1/value2); if (ratio<0.001||ratio>1000.0) { if (fabs(value1)0.0) { newLower = (dropUpper<1.0e30) ? rhs - multiplier*dropUpper : -COIN_DBL_MAX; newUpper = (dropLower>-1.0e30) ? rhs - multiplier*dropLower : COIN_DBL_MAX; } else { newUpper = (dropUpper<1.0e30) ? rhs - multiplier*dropUpper : COIN_DBL_MAX; newLower = (dropLower>-1.0e30) ? rhs - multiplier*dropLower : -COIN_DBL_MAX; } //columnType[iColumn1]=3; columnType[iColumn2]=14; rowType[iRow]=14; rhs = rowLower[iRow]/value2; multiplier = value1/value2; clpPresolveInfo14 thisInfo; thisInfo.oldColumnLower=columnLower[iColumn1]; thisInfo.oldColumnUpper=columnUpper[iColumn1]; thisInfo.oldColumnLower2=columnLower[iColumn2]; thisInfo.oldColumnUpper2=columnUpper[iColumn2]; thisInfo.oldObjective2=objective[iColumn2]; thisInfo.value1=value1; thisInfo.rhs=rowLower[iRow]; thisInfo.row=iRow; thisInfo.column=iColumn1; thisInfo.column2=iColumn2; int nel=columnLength[iColumn2]; CoinBigIndex startCol=columnStart[iColumn2]; thisInfo.lengthColumn2=nel; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=14; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo14), nel,row+startCol,element+startCol); newLower = CoinMax(newLower,columnLower[iColumn1]); newUpper = CoinMin(newUpper,columnUpper[iColumn1]); if (newLower>newUpper+primalTolerance_) { feasible=false; nChanged=-1; numberRowsLook=0; break; } columnLower[iColumn1]=newLower; columnUpper[iColumn1]=newUpper; #if DEBUG_SOME > 0 printf("Dropping doubleton row %d (status %d) keeping column %d (status %d) dropping %d (status %d) (mult,rhs %g %g) - nActions %d\n", iRow,getRowStatus(iRow),iColumn1,getColumnStatus(iColumn1),iColumn2,getColumnStatus(iColumn2),multiplier,rhs,nActions); #endif objective[iColumn1] -= objective[iColumn2]*multiplier; offset -= rowLower[iRow]*(objective[iColumn2]*multiplier); bool needDrop=false; if (newModel->getRowStatus(iRow)!=basic) { if (newModel->getColumnStatus(iColumn2)!=basic) { // On way back may as well have column basic newModel->setColumnStatus(iColumn2,basic); // need to drop basic if (newModel->getColumnStatus(iColumn1)==basic) { //setColumnStatus(iColumn1,superBasic); newModel->setColumnStatus(iColumn1,superBasic); } else { // not much we can do #if DEBUG_SOME > 0 printf("dropping but no basic a\n"); #endif } } else { // looks good } } else { if (newModel->getColumnStatus(iColumn2)!=basic) { // looks good } else { // need to keep a basic if (newModel->getColumnStatus(iColumn1)!=basic) { //setColumnStatus(iColumn2,superBasic); //setColumnStatus(iColumn1,basic); newModel->setColumnStatus(iColumn1,basic); } else { // not much we can do #if DEBUG_SOME > 0 printf("dropping but all basic a\n"); #endif needDrop=true; //setColumnStatus(iColumn2,superBasic); } } } int n=0; start = columnStart[iColumn1]; for (int i=start;i-1.0e30) rowLower[jRow] -= rhsMod; if (rowUpper[jRow]<1.0e30) rowUpper[jRow] -= rhsMod; if (!value) { array[jRow]=valueNew; whichRows2[n++]=jRow; } else { if (!valueNew) valueNew=1.0e-100; array[jRow]=valueNew; } } } columnLength[iColumn2]=0; start = columnStart[iColumn1]; if (n>columnLength[iColumn1]) { orderedMatrix=false; if (lastElement+n>lastGood) { // pack down CoinBigIndex put=lastElement; for (int iColumn=0;iColumngetRowStatus(jRow)!=basic) { newModel->setRowStatus(jRow,basic); needDrop=false; } } // take out of row copy int startR = rowStart[jRow]; int putR=startR; for (int i=startR;i1&&jRow 0 printf("Dropping null free row %d (status %d) - nActions %d\n", iRow,getRowStatus(iRow),nActions); #endif rowType[iRow]=1; clpPresolveInfo1_4_8 thisInfo; thisInfo.oldRowLower=(rowLower_[iRow]>-1.0e30) ? rowLower_[iRow]-rowLower[iRow] : rowLower[iRow]; thisInfo.oldRowUpper=(rowUpper_[iRow]<1.0e30) ? rowUpper_[iRow]-rowUpper[iRow] : rowUpper[iRow]; thisInfo.row=iRow; int n=rowLength[iRow]; CoinBigIndex start=rowStart[iRow]; thisInfo.lengthRow=n; //thisInfo.column=-1; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=1; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo1_4_8), n,column+start,elementByRow+start); // need to take out row CoinBigIndex end=start+n; rowLength[iRow]=0; for (CoinBigIndex k=start;k0 if (xxxxxx<-1000) nChanged=-1; #endif while (nChanged>0) { nChanged=0; int numberColumnsLook=0; for (int i=0;i0 #ifndef NDEBUG checkBasis(newModel, rowType, columnType); #endif #endif int iRow = whichRows[i]; // unmark assert ((rowStatus[iRow]&128)!=0); rowStatus[iRow] &= 127; if (rowLength[iRow]==1) { //rowType[iRow]=55; int iColumn = column[rowStart[iRow]]; if (/*columnType[iColumn]==14||*/columnType[iColumn]<-1) continue; if (!columnType[iColumn]) { columnType[iColumn]=55; whichColumns[numberColumnsLook++]=iColumn; nChanged++; } #if 0 } else if (rowLength[iRow]==2) { if (rowLower[iRow]==rowUpper[iRow]) { CoinBigIndex start = rowStart[iRow]; int iColumn1 = column[start]; int iColumn2 = column[start+1]; if (!columnType[iColumn1]&&!columnType[iColumn2]) { if (fabs(elementByRow[start])0 #ifndef NDEBUG checkBasis(newModel, rowType, columnType); #endif #endif nChanged++; int iColumn = whichColumns[iLook]; if (columnType[iColumn]!=55&&columnType[iColumn]>10) continue; if (columnType[iColumn]==55) columnType[iColumn]=0; CoinBigIndex start=columnStart[iColumn]; int jRowLower=-1; double newLower=columnLower[iColumn]; int jRowUpper=-1; double newUpper=columnUpper[iColumn]; double coefficientLower=0.0; double coefficientUpper=0.0; for (CoinBigIndex i=start;i=0); // adjust bounds double value = elementByRow[rowStart[iRow]]; double lower = newLower; double upper = newUpper; if (value>0.0) { if (rowUpper[iRow]<1.0e30) upper = rowUpper[iRow]/value; if (rowLower[iRow]>-1.0e30) lower = rowLower[iRow]/value; } else { if (rowUpper[iRow]<1.0e30) lower = rowUpper[iRow]/value; if (rowLower[iRow]>-1.0e30) upper = rowLower[iRow]/value; } if (lower>newLower+primalTolerance_) { if (lower>newUpper+primalTolerance_) { feasible=false; nChanged=-1; numberColumnsLook=0; break; } else if (lower>newUpper-primalTolerance_) { newLower=newUpper; } else { newLower = CoinMax(lower,newLower); } jRowLower=iRow; coefficientLower=value; } if (upper=0||jRowUpper>=0) { clpPresolveInfo2 thisInfo; if (jRowLower>=0) { thisInfo.oldRowLower=(rowLower_[jRowLower]>-1.0e30) ? rowLower_[jRowLower]-rowLower[jRowLower] : rowLower[jRowLower]; thisInfo.oldRowUpper=(rowUpper_[jRowLower]<1.0e30) ? rowUpper_[jRowLower]-rowUpper[jRowLower] : rowUpper[jRowLower]; thisInfo.row=jRowLower; thisInfo.coefficient=coefficientLower; } else { thisInfo.row=-1; #ifndef NDEBUG thisInfo.oldRowLower=COIN_DBL_MAX; thisInfo.oldRowUpper=-COIN_DBL_MAX; thisInfo.coefficient=0.0; #endif } if (jRowUpper>=0&&jRowLower!=jRowUpper) { thisInfo.oldRowLower2=(rowLower_[jRowUpper]>-1.0e30) ? rowLower_[jRowUpper]-rowLower[jRowUpper] : rowLower[jRowUpper]; thisInfo.oldRowUpper2=(rowUpper_[jRowUpper]<1.0e30) ? rowUpper_[jRowUpper]-rowUpper[jRowUpper] : rowUpper[jRowUpper]; thisInfo.row2=jRowUpper; thisInfo.coefficient2=coefficientUpper; } else { thisInfo.row2=-1; #ifndef NDEBUG thisInfo.oldRowLower2=COIN_DBL_MAX; thisInfo.oldRowUpper2=-COIN_DBL_MAX; thisInfo.coefficient2=0.0; #endif } thisInfo.oldColumnLower=columnLower[iColumn]; thisInfo.oldColumnUpper=columnUpper[iColumn]; columnLower[iColumn]=newLower; columnUpper[iColumn]=newUpper; thisInfo.column=iColumn; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo2), 0,NULL,NULL); infoA[nActions].type=2; nActions++; } for (CoinBigIndex i=start;i=0&&rowType[iRow]!=5) { #if DEBUG_SOME > 0 printf("Dropping singleton row %d (status %d) because of column %d (status %d) - jRow lower/upper %d/%d - nActions %d\n", iRow,getRowStatus(iRow),iColumn, getColumnStatus(iColumn),jRowLower,jRowUpper,nActions); #endif if (newModel->getRowStatus(iRow)!=basic) { //newModel->setRowStatus(iRow,basic); numberNonBasicSlacksOut++; } rowType[iRow]=1; if (iRow!=jRowLower&&iRow!=jRowUpper) { // mark as redundant infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); clpPresolveInfo1_4_8 thisInfo; thisInfo.oldRowLower=(rowLower_[iRow]>-1.0e30) ? rowLower_[iRow]-rowLower[iRow] : rowLower[iRow]; thisInfo.oldRowUpper=(rowUpper_[iRow]<1.0e30) ? rowUpper_[iRow]-rowUpper[iRow] : rowUpper[iRow]; thisInfo.row=iRow; int n=rowLength[iRow]; CoinBigIndex start=rowStart[iRow]; thisInfo.lengthRow=n; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo1_4_8), n,column+start,elementByRow+start); infoA[nActions].type=1; nActions++; } rowLength[iRow]=0; } else if (rowType[iRow]<=0) { row[put]=iRow; double value = element[i]; element[put++]=value; if (rowType[iRow]>=0&&iFlag<3) { assert(rowType[iRow]==0); double lower = rowLower[iRow]; double upper = rowUpper[iRow]; if (-1.0e20 < lower && upper < 1.0e20) { // bounded - we lose iFlag=-1; //break; } else if (-1.0e20 < lower || upper < 1.0e20) { nonFree++; } // see what this particular row says // jFlag == 2 ==> up is towards feasibility int jFlag = (value > 0.0 ? (upper > 1.0e20 ? 2 : 1) : (lower < -1.0e20 ? 2 : 1)); if (iFlag) { // check that it agrees with iFlag. if (iFlag!=jFlag) { iFlag=-1; } } else { // first row -- initialize iFlag iFlag=jFlag; } } else if (rowType[iRow]<0) { iFlag=-1; // be safe } } } // Do we need to switch status of iColumn? if (numberNonBasicSlacksOut>0) { // make iColumn non basic if possible if (newModel->getColumnStatus(iColumn)==basic) { newModel->setColumnStatus(iColumn,superBasic); } } double cost = objective[iColumn]*optimizationDirection_; int length = put-columnStart[iColumn]; if (!length) { if (!cost) { // put to closest to zero if (fabs(columnLower[iColumn])0.0) { iFlag=1; } else { iFlag=2; } } else { if (cost>0.0&&iFlag==2) iFlag=-1; else if (cost<0.0&&iFlag==1) iFlag=-1; } columnLength[iColumn]=length; //#define NO_MOVABLE #ifdef NO_MOVABLE iFlag=-1; #endif if (iFlag>0&&nonFree) { double newValue; if (iFlag==2) { // fix to upper newValue =CoinMin(columnUpper[iColumn],1.0e20); } else { // fix to lower newValue =CoinMax(columnLower[iColumn],-1.0e20); } columnActivity_[iColumn]=newValue; #if DEBUG_SOME > 0 if (newModel->getColumnStatus(iColumn)== basic) { // ? move basic back onto sub if can? iFlag += 2; } printf("Dropping movable column %d - iFlag %d - jRow lower/upper %d/%d - nActions %d\n", iColumn,iFlag,jRowLower,jRowUpper,nActions); #endif columnType[iColumn]=11; if (newModel->getColumnStatus(iColumn)== basic) { // need to put status somewhere else int shortestNumber=numberColumns_; int shortest=-1; for (int j=start;jgetRowStatus(iRow)!= basic) { shortest=iRow; shortestNumber = rowLength[iRow]; } } if (shortest>=0) { // make basic newModel->setRowStatus(shortest,basic); newModel->setColumnStatus(iColumn,superBasic); } else { // put on a column shortestNumber=numberColumns_; shortest=-1; for (int j=start;jgetColumnStatus(jColumn)!= basic) { shortest=jColumn; shortestNumber = rowLength[iRow]; } } } } if (shortest>=0) { // make basic newModel->setColumnStatus(shortest,basic); } else { #if DEBUG_SOME > 0 printf("what now - dropping - basic\n"); #endif } } } clpPresolveInfo11 thisInfo; thisInfo.oldColumnLower=columnLower[iColumn]; thisInfo.oldColumnUpper=columnUpper[iColumn]; thisInfo.fixedTo=newValue; columnLower[iColumn]=newValue; columnUpper[iColumn]=newValue; thisInfo.column=iColumn; int n=columnLength[iColumn]; CoinBigIndex start=columnStart[iColumn]; thisInfo.lengthColumn=n; infoA[nActions].infoOffset=static_cast(stuff.putStuff-startStuff); infoA[nActions].type=11; nActions++; ClpCopyToMiniSave(stuff,reinterpret_cast(&thisInfo),sizeof(clpPresolveInfo11), n,row+start,element+start); // adjust rhs and take out of rows columnLength[iColumn]=0; nChanged++; for (int j=start;j-1.0e20) rowLower[iRow]=lower-value; double upper = rowUpper[iRow]; if (upper<1.0e20) rowUpper[iRow]=upper-value; // take out of row copy (and put on list) assert (rowType[iRow]<=0&&rowType[iRow]>-2); // See if already marked (will get to row later in loop if ((rowStatus[iRow]&128)==0) { rowStatus[iRow] |= 128; whichRows[numberRowsLook++]=iRow; assert (numberRowsLook<=numberRows_); } int start = rowStart[iRow]; int put=start; for (int i=start;ieventWithInfo(ClpEventHandler::moreMiniPresolve,&moreInfo); newModel->setObjectiveOffset(offset); int nChar2 = nActions*static_cast(sizeof(clpPresolveInfo))+static_cast(stuff.putStuff-startStuff); clpPresolveInfo * infoData = reinterpret_cast(new char[nChar2]); memcpy(infoData,infoA,nActions*sizeof(clpPresolveInfo)); char * info2 = reinterpret_cast(infoData+nActions); memcpy(info2,startStuff,stuff.putStuff-startStuff); listInfo * infoNew = new listInfo; infoNew->numberEntries=nActions; infoNew->maximumEntries=nActions; infoNew->start=infoData; infoNew->numberInitial=numberInitial; *infoOut=infoNew; int nRows=0; for (int iRow=0;iRow0) whichRows[nRows++]=iRow; } int nColumns=0; for (int iColumn=0;iColumn10) whichColumns[nColumns++]=iColumn; } #ifdef FUNNY_CHECK { CoinPackedMatrix rowCopy2 = *this->matrix(); rowCopy2.reverseOrdering(); int * column2 = rowCopy2.getMutableIndices(); CoinBigIndex * rowStart2 = rowCopy2.getMutableVectorStarts(); double * elementByRow2 = rowCopy2.getMutableElements(); int * rowLength2 = rowCopy2.getMutableVectorLengths(); printf("Odd rows\n"); for (int iRow=0;iRow ",iRow); for (CoinBigIndex j=start;j= %g/%g\n",rowLower[iRow],rowLower_[iRow]); } } printf("now columns\n"); for (int iColumn=0;iColumn 0 printf("%d Row types and lookup\n",nRows); int nBNew=0; int iNew=0; for (int iRow=0;iRowgetRowStatus(iRow)==basic) { nBNew++; xNew='B'; } printf("%d -> %d type %d - new status %c\n",iRow,iNew,rowType[iRow],xNew); iNew++; } } printf("%d Column types and lookup\n",nColumns); iNew=0; for (int iColumn=0;iColumngetColumnStatus(iColumn)==basic) { nBNew++; xNew='B'; } printf("%d -> %d type %d - new status %c\n",iColumn,iNew,columnType[iColumn],xNew); iNew++; } } printf("Deleting %d rows (now %d) and %d columns (%d basic)\n",nRows,numberRows_-nRows, nColumns,nBNew); #else #if DEBUG_SOME >0 printf("Deleting %d rows (now %d) and %d columns\n",nRows,numberRows_-nRows, nColumns); #endif #endif #if 0 newModel->deleteRows(nRows,whichRows); newModel->deleteColumns(nColumns,whichColumns); #else newModel->deleteRowsAndColumns(nRows,whichRows,nColumns,whichColumns); #endif } else { delete newModel; newModel=NULL; *infoOut=NULL; } delete [] whichRows; delete [] infoA; delete [] startStuff; delete [] array; return newModel; } // After mini presolve void ClpSimplex::miniPostsolve(const ClpSimplex * presolvedModel, void * infoIn) { int numberTotal=numberRows_+numberColumns_; listInfo * infoX = reinterpret_cast(infoIn); int nActions=infoX->numberEntries; #if DEBUG_SOME > 0 #ifndef NDEBUG int numberInitial=infoX->numberInitial; #endif #endif clpPresolveInfo * infoA = infoX->start; char * startStuff = reinterpret_cast(infoA+nActions); // move status and solution across int numberColumns2=presolvedModel->numberColumns(); const double * solution2 = presolvedModel->primalColumnSolution(); unsigned char * rowStatus2 = presolvedModel->statusArray()+numberColumns2; unsigned char * columnStatus2 = presolvedModel->statusArray(); unsigned char * rowStatus = status_+numberColumns_; unsigned char * columnStatus = status_; char * rowType = new char [numberTotal]; memset(rowType,0,numberTotal); char * columnType = rowType+numberRows_; double * rowLowerX = new double [3*numberRows_+3*numberColumns_+CoinMax(numberRows_,numberColumns_)]; double * rowUpperX = rowLowerX+numberRows_; double * columnLowerX = rowUpperX+numberRows_; double * columnUpperX = columnLowerX+numberColumns_; double * objectiveX = columnUpperX+numberColumns_; double * tempElement = objectiveX+numberColumns_; double * array = tempElement+CoinMax(numberRows_,numberColumns_); memset(array,0,numberRows_*sizeof(double)); int * tempIndex = new int [CoinMax(numberRows_,numberColumns_)+4+2*numberColumns_+numberRows_]; int * forward = tempIndex+CoinMax(numberRows_,numberColumns_)+1; int * backward = forward + numberColumns_+2; int * whichRows2 = backward + numberColumns_+1; for (int i=-1;igetIndices(); const CoinBigIndex * columnStart = matrix()->getVectorStarts(); const int * columnLength = matrix()->getVectorLengths(); const double * element = matrix()->getElements(); // forwards so dropped column at end for (int i=0;i(type); } break; case 2: // sub { clpPresolveInfo2 thisInfo; memcpy(&thisInfo,getStuff,sizeof(clpPresolveInfo2)); iRow = thisInfo.row; if (iRow>=0) rowType[iRow]=2; iRow = thisInfo.row2; if (iRow>=0) rowType[iRow]=2; iColumn = thisInfo.column; columnType[iColumn]=2; } break; case 11: // movable column { clpPresolveInfo11 thisInfo; memcpy(&thisInfo,getStuff,sizeof(clpPresolveInfo11)); iColumn = thisInfo.column; columnType[iColumn]=11; } break; case 13: // empty column { clpPresolveInfo13 thisInfo; memcpy(&thisInfo,getStuff,sizeof(clpPresolveInfo13)); iColumn = thisInfo.column; columnType[iColumn]=13; } break; case 14: // doubleton { clpPresolveInfo14 thisInfo; memcpy(&thisInfo,getStuff,sizeof(clpPresolveInfo14)); iRow = thisInfo.row; iColumn = thisInfo.column; int iColumn2 = thisInfo.column2; columnType[iColumn]=3; columnType[iColumn2]=14; rowType[iRow]=3; } break; } #if DEBUG_SOME > 0 printf("Action %d type %d row %d column %d\n", i,type,iRow,iColumn); #endif } int iGet=0; const double * rowLowerY = presolvedModel->rowLower(); const double * rowUpperY = presolvedModel->rowUpper(); for (int iRow=0;iRowrowActivity_[iGet]; dual_[iRow]=presolvedModel->dual_[iGet]; rowLowerX[iRow]=rowLowerY[iGet]; rowUpperX[iRow]=rowUpperY[iGet]; tempIndex[iGet]=iRow; iGet++; } else { setRowStatus(iRow,basic); } } assert (iGet==presolvedModel->numberRows()); CoinPackedMatrix matrixX; int numberElementsOriginal=matrix_->getNumElements(); const int * rowY = presolvedModel->matrix()->getIndices(); const CoinBigIndex * columnStartY = presolvedModel->matrix()->getVectorStarts(); const int * columnLengthY = presolvedModel->matrix()->getVectorLengths(); const double * elementY = presolvedModel->matrix()->getElements(); iGet=0; CoinBigIndex put=0; for (int iColumn=0;iColumncolumnLower(); const double * columnUpperY = presolvedModel->columnUpper(); iGet=0; put=0; memcpy(objectiveX,this->objective(),numberColumns_*sizeof(double)); const double * objectiveY=presolvedModel->objective(); for (int iColumn=0;iColumn=0) next += CoinMax(columnLength[iColumn]-columnLengthY[iGet],0)+spare; columnStatus[iColumn]=columnStatus2[iGet]; columnActivity_[iColumn]=solution2[iGet]; columnLowerX[iColumn]=columnLowerY[iGet]; columnUpperX[iColumn]=columnUpperY[iGet]; columnLengthX[iColumn]=columnLengthY[iGet]; objectiveX[iColumn]=objectiveY[iGet]; for (CoinBigIndex j=columnStartY[iGet];jcolumnActivity_[iGet]; iGet++; columnType[iColumn]=0; put = next; } else { put += CoinMax(columnLength[iColumn]+spare,0); columnActivity_[iColumn]=0.0; columnType[iColumn]=1; columnLengthX[iColumn]=0; setColumnStatus(iColumn,superBasic); } } assert (put<=lastElement); columnStartX[numberColumns_]=lastElement+numberElementsOriginal; assert (put<=lastElement); assert (iGet==numberColumns2); matrixX.times(columnActivity_,rowActivity_); if (optimizationDirection_<0) { for (int i=0;i 0 double * tempRhs=new double[numberRows_]; #endif #ifndef NDEBUG bool checkMatrixAtEnd=true; #endif for (int i=nActions-1;i>=0;i--) { #if DEBUG_SOME > 0 #if 1 //ndef NDEBUG memset(tempRhs,0,numberRows_*sizeof(double)); for (int iColumn=0;iColumncolumnUpper_[iColumn]+1.0e-5) //printf ("Bad column %d %g <= %g <= %g\n",iColumn, // columnLower_[iColumn],columnActivity_[iColumn],columnUpper_[iColumn]); double value=columnActivity_[iColumn]; for (CoinBigIndex j=columnStartX[iColumn]; j1.0e-4) printf("Row %d temprhs %g rowActivity_ %g\n",iRow,tempRhs[iRow], rowActivity_[iRow]); if (tempRhs[iRow]rowUpperX[iRow]+1.0e-4) { printf("Row %d %g %g %g\n",iRow,rowLowerX[iRow], tempRhs[iRow],rowUpperX[iRow]); nBadRow++; } } assert (!nBadRow); #endif #ifndef NDEBUG if (i>=numberInitial&&true) { for (int iColumn=0;iColumn10.0*dualTolerance_&& columnActivity_[iColumn]>columnLowerX[iColumn]+primalTolerance_) printf("bad dj on column %d lb dj %g in/out %c\n",iColumn,djValue,inOut); else if (djValue<-10.0*dualTolerance_&& columnActivity_[iColumn]0 printf("Action %d type %d\n",i,type); #ifndef NDEBUG checkBasis(this, rowType, columnType); #endif #endif switch (type) { case 1: case 4: case 8: case 9: // redundant { #ifndef NDEBUG if (type==4) checkMatrixAtEnd=false; #endif clpPresolveInfo8 thisInfo; copyFromSave(restore,infoA[i],&thisInfo); iRow = thisInfo.row; // Insert row and modify RHS #ifdef CLP_USER_DRIVEN if (type>=8) { thisInfo.tempElement=tempElement; thisInfo.tempIndex=tempIndex; thisInfo.rowLowerX=rowLowerX; thisInfo.rowUpperX=rowUpperX; eventHandler_->eventWithInfo(ClpEventHandler::modifyMatrixInMiniPostsolve,&thisInfo); } else { #endif if (rowLower_[iRow]>-1.0e30) rowLowerX[iRow]=rowLower_[iRow]-thisInfo.oldRowLower; else rowLowerX[iRow]=thisInfo.oldRowLower; if (rowUpper_[iRow]<1.0e30) rowUpperX[iRow]=rowUpper_[iRow]-thisInfo.oldRowUpper; else rowUpperX[iRow]=thisInfo.oldRowUpper; #ifdef CLP_USER_DRIVEN } #endif int n=thisInfo.lengthRow; double rhs=0.0; for (int i=0;i=0) { rowType[jRowLower]=0; if (rowLower_[jRowLower]>-1.0e30) rowLowerX[jRowLower]=rowLower_[jRowLower]-thisInfo.oldRowLower; else rowLowerX[jRowLower]=thisInfo.oldRowLower; if (rowUpper_[jRowLower]<1.0e30) rowUpperX[jRowLower]=rowUpper_[jRowLower]-thisInfo.oldRowUpper; else rowUpperX[jRowLower]=thisInfo.oldRowUpper; columnLengthX[iColumn]++; rowX[start+length]=jRowLower; elementX[start+length]=valueLower; rowActivity_[jRowLower]=valueLower*columnActivity_[iColumn]; // start off with slack basic setRowStatus(jRowLower,basic); length++; } if (jRowUpper>=0) { rowType[jRowUpper]=0; if (rowLower_[jRowUpper]>-1.0e30) rowLowerX[jRowUpper]=rowLower_[jRowUpper]-thisInfo.oldRowLower2; else rowLowerX[jRowUpper]=thisInfo.oldRowLower2; if (rowUpper_[jRowUpper]<1.0e30) rowUpperX[jRowUpper]=rowUpper_[jRowUpper]-thisInfo.oldRowUpper2; else rowUpperX[jRowUpper]=thisInfo.oldRowUpper2; columnLengthX[iColumn]++; rowX[start+length]=jRowUpper; elementX[start+length]=valueUpper; rowActivity_[jRowUpper]=valueUpper*columnActivity_[iColumn]; // start off with slack basic setRowStatus(jRowUpper,basic); length++; } double djValue = objectiveX[iColumn]; for (CoinBigIndex j=columnStartX[iColumn]; jthisInfo.oldColumnLower+primalTolerance_&& solValuedualTolerance_; } if (solValue<=thisInfo.oldColumnLower+primalTolerance_&&djValue<-dualTolerance_) { #if DEBUG_SOME > 1 printf("odd column %d at lb of %g has dj of %g\n", iColumn,thisInfo.oldColumnLower,djValue); #endif hasToBeBasic=true; } else if (solValue>=thisInfo.oldColumnUpper-primalTolerance_&&djValue>dualTolerance_) { #if DEBUG_SOME > 1 printf("odd column %d at ub of %g has dj of %g\n", iColumn,thisInfo.oldColumnUpper,djValue); #endif hasToBeBasic=true; } if (hasToBeBasic) { if (jRowLower>=0&&jRowUpper>=0) { // choose #if DEBUG_SOME > 1 printf("lower row %d %g <= %g <= %g\n", jRowLower,rowLowerX[jRowLower],rowActivity_[jRowLower], rowUpperX[jRowLower]); #endif double awayLower = CoinMin(rowActivity_[jRowLower]-rowLowerX[jRowLower], rowUpperX[jRowLower]-rowActivity_[jRowLower]); #if DEBUG_SOME > 1 printf("upper row %d %g <= %g <= %g\n", jRowUpper,rowLowerX[jRowUpper],rowActivity_[jRowUpper], rowUpperX[jRowUpper]); #endif double awayUpper = CoinMin(rowActivity_[jRowUpper]-rowLowerX[jRowUpper], rowUpperX[jRowUpper]-rowActivity_[jRowUpper]); if (awayLower>awayUpper) jRowLower=-1; } if (jRowLower<0) { setRowStatus(jRowUpper,superBasic); setColumnStatus(iColumn,basic); dual_[jRowUpper]=djValue/valueUpper; } else { setRowStatus(jRowLower,superBasic); setColumnStatus(iColumn,basic); dual_[jRowLower]=djValue/valueLower; } } } columnLowerX[iColumn]=thisInfo.oldColumnLower; columnUpperX[iColumn]=thisInfo.oldColumnUpper; } break; case 11: // movable column { clpPresolveInfo11 thisInfo; copyFromSave(restore,infoA[i],&thisInfo); iColumn = thisInfo.column; columnType[iColumn]=0; assert (!columnLengthX[iColumn]); int newLength=thisInfo.lengthColumn; CoinBigIndex start=columnStartX[iColumn]; int nextColumn=forward[iColumn]; CoinBigIndex startNext=columnStartX[nextColumn]; if (start+newLength>startNext) { // need more moveAround(numberColumns_,numberElementsOriginal, iColumn,newLength, forward,backward,columnStartX,columnLengthX, rowX,elementX); start=columnStartX[iColumn]; } columnLengthX[iColumn]=newLength; memcpy(rowX+start,tempIndex,newLength*sizeof(int)); memcpy(elementX+start,tempElement,newLength*sizeof(double)); double solValue=thisInfo.fixedTo; columnActivity_[iColumn]=solValue; if (solValue) { for (int j=columnStartX[iColumn]; j-1.0e30) rowLowerX[jRow] += value; if (rowUpperX[jRow]<1.0e30) rowUpperX[jRow] += value; } } double djValue = objectiveX[iColumn]; for (CoinBigIndex j=columnStartX[iColumn]; jthisInfo.oldColumnLower+primalTolerance_&& solValuedualTolerance_; } if (solValue<=thisInfo.oldColumnLower+primalTolerance_&&djValue<-dualTolerance_) { #if DEBUG_SOME > 1 printf("odd column %d at lb of %g has dj of %g\n", iColumn,thisInfo.oldColumnLower,djValue); #endif hasToBeBasic=true; } else if (solValue>=thisInfo.oldColumnUpper-primalTolerance_&&djValue>dualTolerance_) { #if DEBUG_SOME > 1 printf("odd column %d at ub of %g has dj of %g\n", iColumn,thisInfo.oldColumnUpper,djValue); #endif hasToBeBasic=true; } if (hasToBeBasic) { //abort(); //setRowStatus(iRow,superBasic); setColumnStatus(iColumn,basic); //dual_[iRow]=djValue/value; } } columnLowerX[iColumn]=thisInfo.oldColumnLower; columnUpperX[iColumn]=thisInfo.oldColumnUpper; } break; case 13: // empty (or initially fixed) column { clpPresolveInfo13 thisInfo; copyFromSave(restore,infoA[i],&thisInfo); iColumn = thisInfo.column; columnType[iColumn]=0; columnLowerX[iColumn]=thisInfo.oldColumnLower; columnUpperX[iColumn]=thisInfo.oldColumnUpper; assert (!columnLengthX[iColumn]); int newLength=columnLength[iColumn]; CoinBigIndex startOriginal = columnStart[iColumn]; double solValue=columnLower_[iColumn]; columnActivity_[iColumn]=solValue; if (newLength&&solValue) { for (int j=startOriginal;j-1.0e20) rowLowerX[iRow]=lower+value; double upper = rowUpperX[iRow]; if (upper<1.0e20) rowUpperX[iRow]=upper+value; } } #ifndef NDEBUG // copy from original CoinBigIndex start=columnStartX[iColumn]; int nextColumn=forward[iColumn]; CoinBigIndex startNext=columnStartX[nextColumn]; if (start+newLength>startNext) { // need more moveAround(numberColumns_,numberElementsOriginal, iColumn,newLength, forward,backward,columnStartX,columnLengthX, rowX,elementX); start=columnStartX[iColumn]; } columnLengthX[iColumn]=newLength; memcpy(rowX+start,row+startOriginal,newLength*sizeof(int)); memcpy(elementX+start,element+startOriginal,newLength*sizeof(double)); #endif } break; case 14: // doubleton { clpPresolveInfo14 thisInfo; copyFromSave(restore,infoA[i],&thisInfo); iRow = thisInfo.row; rowType[iRow]=0; int iColumn1 = thisInfo.column; int iColumn2 = thisInfo.column2; columnType[iColumn2]=0; double value1=thisInfo.value1; int length=columnLengthX[iColumn1]; CoinBigIndex start=columnStartX[iColumn1]; for (int i=0;istartNext) { // need more moveAround(numberColumns_,numberElementsOriginal, iColumn2,newLength, forward,backward,columnStartX,columnLengthX, rowX,elementX); start=columnStartX[iColumn2]; } columnLengthX[iColumn2]=newLength; memcpy(rowX+start,tempIndex,newLength*sizeof(int)); memcpy(elementX+start,tempElement,newLength*sizeof(double)); double value2=0.0; for (int i=0;i-1.0e30) rowLowerX[jRow] += rhsMod; if (rowUpperX[jRow]<1.0e30) rowUpperX[jRow] += rhsMod; rowActivity_[jRow] += rhsMod; if (!value) { array[jRow]=valueNew; whichRows2[n++]=jRow; } else { if (!valueNew) valueNew=1.0e-100; array[jRow]=valueNew; } } length=0; for (int i=0;istartNext) { // need more moveAround(numberColumns_,numberElementsOriginal, iColumn1,length, forward,backward,columnStartX,columnLengthX, rowX,elementX); start=columnStartX[iColumn1]; } columnLengthX[iColumn1]=length; memcpy(rowX+start,tempIndex,length*sizeof(int)); memcpy(elementX+start,tempElement,length*sizeof(double)); objectiveX[iColumn2]=thisInfo.oldObjective2; objectiveX[iColumn1] += objectiveX[iColumn2]*multiplier; //offset += rhs*(objectiveX[iColumn2]*multiplier); double value = multiplier1-columnActivity_[iColumn1]*multiplier; #if DEBUG_SOME > 0 printf("type14 column2 %d rhs %g value1 %g - value %g\n", iColumn2,thisInfo.rhs,thisInfo.value1,value); #endif columnActivity_[iColumn2]=value; double djValue1 = objectiveX[iColumn1]; for (CoinBigIndex j=columnStartX[iColumn1]; jdualTolerance_&&solValue>=upperValue-primalTolerance_) bad1=dj1; } double dj2 = djValue2-value2*pi; double bad2=0.0; if (!fixed2) { if (dj2<-dualTolerance_&&solValue2<=lowerValue2+primalTolerance_) bad2=-dj2; else if (dj2>dualTolerance_&&solValue2>=upperValue2-primalTolerance_) bad2=dj2; } if (CoinMax(bad1,bad2)lowerValue+primalTolerance_&& solValuedualTolerance_) choice=1; } else if (solValue2>lowerValue2+primalTolerance_&& solValue2dualTolerance_) choice=2; } if (choice==1) { // iColumn1 in basis setRowStatus(iRow,superBasic); setColumnStatus(iColumn1,basic); dual_[iRow]=djValue1/value1; } else if (choice==2) { // iColumn2 in basis setRowStatus(iRow,superBasic); setColumnStatus(iColumn2,basic); dual_[iRow]=djValue2/value2; } } else { if (fabs(djValue1)>10.0*dualTolerance_) { // iColumn2 in basis setRowStatus(iRow,superBasic); setColumnStatus(iColumn2,basic); dual_[iRow]=djValue2/value2; } else { // do we need iColumn2 in basis double solValue2 = columnActivity_[iColumn2]; double lowerValue2 = columnLowerX[iColumn2]; double upperValue2 = columnUpperX[iColumn2]; if (solValue2>lowerValue2+primalTolerance_&& solValue21.0e-4|| fabs(rowUpper_[iRow]-rowUpperX[iRow])>1.0e-4) printf("USER row %d lower,x %g %g upper,x %g %g\n",iRow,rowLower_[iRow],rowLowerX[iRow], rowUpper_[iRow],rowUpperX[iRow]); #endif } double * objective = this->objective(); for (int iColumn=0;iColumn0 matrix()->times(columnActivity_,rowActivity_); for (int i=0;i=columnLower_[i]-1.0e-5&& columnActivity_[i]<=columnUpper_[i]+1.0e-5); int nBad=0; for (int i=0;irowUpper_[i]+1.0e-5) { printf("Row %d %g %g %g\n",i,rowLower_[i], rowActivity_[i],rowUpper_[i]); nBad++; } } ClpTraceDebug (!nBad); #endif #if 1 //DEBUG_SOME > 0 delete [] tempRhs; #endif delete infoX; delete [] infoA; delete [] rowLowerX; } Clp-1.15.10/src/ClpConstraintQuadratic.cpp0000644000076600007660000002471011510657452017001 0ustar coincoin/* $Id: ClpConstraintQuadratic.cpp 1665 2011-01-04 17:55:54Z 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). #include "CoinPragma.hpp" #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "ClpConstraintQuadratic.hpp" #include "CoinSort.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic () : ClpConstraint() { type_ = 0; start_ = NULL; column_ = NULL; coefficient_ = NULL; numberColumns_ = 0; numberCoefficients_ = 0; numberQuadraticColumns_ = 0; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic (int row, int numberQuadraticColumns , int numberColumns, const CoinBigIndex * start, const int * column, const double * coefficient) : ClpConstraint() { type_ = 0; rowNumber_ = row; numberColumns_ = numberColumns; numberQuadraticColumns_ = numberQuadraticColumns; start_ = CoinCopyOfArray(start, numberQuadraticColumns + 1); int numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(column, numberElements); coefficient_ = CoinCopyOfArray(coefficient, numberElements); char * mark = new char [numberQuadraticColumns_]; memset(mark, 0, numberQuadraticColumns_); int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert (jColumn < numberQuadraticColumns_); mark[jColumn] = 1; } mark[iColumn] = 1; } } numberCoefficients_ = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (mark[iColumn]) numberCoefficients_++; } delete [] mark; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic (const ClpConstraintQuadratic & rhs) : ClpConstraint(rhs) { numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; numberQuadraticColumns_ = rhs.numberQuadraticColumns_; start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); int numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(rhs.column_, numberElements); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpConstraintQuadratic::~ClpConstraintQuadratic () { delete [] start_; delete [] column_; delete [] coefficient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpConstraintQuadratic & ClpConstraintQuadratic::operator=(const ClpConstraintQuadratic& rhs) { if (this != &rhs) { delete [] start_; delete [] column_; delete [] coefficient_; numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; numberQuadraticColumns_ = rhs.numberQuadraticColumns_; start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); int numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(rhs.column_, numberElements); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpConstraint * ClpConstraintQuadratic::clone() const { return new ClpConstraintQuadratic(*this); } // Returns gradient int ClpConstraintQuadratic::gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue, double & offset, bool useScaling, bool refresh) const { if (refresh || !lastGradient_) { offset_ = 0.0; functionValue_ = 0.0; if (!lastGradient_) lastGradient_ = new double[numberColumns_]; CoinZeroN(lastGradient_, numberColumns_); bool scaling = (model && model->rowScale() && useScaling); if (!scaling) { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { double valueJ = solution[jColumn]; double elementValue = coefficient_[j]; if (iColumn != jColumn) { offset_ -= valueI * valueJ * elementValue; double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; lastGradient_[iColumn] += gradientI; lastGradient_[jColumn] += gradientJ; } else { offset_ -= 0.5 * valueI * valueI * elementValue; double gradientI = valueI * elementValue; lastGradient_[iColumn] += gradientI; } } else { // linear part lastGradient_[iColumn] += coefficient_[j]; functionValue_ += valueI * coefficient_[j]; } } } functionValue_ -= offset_; } else { abort(); // do scaling const double * columnScale = model->columnScale(); for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; // already scaled double coefficient = coefficient_[i] * columnScale[iColumn]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } } functionValue = functionValue_; offset = offset_; CoinMemcpyN(lastGradient_, numberColumns_, gradient); return 0; } // Resize constraint void ClpConstraintQuadratic::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { abort(); #ifndef NDEBUG int lastColumn = column_[numberCoefficients_-1]; #endif assert (newNumberColumns > lastColumn); delete [] lastGradient_; lastGradient_ = NULL; numberColumns_ = newNumberColumns; } } // Delete columns in constraint void ClpConstraintQuadratic::deleteSome(int numberToDelete, const int * which) { if (numberToDelete) { abort(); int i ; char * deleted = new char[numberColumns_]; memset(deleted, 0, numberColumns_ * sizeof(char)); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { deleted[j] = 1; } } int n = 0; for (i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; if (!deleted[iColumn]) { column_[n] = iColumn; coefficient_[n++] = coefficient_[i]; } } numberCoefficients_ = n; } } // Scale constraint void ClpConstraintQuadratic::reallyScale(const double * ) { abort(); } /* Given a zeroed array sets nonquadratic columns to 1. Returns number of nonlinear columns */ int ClpConstraintQuadratic::markNonlinear(char * which) const { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert (jColumn < numberQuadraticColumns_); which[jColumn] = 1; which[iColumn] = 1; } } } int numberCoefficients = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (which[iColumn]) numberCoefficients++; } return numberCoefficients; } /* Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ int ClpConstraintQuadratic::markNonzero(char * which) const { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert (jColumn < numberQuadraticColumns_); which[jColumn] = 1; } which[iColumn] = 1; } } int numberCoefficients = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (which[iColumn]) numberCoefficients++; } return numberCoefficients; } // Number of coefficients int ClpConstraintQuadratic::numberCoefficients() const { return numberCoefficients_; } Clp-1.15.10/src/ClpObjective.hpp0000644000076600007660000001026311662222261014726 0ustar coincoin/* $Id: ClpObjective.hpp 1825 2011-11-20 16:02:57Z 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 ClpObjective_H #define ClpObjective_H //############################################################################# class ClpSimplex; class ClpModel; /** Objective Abstract Base Class Abstract Base Class for describing an objective function */ class ClpObjective { public: ///@name Stuff //@{ /** Returns gradient. If Linear 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) = 0; /** Returns reduced gradient.Returns an offset (to be added to current one). */ virtual double reducedGradient(ClpSimplex * model, double * region, bool useFeasibleCosts) = 0; /** 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) = 0; /// Return objective value (without any ClpModel offset) (model may be NULL) virtual double objectiveValue(const ClpSimplex * model, const double * solution) const = 0; /// Resize objective virtual void resize(int newNumberColumns) = 0; /// Delete columns in objective virtual void deleteSome(int numberToDelete, const int * which) = 0; /// Scale objective virtual void reallyScale(const double * columnScale) = 0; /** 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 ClpObjective(); /// Copy constructor ClpObjective(const ClpObjective &); /// Assignment operator ClpObjective & operator=(const ClpObjective& rhs); /// Destructor virtual ~ClpObjective (); /// Clone virtual ClpObjective * clone() const = 0; /** Subset clone. Duplicates are allowed and order is as given. Derived classes need not provide this as it may not always make sense */ virtual ClpObjective * subsetClone (int numberColumns, const int * whichColumns) const; //@} ///@name Other //@{ /// Returns type (above 63 is extra information) inline int type() const { return type_; } /// Sets type (above 63 is extra information) inline void setType(int value) { type_ = value; } /// Whether activated inline int activated() const { return activated_; } /// Set whether activated inline void setActivated(int value) { activated_ = value; } /// Objective offset inline double nonlinearOffset () const { return offset_; } //@} //--------------------------------------------------------------------------- protected: ///@name Protected member data //@{ /// Value of non-linear part of objective double offset_; /// Type of objective - linear is 1 int type_; /// Whether activated int activated_; //@} }; #endif Clp-1.15.10/src/AbcSimplexFactorization.hpp0000644000076600007660000003360412101105055017133 0ustar coincoin/* $Id: AbcSimplexFactorization.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef AbcSimplexFactorization_H #define AbcSimplexFactorization_H #include "CoinPragma.hpp" #include "CoinAbcCommon.hpp" #include "CoinAbcFactorization.hpp" #include "AbcMatrix.hpp" //#include "CoinAbcAnyFactorization.hpp" #include "AbcSimplex.hpp" class ClpFactorization; /** This just implements AbcFactorization when an AbcMatrix object is passed. */ class AbcSimplexFactorization { public: /**@name factorization */ //@{ /** When part of LP - given by basic variables. Actually does factorization. Arrays passed in have non negative value to say basic. If status is okay, basic variables have pivot row - this is only needed if increasingRows_ >1. Allows scaling If status is singular, then basic variables have pivot row and ones thrown out have -1 returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ int factorize (AbcSimplex * model, int solveType, bool valuesPass); #ifdef EARLY_FACTORIZE /// Returns -2 if can't, -1 if singular, -99 memory, 0 OK inline int factorize (AbcSimplex * model, CoinIndexedVector & stuff) { return coinAbcFactorization_->factorize(model,stuff);} #endif //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ AbcSimplexFactorization(int numberRows=0); /** Destructor */ ~AbcSimplexFactorization(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ AbcSimplexFactorization(const AbcSimplexFactorization&, int denseIfSmaller = 0); AbcSimplexFactorization& operator=(const AbcSimplexFactorization&); /// Sets factorization void setFactorization(AbcSimplexFactorization & rhs); //@} /* **** below here is so can use networkish basis */ /**@name rank one updates which do exist */ //@{ /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update already in U */ inline #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * regionSparse, int pivotRow) {return coinAbcFactorization_->checkReplacePart1(regionSparse,pivotRow);} /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update in vector */ inline #ifdef ABC_LONG_FACTORIZATION long #endif double checkReplacePart1 ( CoinIndexedVector * regionSparse, CoinIndexedVector * partialUpdate, int pivotRow) {return coinAbcFactorization_->checkReplacePart1(regionSparse,partialUpdate,pivotRow);} /** Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update already in U */ inline void checkReplacePart1a ( CoinIndexedVector * regionSparse, int pivotRow) {coinAbcFactorization_->checkReplacePart1a(regionSparse,pivotRow);} inline double checkReplacePart1b (CoinIndexedVector * regionSparse, int pivotRow) {return coinAbcFactorization_->checkReplacePart1b(regionSparse,pivotRow);} /** Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ inline int checkReplacePart2 ( int pivotRow, double btranAlpha, double ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha) {return coinAbcFactorization_->checkReplacePart2(pivotRow,btranAlpha,ftranAlpha,ftAlpha);} #ifdef ABC_LONG_FACTORIZATION /// Clear all hidden arrays inline void clearHiddenArrays() { coinAbcFactorization_->clearHiddenArrays();} #endif /** Replaces one Column to basis, partial update already in U */ void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ); /** Replaces one Column to basis, partial update in vector */ void replaceColumnPart3 ( const AbcSimplex * model, CoinIndexedVector * regionSparse, CoinIndexedVector * tableauColumn, CoinIndexedVector * partialUpdate, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha ); #ifdef EARLY_FACTORIZE /// 0 success, -1 can't +1 accuracy problems inline int replaceColumns ( const AbcSimplex * model, CoinIndexedVector & stuff, int firstPivot,int lastPivot,bool cleanUp) { return coinAbcFactorization_->replaceColumns(model,stuff,firstPivot,lastPivot,cleanUp);} #endif //@} /**@name various uses of factorization (return code number elements) which user may want to know about */ //@{ #if 0 /** Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room region1 starts as zero and is zero at end */ int updateColumnFT ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2); /** Updates one column (FTRAN) from region2 region1 starts as zero and is zero at end */ int updateColumn ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const; /** Updates one column (FTRAN) from region2 Tries to do FT update number returned is negative if no room. Also updates region3 region1 starts as zero and is zero at end */ int updateTwoColumnsFT ( CoinIndexedVector * regionSparse1, CoinIndexedVector * regionSparse2, CoinIndexedVector * regionSparse3) ; /** Updates one column (BTRAN) from region2 region1 starts as zero and is zero at end */ int updateColumnTranspose ( CoinIndexedVector * regionSparse, CoinIndexedVector * regionSparse2) const; #endif /** Updates one column (FTRAN) Tries to do FT update number returned is negative if no room */ inline int updateColumnFT ( CoinIndexedVector & regionSparseFT) { return coinAbcFactorization_->updateColumnFT(regionSparseFT);} inline int updateColumnFTPart1 ( CoinIndexedVector & regionSparseFT) { return coinAbcFactorization_->updateColumnFTPart1(regionSparseFT);} inline void updateColumnFTPart2 ( CoinIndexedVector & regionSparseFT) { coinAbcFactorization_->updateColumnFTPart2(regionSparseFT);} /** Updates one column (FTRAN) Tries to do FT update puts partial update in vector */ inline void updateColumnFT ( CoinIndexedVector & regionSparseFT, CoinIndexedVector & partialUpdate, int which) { coinAbcFactorization_->updateColumnFT(regionSparseFT,partialUpdate,which);} /** Updates one column (FTRAN) */ inline int updateColumn ( CoinIndexedVector & regionSparse) const { return coinAbcFactorization_->updateColumn(regionSparse);} /** Updates one column (FTRAN) from regionFT Tries to do FT update number returned is negative if no room. Also updates regionOther */ inline int updateTwoColumnsFT ( CoinIndexedVector & regionSparseFT, CoinIndexedVector & regionSparseOther) { return coinAbcFactorization_->updateTwoColumnsFT(regionSparseFT,regionSparseOther);} /** Updates one column (BTRAN) */ inline int updateColumnTranspose ( CoinIndexedVector & regionSparse) const { return coinAbcFactorization_->updateColumnTranspose(regionSparse);} /** Updates one column (FTRAN) */ inline void updateColumnCpu ( CoinIndexedVector & regionSparse,int whichCpu) const { coinAbcFactorization_->updateColumnCpu(regionSparse,whichCpu);} /** Updates one column (BTRAN) */ inline void updateColumnTransposeCpu ( CoinIndexedVector & regionSparse,int whichCpu) const { coinAbcFactorization_->updateColumnTransposeCpu(regionSparse,whichCpu);} /** Updates one full column (FTRAN) */ inline void updateFullColumn ( CoinIndexedVector & regionSparse) const { coinAbcFactorization_->updateFullColumn(regionSparse);} /** Updates one full column (BTRAN) */ inline void updateFullColumnTranspose ( CoinIndexedVector & regionSparse) const { coinAbcFactorization_->updateFullColumnTranspose(regionSparse);} /** Updates one column for dual steepest edge weights (FTRAN) */ void updateWeights ( CoinIndexedVector & regionSparse) const { coinAbcFactorization_->updateWeights(regionSparse);} //@} /**@name Lifted from CoinFactorization */ //@{ /// Total number of elements in factorization inline int numberElements ( ) const { return coinAbcFactorization_->numberElements() ; } /// Maximum number of pivots between factorizations inline int maximumPivots ( ) const { return coinAbcFactorization_->maximumPivots() ; } /// Set maximum number of pivots between factorizations inline void maximumPivots ( int value) { coinAbcFactorization_->maximumPivots(value); } /// Returns true if doing FT inline bool usingFT() const { return !coinAbcFactorization_->wantsTableauColumn();} /// Returns number of pivots since factorization inline int pivots ( ) const { return coinAbcFactorization_->pivots() ; } /// Sets number of pivots since factorization inline void setPivots ( int value ) const { coinAbcFactorization_->setPivots(value) ; } /// Whether larger areas needed inline double areaFactor ( ) const { return coinAbcFactorization_->areaFactor() ; } /// Set whether larger areas needed inline void areaFactor ( double value) { coinAbcFactorization_->areaFactor(value); } /// Zero tolerance inline double zeroTolerance ( ) const { return coinAbcFactorization_->zeroTolerance() ; } /// Set zero tolerance inline void zeroTolerance ( double value) { coinAbcFactorization_->zeroTolerance(value); } /// Set tolerances to safer of existing and given void saferTolerances ( double zeroTolerance, double pivotTolerance); /// Returns status inline int status ( ) const { return coinAbcFactorization_->status() ; } /// Sets status inline void setStatus ( int value) { coinAbcFactorization_->setStatus(value) ; } #if ABC_PARALLEL==2 /// Says parallel inline void setParallelMode(int value) {coinAbcFactorization_->setParallelMode(value);}; #endif /// Returns number of dense rows inline int numberDense() const { return coinAbcFactorization_->numberDense() ; } inline bool timeToRefactorize() const { return coinAbcFactorization_->pivots() > coinAbcFactorization_->numberRows() / 2.45 + 20; } /// Get rid of all memory inline void clearArrays() { coinAbcFactorization_->clearArrays(); } /// Number of Rows after factorization inline int numberRows ( ) const { return coinAbcFactorization_->numberRows() ; } /// Number of slacks at last factorization inline int numberSlacks() const { return numberSlacks_;} /// Pivot tolerance inline double pivotTolerance ( ) const { return coinAbcFactorization_->pivotTolerance(); } /// Set pivot tolerance inline void pivotTolerance ( double value) { coinAbcFactorization_->pivotTolerance(value); } /// Minimum pivot tolerance inline double minimumPivotTolerance ( ) const { return coinAbcFactorization_->minimumPivotTolerance(); } /// Set minimum pivot tolerance inline void minimumPivotTolerance ( double value) { coinAbcFactorization_->minimumPivotTolerance(value); } /// pivot region inline double * pivotRegion() const { return coinAbcFactorization_->pivotRegion();} /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed //inline void relaxAccuracyCheck(double /*value*/) { //abort(); //} /// Delete all stuff (leaves as after CoinFactorization()) inline void almostDestructor() { coinAbcFactorization_->clearArrays(); } /// So we can temporarily switch off dense void setDenseThreshold(int number); int getDenseThreshold() const; /// If nonzero force use of 1,dense 2,small 3,long void forceOtherFactorization(int which); /// Go over to dense code void goDenseOrSmall(int numberRows); /// Get switch to dense if number rows <= this inline int goDenseThreshold() const { return goDenseThreshold_; } /// Set switch to dense if number rows <= this inline void setGoDenseThreshold(int value) { goDenseThreshold_ = value; } /// Get switch to small if number rows <= this inline int goSmallThreshold() const { return goSmallThreshold_; } /// Set switch to small if number rows <= this inline void setGoSmallThreshold(int value) { goSmallThreshold_ = value; } /// Get switch to long/ordered if number rows >= this inline int goLongThreshold() const { return goLongThreshold_; } /// Set switch to long/ordered if number rows >= this inline void setGoLongThreshold(int value) { goLongThreshold_ = value; } /// Returns type inline int typeOfFactorization() const { return forceB_;} /// Synchronize stuff void synchronize(const ClpFactorization * otherFactorization,const AbcSimplex * model); //@} /**@name other stuff */ //@{ /** makes a row copy of L for speed and to allow very sparse problems */ void goSparse(); #ifndef NDEBUG inline void checkMarkArrays() const { coinAbcFactorization_->checkMarkArrays();} #endif /// Says whether to redo pivot order inline bool needToReorder() const {abort();return true;} /// Pointer to factorization CoinAbcAnyFactorization * factorization() const { return coinAbcFactorization_;} //@} ////////////////// data ////////////////// private: /**@name data */ //@{ /// Pointer to model AbcSimplex * model_; /// Pointer to factorization CoinAbcAnyFactorization * coinAbcFactorization_; /// If nonzero force use of 1,dense 2,small 3,long int forceB_; /// Switch to dense if number rows <= this int goDenseThreshold_; /// Switch to small if number rows <= this int goSmallThreshold_; /// Switch to long/ordered if number rows >= this int goLongThreshold_; /// Number of slacks at last factorization int numberSlacks_; //@} }; #endif Clp-1.15.10/src/AbcPrimalColumnDantzig.cpp0000644000076600007660000002312412101105055016667 0ustar coincoin/* $Id: AbcPrimalColumnDantzig.cpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include #include "CoinIndexedVector.hpp" #include "AbcSimplex.hpp" #include "AbcPrimalColumnDantzig.hpp" #include "AbcSimplexFactorization.hpp" #include "AbcMatrix.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- AbcPrimalColumnDantzig::AbcPrimalColumnDantzig () : AbcPrimalColumnPivot() { type_ = 1; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- AbcPrimalColumnDantzig::AbcPrimalColumnDantzig (const AbcPrimalColumnDantzig & source) : AbcPrimalColumnPivot(source) { } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- AbcPrimalColumnDantzig::~AbcPrimalColumnDantzig () { } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- AbcPrimalColumnDantzig & AbcPrimalColumnDantzig::operator=(const AbcPrimalColumnDantzig& rhs) { if (this != &rhs) { AbcPrimalColumnPivot::operator=(rhs); } return *this; } // Returns pivot column, -1 if none int AbcPrimalColumnDantzig::pivotColumn(CoinPartitionedVector * updates, CoinPartitionedVector * /*spareRow2*/, CoinPartitionedVector * spareColumn1) { assert(model_); int iSection, j; int number; double multiplier; int * index; double * updateBy; double * reducedCost; bool anyUpdates; if (updates->getNumElements()) { anyUpdates = true; } else { // sub flip - nothing to do anyUpdates = false; } if (anyUpdates) { model_->factorization()->updateColumnTranspose(*updates); int iVector=model_->getAvailableArray(); int bestSequence= model_->abcMatrix()->pivotColumnDantzig(*updates,*model_->usefulArray(iVector)); model_->setAvailableArray(iVector); int pivotRow = model_->pivotRow(); if (pivotRow >= 0) { // make sure infeasibility on incoming is 0.0 int sequenceIn = model_->sequenceIn(); double * reducedCost = model_->djRegion(); reducedCost[sequenceIn]=0.0; } #if 1 if (model_->logLevel()==127) { double * reducedCost = model_->djRegion(); int numberRows=model_->numberRows(); printf("Best sequence %d\n",bestSequence); for (int i=0;inumberColumns();i++) printf("column %d dj %g\n",i,reducedCost[i+numberRows]); } #endif looksOptimal_=bestSequence<0; return bestSequence; // put row of tableau in rowArray and columnArray model_->abcMatrix()->transposeTimes(*updates, *spareColumn1); for (iSection = 0; iSection < 2; iSection++) { reducedCost = model_->djRegion(iSection); if (!iSection) { number = updates->getNumElements(); index = updates->getIndices(); updateBy = updates->denseVector(); multiplier=-1.0; } else { number = spareColumn1->getNumElements(); index = spareColumn1->getIndices(); updateBy = spareColumn1->denseVector(); multiplier=1.0; } for (j = 0; j < number; j++) { int iSequence = index[j]; double value = reducedCost[iSequence]; value -= multiplier*updateBy[iSequence]; updateBy[iSequence] = 0.0; reducedCost[iSequence] = value; } } updates->setNumElements(0); spareColumn1->setNumElements(0); } // update of duals finished - now do pricing #if 0 double largest = model_->currentPrimalTolerance(); // we can't really trust infeasibilities if there is primal error if (model_->largestDualError() > 1.0e-8) largest *= model_->largestDualError() / 1.0e-8; #endif double bestDj = model_->dualTolerance(); int bestSequence = -1; double bestFreeDj = model_->dualTolerance(); int bestFreeSequence = -1; number = model_->numberTotal(); int iSequence; reducedCost = model_->djRegion(); #ifndef CLP_PRIMAL_SLACK_MULTIPLIER for (iSequence = 0; iSequence < number; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case AbcSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case AbcSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } #else int numberColumns = model_->numberColumns(); int maximumRows=model_->maximumAbcNumberRows(); for (iSequence = maximumRows; iSequence < numberColumns+maximumRows; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence]; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case AbcSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case AbcSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } // Rows number=model_->numberRows(); for (iSequence=0 ; iSequence < number; iSequence++) { // check flagged variable if (!model_->flagged(iSequence)) { double value = reducedCost[iSequence] * CLP_PRIMAL_SLACK_MULTIPLIER; AbcSimplex::Status status = model_->getInternalStatus(iSequence); switch(status) { case AbcSimplex::basic: case AbcSimplex::isFixed: break; case AbcSimplex::isFree: case AbcSimplex::superBasic: if (fabs(value) > bestFreeDj) { bestFreeDj = fabs(value); bestFreeSequence = iSequence; } break; case AbcSimplex::atUpperBound: if (value > bestDj) { bestDj = value; bestSequence = iSequence; } break; case AbcSimplex::atLowerBound: if (value < -bestDj) { bestDj = -value; bestSequence = iSequence; } } } } #endif // bias towards free if (bestFreeSequence >= 0 && bestFreeDj > 0.1 * bestDj) bestSequence = bestFreeSequence; #if 1 if (model_->logLevel()==127) { double * reducedCost = model_->djRegion(); int numberRows=model_->numberRows(); printf("Best sequence %d\n",bestSequence); for (int i=0;inumberColumns();i++) printf("column %d dj %g\n",i,reducedCost[i+numberRows]); } #endif looksOptimal_=bestSequence<0; return bestSequence; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- AbcPrimalColumnPivot * AbcPrimalColumnDantzig::clone(bool CopyData) const { if (CopyData) { return new AbcPrimalColumnDantzig(*this); } else { return new AbcPrimalColumnDantzig(); } } Clp-1.15.10/src/CoinAbcFactorization.hpp0000644000076600007660000000250712101105055016400 0ustar coincoin/* $Id: CoinAbcFactorization.hpp 1910 2013-01-27 02:00:13Z stefan $ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). /* Authors John Forrest */ #ifndef CoinAbcFactorization_H #define CoinAbcFactorization_H #include "CoinAbcCommonFactorization.hpp" #ifndef ABC_JUST_ONE_FACTORIZATION #define CoinAbcTypeFactorization CoinAbcFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #undef CoinAbcTypeFactorization #undef ABC_SMALL #undef COIN_BIG_DOUBLE #define COIN_BIG_DOUBLE 1 #define CoinAbcTypeFactorization CoinAbcLongFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #undef CoinAbcTypeFactorization #undef ABC_SMALL #undef COIN_BIG_DOUBLE #define CoinAbcTypeFactorization CoinAbcSmallFactorization #define ABC_SMALL 4 #include "CoinAbcBaseFactorization.hpp" #undef CoinAbcTypeFactorization #undef ABC_SMALL #define CoinAbcTypeFactorization CoinAbcOrderedFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #undef CoinAbcTypeFactorization #undef ABC_SMALL #else #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #endif Clp-1.15.10/depcomp0000755000076600007660000003710011405215425012430 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: Clp-1.15.10/MSVisualStudio/0000755000076600007660000000000012377556130013757 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/0000755000076600007660000000000012377556130014365 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/ClpExamplesTestBarrier/0000755000076600007660000000000012377556130020751 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/ClpExamplesTestBarrier/ClpExamplesTestBarrier.vcxproj0000644000076600007660000004416012106747306026754 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4} ClpExamplesTestBarrier Application false MultiByte Application false MultiByte Application false MultiByte Application false MultiByte <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Release/ClpExamplesTestBarrier.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesTestBarrier.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/ClpExamplesTestBarrier.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesTestBarrier.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Debug/ClpExamplesTestBarrier.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesTestBarrier.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Debug/ClpExamplesTestBarrier.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true ProgramDatabase Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesTestBarrier.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false Clp-1.15.10/MSVisualStudio/v10/libClp/0000755000076600007660000000000012377556130015572 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/libClp/libClp.vcxproj0000644000076600007660000027350112131314313020403 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} libClp StaticLibrary StaticLibrary StaticLibrary StaticLibrary <_ProjectFileVersion>10.0.30319.1 AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 true ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true true NDEBUG;%(PreprocessorDefinitions) 0x0409 true X64 ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0409 true X64 Default ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) NDEBUG;%(PreprocessorDefinitions) 0x0409 true true true true 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) true true true true Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true true true true Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks Disabled %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) EnableFastChecks MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) MaxSpeed %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) true true true 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) 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) Clp-1.15.10/MSVisualStudio/v10/clp/0000755000076600007660000000000012377556130015143 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/clp/clp.vcxproj0000644000076600007660000005323112156635016017336 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B} clp Application Application Application Application <_ProjectFileVersion>10.0.30319.1 false false false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/clp.tlb ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;COIN_MSVS;%(PreprocessorDefinitions) EditAndContinue _DEBUG;%(PreprocessorDefinitions) 0x0409 true true Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false X64 .\Debug/clp.tlb ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;COIN_MSVS;%(PreprocessorDefinitions) ProgramDatabase _DEBUG;%(PreprocessorDefinitions) 0x0409 true true Console false MachineX64 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/clp.tlb ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;COIN_MSVS;%(PreprocessorDefinitions) true NDEBUG;%(PreprocessorDefinitions) 0x0409 true Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false X64 .\Release/clp.tlb ..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) CLP_BUILD;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;COIN_MSVS;%(PreprocessorDefinitions) NDEBUG;%(PreprocessorDefinitions) 0x0409 true Console false MachineX64 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false 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) Clp-1.15.10/MSVisualStudio/v10/ClpExamplesMinimum/0000755000076600007660000000000012377556130020136 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/ClpExamplesMinimum/ClpExamplesMinimum.vcxproj0000644000076600007660000004402212106747306025323 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {C23C220A-5EF9-4C87-93E9-31472E684D6A} Application false MultiByte Application false MultiByte Application false MultiByte Application false MultiByte <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/ClpExamplesMinimum.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesMinimum.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Debug/ClpExamplesMinimum.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true ProgramDatabase Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesMinimum.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/ClpExamplesMinimum.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesMinimum.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/ClpExamplesMinimum.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesMinimum.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false Clp-1.15.10/MSVisualStudio/v10/OsiClpUnitTest/0000755000076600007660000000000012377556130017256 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/OsiClpUnitTest/OsiClpUnitTest.vcxproj0000644000076600007660000003267712106747306023600 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7} OsiClpUnitTest Win32Proj Application Unicode false Application Unicode Application Unicode false Application Unicode <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ true $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Osi\src\OsiCommonTest;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;_DEBUG;_CONSOLE;COIN_MSVS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console MachineX86 false X64 Disabled ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Osi\src\OsiCommonTest;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;COIN_MSVS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console MachineX64 false MaxSpeed true ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Osi\src\OsiCommonTest;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;NDEBUG;_CONSOLE;COIN_MSVS;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 ProgramDatabase libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console true true MachineX86 false X64 MaxSpeed true ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\Osi\src\OsiCommonTest;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;COIN_MSVS;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 ProgramDatabase libCoinUtils.lib;libOsi.lib;libOsiCommonTest.lib;libClp.lib;libOsiClp.lib;%(AdditionalDependencies) $(OutDir);%(AdditionalLibraryDirectories) true Console true true MachineX64 false {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {109d6e6f-6d91-460f-86ae-df27400e09a9} false {7d98e2cb-876e-4f75-9f71-77d3fe87e149} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false {02d45875-a8cf-41b9-990b-3699c0ecfe10} false Clp-1.15.10/MSVisualStudio/v10/ClpExamplesTestQP/0000755000076600007660000000000012377556130017703 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/ClpExamplesTestQP/ClpExamplesTestQP.vcxproj0000644000076600007660000004401112106747306024633 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613} Application false MultiByte Application false MultiByte Application false MultiByte Application false MultiByte <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false $(SolutionDir)$(Platform)\$(Configuration)\ $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset .\Debug/ClpExamplesTestQP.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true EditAndContinue Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesTestQP.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Debug/ClpExamplesTestQP.tlb Disabled ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true ProgramDatabase Default _DEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true true .\Debug/ClpExamplesTestQP.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/ClpExamplesTestQP.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesTestQP.pdb Console false MachineX86 $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false .\Release/ClpExamplesTestQP.tlb MaxSpeed OnlyExplicitInline ..\..\..\..\Clp\src;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;SAMPLEDIR="..\\..\\..\\..\\Data\\Sample\\\";%(PreprocessorDefinitions) true MultiThreadedDLL true true $(IntDir)$(TargetName).pch $(IntDir) $(IntDir) $(IntDir)vc$(PlatformToolsetVersion).pdb Level3 true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 $(OutDir)$(TargetName)$(TargetExt) true .\Release/ClpExamplesTestQP.pdb Console false $(OutDir);%(AdditionalLibraryDirectories) libCoinUtils.lib;libClp.lib;%(AdditionalDependencies) false Disabled Disabled %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) EnableFastChecks EnableFastChecks MaxSpeed MaxSpeed %(AdditionalIncludeDirectories) %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) %(PreprocessorDefinitions) {c4867f15-438d-4ff8-8388-62fbaaa9786c} false {4f8f7d1c-3a9e-444d-8ee9-77f33fa05994} false Clp-1.15.10/MSVisualStudio/v10/libOsiClp/0000755000076600007660000000000012377556130016245 5ustar coincoinClp-1.15.10/MSVisualStudio/v10/libOsiClp/libOsiClp.vcxproj0000644000076600007660000002225312131314313021525 0ustar coincoin Debug Win32 Debug x64 Release Win32 Release x64 {02D45875-A8CF-41B9-990B-3699C0ECFE10} libOsiClp StaticLibrary StaticLibrary StaticLibrary StaticLibrary <_ProjectFileVersion>10.0.30319.1 AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) _DEBUG;%(PreprocessorDefinitions) 0x0409 ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true true Default NDEBUG;%(PreprocessorDefinitions) 0x0409 X64 ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks ProgramDatabase Default _DEBUG;%(PreprocessorDefinitions) 0x0409 X64 Default ..\..\..\..\Clp\src;..\..\..\..\Clp\src\OsiClp;..\..\..\..\Osi\src;..\..\..\..\Osi\src\Osi;..\..\..\..\CoinUtils\src;..\..\..\..\BuildTools\headers;%(AdditionalIncludeDirectories) OSI_BUILD;WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) Default NDEBUG;%(PreprocessorDefinitions) 0x0409 Clp-1.15.10/MSVisualStudio/v10/Clp.sln0000644000076600007660000002060011616026445015613 0ustar coincoinMicrosoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesMinimum", "ClpExamplesMinimum\ClpExamplesMinimum.vcxproj", "{C23C220A-5EF9-4C87-93E9-31472E684D6A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesTestBarrier", "ClpExamplesTestBarrier\ClpExamplesTestBarrier.vcxproj", "{F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesTestQP", "ClpExamplesTestQP\ClpExamplesTestQP.vcxproj", "{E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clp", "clp\clp.vcxproj", "{0E9135A7-CB30-48D9-A83D-0F49EC3B601B}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libClp", "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}") = "libOsiClp", "libOsiClp\libOsiClp.vcxproj", "{02D45875-A8CF-41B9-990B-3699C0ECFE10}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OsiClpUnitTest", "OsiClpUnitTest\OsiClpUnitTest.vcxproj", "{70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}" 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}") = "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 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|Win32.ActiveCfg = Debug|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|Win32.Build.0 = Debug|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|x64.ActiveCfg = Debug|x64 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|x64.Build.0 = Debug|x64 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|Win32.ActiveCfg = Release|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|Win32.Build.0 = Release|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|x64.ActiveCfg = Release|x64 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|x64.Build.0 = Release|x64 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|Win32.ActiveCfg = Debug|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|Win32.Build.0 = Debug|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|x64.ActiveCfg = Debug|x64 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|x64.Build.0 = Debug|x64 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|Win32.ActiveCfg = Release|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|Win32.Build.0 = Release|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|x64.ActiveCfg = Release|x64 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|x64.Build.0 = Release|x64 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|Win32.ActiveCfg = Debug|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|Win32.Build.0 = Debug|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|x64.ActiveCfg = Debug|x64 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|x64.Build.0 = Debug|x64 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|Win32.ActiveCfg = Release|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|Win32.Build.0 = Release|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|x64.ActiveCfg = Release|x64 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|x64.Build.0 = Release|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|Win32.ActiveCfg = Debug|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|Win32.Build.0 = Debug|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|x64.ActiveCfg = Debug|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|x64.Build.0 = Debug|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|Win32.ActiveCfg = Release|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|Win32.Build.0 = Release|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|x64.ActiveCfg = Release|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.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 {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 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|Win32.ActiveCfg = Debug|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|Win32.Build.0 = Debug|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|x64.ActiveCfg = Debug|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|x64.Build.0 = Debug|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|Win32.ActiveCfg = Release|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|Win32.Build.0 = Release|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|x64.ActiveCfg = Release|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.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 {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 Clp-1.15.10/MSVisualStudio/v9/0000755000076600007660000000000012377556130014315 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/ClpExamplesTestBarrier/0000755000076600007660000000000012377556130020701 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/ClpExamplesTestBarrier/ClpExamplesTestBarrier.vcproj0000644000076600007660000001333011475602445026511 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/libClp/0000755000076600007660000000000012377556130015522 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/libClp/libClp.vcproj0000644000076600007660000015644411654750131020164 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/clp/0000755000076600007660000000000012377556130015073 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/clp/clp.vcproj0000644000076600007660000003423611653650063017102 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/ClpExamplesMinimum/0000755000076600007660000000000012377556130020066 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/ClpExamplesMinimum/ClpExamplesMinimum.vcproj0000644000076600007660000001320711475602445025066 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/OsiClpUnitTest/0000755000076600007660000000000012377556130017206 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/OsiClpUnitTest/OsiClpUnitTest.vcproj0000644000076600007660000002043111475602445023323 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/ClpExamplesTestQP/0000755000076600007660000000000012377556130017633 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/ClpExamplesTestQP/ClpExamplesTestQP.vcproj0000644000076600007660000001317511475602445024404 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/libOsiClp/0000755000076600007660000000000012377556130016175 5ustar coincoinClp-1.15.10/MSVisualStudio/v9/libOsiClp/libOsiClp.vcproj0000644000076600007660000001721111562355604021302 0ustar coincoin Clp-1.15.10/MSVisualStudio/v9/Clp.sln0000644000076600007660000002124011475602445015547 0ustar coincoinMicrosoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesMinimum", "ClpExamplesMinimum\ClpExamplesMinimum.vcproj", "{C23C220A-5EF9-4C87-93E9-31472E684D6A}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesTestBarrier", "ClpExamplesTestBarrier\ClpExamplesTestBarrier.vcproj", "{F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClpExamplesTestQP", "ClpExamplesTestQP\ClpExamplesTestQP.vcproj", "{E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clp", "clp\clp.vcproj", "{0E9135A7-CB30-48D9-A83D-0F49EC3B601B}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libClp", "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}") = "libOsiClp", "libOsiClp\libOsiClp.vcproj", "{02D45875-A8CF-41B9-990B-3699C0ECFE10}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OsiClpUnitTest", "OsiClpUnitTest\OsiClpUnitTest.vcproj", "{70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}" ProjectSection(ProjectDependencies) = postProject {C4867F15-438D-4FF8-8388-62FBAAA9786C} = {C4867F15-438D-4FF8-8388-62FBAAA9786C} {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} = {4F8F7D1C-3A9E-444D-8EE9-77F33FA05994} {109D6E6F-6D91-460F-86AE-DF27400E09A9} = {109D6E6F-6D91-460F-86AE-DF27400E09A9} {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}") = "libOsi", "..\..\..\Osi\MSVisualStudio\v9\libOsi\libOsi.vcproj", "{7D98E2CB-876E-4F75-9F71-77D3FE87E149}" 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 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|Win32.ActiveCfg = Debug|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Debug|x64.ActiveCfg = Debug|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|Win32.ActiveCfg = Release|Win32 {C23C220A-5EF9-4C87-93E9-31472E684D6A}.Release|x64.ActiveCfg = Release|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|Win32.ActiveCfg = Debug|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Debug|x64.ActiveCfg = Debug|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|Win32.ActiveCfg = Release|Win32 {F6DD73C8-6714-414E-9A98-D51F6D6AD9B4}.Release|x64.ActiveCfg = Release|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|Win32.ActiveCfg = Debug|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Debug|x64.ActiveCfg = Debug|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|Win32.ActiveCfg = Release|Win32 {E7EA8BD6-D2AA-40F0-9F0E-42A339DCF613}.Release|x64.ActiveCfg = Release|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|Win32.ActiveCfg = Debug|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|Win32.Build.0 = Debug|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|x64.ActiveCfg = Debug|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Debug|x64.Build.0 = Debug|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|Win32.ActiveCfg = Release|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|Win32.Build.0 = Release|Win32 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.Release|x64.ActiveCfg = Release|x64 {0E9135A7-CB30-48D9-A83D-0F49EC3B601B}.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 {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 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|Win32.ActiveCfg = Debug|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|Win32.Build.0 = Debug|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|x64.ActiveCfg = Debug|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Debug|x64.Build.0 = Debug|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|Win32.ActiveCfg = Release|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|Win32.Build.0 = Release|Win32 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.Release|x64.ActiveCfg = Release|x64 {70730B26-9A00-4C1D-8AD2-ECE43B8F96A7}.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 {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 Clp-1.15.10/Makefile.in0000644000076600007660000010272512253625222013130 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@ # Don't do src/OsiClp recursively, since src/OsiClp/libOsiClp depends on src/libClp @COIN_HAS_OSI_TRUE@am__append_1 = src/OsiClp # 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_2 = test @COIN_HAS_OSI_TRUE@am__append_3 = osi-clp.pc DIST_COMMON = README $(am__configure_deps) \ $(srcdir)/BuildTools/Makemain.inc $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/clp-uninstalled.pc.in \ $(srcdir)/clp.pc.in $(top_srcdir)/configure \ $(top_srcdir)/doxydoc/doxygen.conf.in \ $(top_srcdir)/examples/Makefile.in \ $(top_srcdir)/src/OsiClp/osi-clp-uninstalled.pc.in \ $(top_srcdir)/src/OsiClp/osi-clp.pc.in AUTHORS config.guess \ config.sub depcomp install-sh ltmain.sh missing @HAVE_EXTERNALS_TRUE@am__append_4 = Dependencies @HAVE_EXTERNALS_TRUE@am__append_5 = .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_clp.h CONFIG_CLEAN_FILES = examples/Makefile clp.pc clp-uninstalled.pc \ osi-clp.pc osi-clp-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/OsiClp 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@ ADD_FFLAGS = @ADD_FFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMDINCDIR = @AMDINCDIR@ AMDLIB = @AMDLIB@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BLAS_CFLAGS = @BLAS_CFLAGS@ BLAS_CFLAGS_INSTALLED = @BLAS_CFLAGS_INSTALLED@ BLAS_DATA = @BLAS_DATA@ BLAS_DATA_INSTALLED = @BLAS_DATA_INSTALLED@ BLAS_DEPENDENCIES = @BLAS_DEPENDENCIES@ BLAS_LIBS = @BLAS_LIBS@ BLAS_LIBS_INSTALLED = @BLAS_LIBS_INSTALLED@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CHOLMODINCDIR = @CHOLMODINCDIR@ CHOLMODLIB = @CHOLMODLIB@ CLPLIB_CFLAGS = @CLPLIB_CFLAGS@ CLPLIB_CFLAGS_INSTALLED = @CLPLIB_CFLAGS_INSTALLED@ CLPLIB_DEPENDENCIES = @CLPLIB_DEPENDENCIES@ CLPLIB_LIBS = @CLPLIB_LIBS@ CLPLIB_LIBS_INSTALLED = @CLPLIB_LIBS_INSTALLED@ CLPLIB_PCLIBS = @CLPLIB_PCLIBS@ CLPLIB_PCREQUIRES = @CLPLIB_PCREQUIRES@ CLP_SVN_REV = @CLP_SVN_REV@ COINUTILS_CFLAGS = @COINUTILS_CFLAGS@ COINUTILS_CFLAGS_INSTALLED = @COINUTILS_CFLAGS_INSTALLED@ COINUTILS_DATA = @COINUTILS_DATA@ COINUTILS_DATA_INSTALLED = @COINUTILS_DATA_INSTALLED@ COINUTILS_DEPENDENCIES = @COINUTILS_DEPENDENCIES@ COINUTILS_LIBS = @COINUTILS_LIBS@ COINUTILS_LIBS_INSTALLED = @COINUTILS_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_ABC_FALSE = @COIN_HAS_ABC_FALSE@ COIN_HAS_ABC_TRUE = @COIN_HAS_ABC_TRUE@ COIN_HAS_AMD_FALSE = @COIN_HAS_AMD_FALSE@ COIN_HAS_AMD_TRUE = @COIN_HAS_AMD_TRUE@ COIN_HAS_BLAS_FALSE = @COIN_HAS_BLAS_FALSE@ COIN_HAS_BLAS_TRUE = @COIN_HAS_BLAS_TRUE@ COIN_HAS_CHOLMOD_FALSE = @COIN_HAS_CHOLMOD_FALSE@ COIN_HAS_CHOLMOD_TRUE = @COIN_HAS_CHOLMOD_TRUE@ COIN_HAS_COINUTILS_FALSE = @COIN_HAS_COINUTILS_FALSE@ COIN_HAS_COINUTILS_TRUE = @COIN_HAS_COINUTILS_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_MUMPS_FALSE = @COIN_HAS_MUMPS_FALSE@ COIN_HAS_MUMPS_TRUE = @COIN_HAS_MUMPS_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_OSI_FALSE = @COIN_HAS_OSI_FALSE@ COIN_HAS_OSI_TRUE = @COIN_HAS_OSI_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_WSMP_FALSE = @COIN_HAS_WSMP_FALSE@ COIN_HAS_WSMP_TRUE = @COIN_HAS_WSMP_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DBG_FFLAGS = @DBG_FFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FLIBS = @FLIBS@ 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@ 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@ MPICC = @MPICC@ MPICXX = @MPICXX@ MPIF77 = @MPIF77@ MUMPS_CFLAGS = @MUMPS_CFLAGS@ MUMPS_CFLAGS_INSTALLED = @MUMPS_CFLAGS_INSTALLED@ MUMPS_DATA = @MUMPS_DATA@ MUMPS_DATA_INSTALLED = @MUMPS_DATA_INSTALLED@ MUMPS_DEPENDENCIES = @MUMPS_DEPENDENCIES@ MUMPS_LIBS = @MUMPS_LIBS@ MUMPS_LIBS_INSTALLED = @MUMPS_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@ OPT_FFLAGS = @OPT_FFLAGS@ OSICLPLIB_CFLAGS = @OSICLPLIB_CFLAGS@ OSICLPLIB_CFLAGS_INSTALLED = @OSICLPLIB_CFLAGS_INSTALLED@ OSICLPLIB_DEPENDENCIES = @OSICLPLIB_DEPENDENCIES@ OSICLPLIB_LIBS = @OSICLPLIB_LIBS@ OSICLPLIB_LIBS_INSTALLED = @OSICLPLIB_LIBS_INSTALLED@ OSICLPLIB_PCLIBS = @OSICLPLIB_PCLIBS@ OSICLPLIB_PCREQUIRES = @OSICLPLIB_PCREQUIRES@ 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@ OSI_CFLAGS = @OSI_CFLAGS@ OSI_CFLAGS_INSTALLED = @OSI_CFLAGS_INSTALLED@ OSI_DATA = @OSI_DATA@ OSI_DATA_INSTALLED = @OSI_DATA_INSTALLED@ OSI_DEPENDENCIES = @OSI_DEPENDENCIES@ OSI_LIBS = @OSI_LIBS@ OSI_LIBS_INSTALLED = @OSI_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@ STRIP = @STRIP@ VERSION = @VERSION@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ 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 # ######################################################################## SUBDIRS = src $(am__append_1) $(am__append_2) ######################################################################## # 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/basicmodelclasses.xml doc/clpexe.xml \ doc/clpuserguide.xml doc/doxygen.xml doc/faqcontent.xml \ doc/faq.xml doc/intro.xml doc/legal.xml doc/messages.xml \ doc/moresamples.xml doc/notsobasic.xml doc/revhist.xml \ doc/Howto/docbook4clp.xml examples/addBits.cpp \ examples/addColumns.cpp examples/addRows.cpp \ examples/decompose.cpp examples/defaults.cpp \ examples/driver2.cpp examples/driverC.c examples/driver.cpp \ examples/dualCuts.cpp examples/ekk.cpp \ examples/ekk_interface.cpp examples/hello.cpp \ examples/hello.mps examples/input.130 examples/INSTALL \ examples/makeDual.cpp examples/Makefile.in \ examples/minimum.cpp examples/network.cpp examples/piece.cpp \ examples/rowColumn.cpp examples/sprint2.cpp \ examples/sprint.cpp examples/testBarrier.cpp \ examples/testBasis.cpp examples/testGub2.cpp \ examples/testGub.cpp examples/testQP.cpp \ examples/useVolume.cpp $(am__append_4) ######################################################################## # Creation of the addlibs file # ######################################################################## pkgconfiglibdir = $(libdir)/pkgconfig pkgconfiglib_DATA = clp.pc $(am__append_3) addlibsdir = $(DESTDIR)$(datadir)/coin/doc/Clp ######################################################################## # Maintainer Stuff # ######################################################################## CLEANFILES = # Files that are generated and should be cleaned with make distclean DISTCLEANFILES = $(am__append_5) $(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 $@ clp.pc: $(top_builddir)/config.status $(srcdir)/clp.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ clp-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/clp-uninstalled.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ osi-clp.pc: $(top_builddir)/config.status $(top_srcdir)/src/OsiClp/osi-clp.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ osi-clp-uninstalled.pc: $(top_builddir)/config.status $(top_srcdir)/src/OsiClp/osi-clp-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)/doc/Howto $(distdir)/doxydoc $(distdir)/examples $(distdir)/src/OsiClp @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 clp > $(addlibsdir)/clp_addlibs.txt @COIN_CXX_IS_CL_TRUE@@COIN_HAS_PKGCONFIG_FALSE@ echo "-libpath:`$(CYGPATH_W) @abs_lib_dir@` libClp.lib @CLPLIB_LIBS_INSTALLED@" > $(addlibsdir)/clp_addlibs.txt @COIN_CXX_IS_CL_FALSE@@COIN_HAS_PKGCONFIG_FALSE@ echo -L@abs_lib_dir@ -lClp @CLPLIB_LIBS_INSTALLED@ > $(addlibsdir)/clp_addlibs.txt uninstall-hook: rm -f $(addlibsdir)/clp_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: Clp-1.15.10/ltmain.sh0000755000076600007660000057753011405215425012716 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: Clp-1.15.10/missing0000755000076600007660000002540611405215425012460 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: Clp-1.15.10/README0000644000076600007660000000403510662211377011742 0ustar coincoinNOTE: The information in this file might not yet include the changes introduced with the switch to the autotools. To build Clp see INSTALL file To use Clp you need the Clp and Coin libraries To make standalone executable do 'make Clp' in the Clp directory. This creates an executable clp in Clp/src. To run unitTest do 'make unitTest' in the Clp directory. This will do some minimal testing. To run clp on all netlib problems do 'make unitTest NETLIBDIR=' dirname should be the path to the directory containing all the netlib files. If you have compiled Clp without zlib support then the files must be uncompressed. Running clp gives you some hints. It can do a unit test (clp -unitTest) and solve netlib problems (-netlib or -netlibp using primal). It can also solve problems and set tolerances etc. Just do clp and then try ? or setting various stuff. clp filename reads file, does presolve and dual algorithm clp filename -primalsimplex would use primal instead On Linux clp can do file completion and line editing if it can find history, readline and termcap.. If you want to stress the code you can set various stuff e.g. dantzig pricing and then go into netlib testing. I do not guarantee that it will solve all netlib if you get too creative. For instance using presolve makes netlib solve faster - but pilot87 prefers a large infeasibility weight. So clp -presolve on -dualbound 1.0e10 -netlib works well. There are samples in ./Samples. To create an executable - testit do make DRIVER=minimum to use minimum.cpp or whichever driver you want. A list is in Makefile. Three useful samples are: minimum.cpp This is the simplest possible program to read an mps file. defaults.cpp. This does not do much more, but it does it in much more complicated way by specifically setting defaults so it does give more useful information. It also prints a solution in a format "similar" to that of MPSX. presolve.cpp. This is a good driver for larger problems. Other ones can get complicated so start simple and work your way up. Clp-1.15.10/test/0000755000076600007660000000000012377556127012051 5ustar coincoinClp-1.15.10/test/Makefile.am0000644000076600007660000000442011621723240014064 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 1781 2011-08-14 10:42:40Z stefan $ # Author: Andreas Waechter IBM 2006-04-13 AUTOMAKE_OPTIONS = foreign ######################################################################## # unitTest for OsiClp # ######################################################################## if COIN_HAS_OSITESTS noinst_PROGRAMS = osiUnitTest osiUnitTest_SOURCES = osiUnitTest.cpp OsiClpSolverInterfaceTest.cpp osiUnitTest_LDADD = ../src/libClp.la ../src/OsiClp/libOsiClp.la \ $(CLPLIB_LIBS) $(OSICLP_LIBS) $(OSITESTS_LIBS) osiUnitTest_DEPENDENCIES = ../src/libClp.la ../src/OsiClp/libOsiClp.la \ $(CLPLIB_DEPENDENCIES) $(OSICLP_DEPENDENCIES) $(OSITESTS_DEPENDENCIES) AM_CPPFLAGS = \ -I`$(CYGPATH_W) $(srcdir)/../src` \ -I`$(CYGPATH_W) $(srcdir)/../src/OsiClp` \ $(COINUTILS_CFLAGS) $(OSI_CFLAGS) $(OSITESTS_CFLAGS) testdepend = osiUnitTest$(EXEEXT) endif ######################################################################## # unitTest for Clp # ######################################################################## unittestflags = osiunittestflags = if COIN_HAS_SAMPLE unittestflags += -dirSample `$(CYGPATH_W) $(SAMPLE_DATA)` osiunittestflags += -mpsDir=`$(CYGPATH_W) $(SAMPLE_DATA)` endif unittestflags += -unitTest if COIN_HAS_NETLIB unittestflags += -dirNetlib `$(CYGPATH_W) $(NETLIB_DATA)` -netlib osiunittestflags += -netlibDir=`$(CYGPATH_W) $(NETLIB_DATA)` -testOsiSolverInterface endif # We are using the CLP solver executable to do the unit test test: ../src/clp$(EXEEXT) $(testdepend) ../src/clp$(EXEEXT) $(unittestflags) || exit 1 if test -e osiUnitTest$(EXEEXT) ; then \ ./osiUnitTest$(EXEEXT) $(osiunittestflags) || exit 1 ; \ fi .PHONY: test ######################################################################## # 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 Clp-1.15.10/test/osiUnitTest.cpp0000644000076600007660000000637411575424014015045 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$ #include "CoinPragma.hpp" #include #include "OsiUnitTests.hpp" #include "OsiClpSolverInterface.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. */ { OsiClpSolverInterface clpSi; testingMessage( "Testing OsiRowCut with OsiClpSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiRowCutUnitTest(&clpSi,mpsDir), {}, clpSi, "rowcut unittest"); } { OsiClpSolverInterface clpSi; testingMessage( "Testing OsiColCut with OsiClpSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiColCutUnitTest(&clpSi,mpsDir), {}, clpSi, "colcut unittest"); } { OsiClpSolverInterface clpSi; testingMessage( "Testing OsiRowCutDebugger with OsiClpSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiRowCutDebuggerUnitTest(&clpSi,mpsDir), {}, clpSi, "rowcut debugger unittest"); } /* Run the OsiClp class test. This will also call OsiSolverInterfaceCommonUnitTest. */ testingMessage( "Testing OsiClpSolverInterface\n" ); OSIUNITTEST_CATCH_ERROR(OsiClpSolverInterfaceUnitTest(mpsDir,netlibDir), {}, "clp", "osiclp 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 OsiClpSolverInterface); testingMessage( "Testing OsiSolverInterface on Netlib problems.\n" ); OSIUNITTEST_CATCH_ERROR(OsiSolverInterfaceMpsUnitTest(vecSi,netlibDir), {}, "clp", "netlib unittest"); delete vecSi[0]; } else testingMessage( "***Skipped Testing of OsiClpSolverInterface 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; } Clp-1.15.10/test/Makefile.in0000644000076600007660000005230112253625014014100 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_OSITESTS_TRUE@noinst_PROGRAMS = osiUnitTest$(EXEEXT) @COIN_HAS_SAMPLE_TRUE@am__append_1 = -dirSample `$(CYGPATH_W) $(SAMPLE_DATA)` @COIN_HAS_SAMPLE_TRUE@am__append_2 = -mpsDir=`$(CYGPATH_W) $(SAMPLE_DATA)` @COIN_HAS_NETLIB_TRUE@am__append_3 = -dirNetlib `$(CYGPATH_W) $(NETLIB_DATA)` -netlib @COIN_HAS_NETLIB_TRUE@am__append_4 = -netlibDir=`$(CYGPATH_W) $(NETLIB_DATA)` -testOsiSolverInterface 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_clp.h CONFIG_CLEAN_FILES = PROGRAMS = $(noinst_PROGRAMS) am__osiUnitTest_SOURCES_DIST = osiUnitTest.cpp \ OsiClpSolverInterfaceTest.cpp @COIN_HAS_OSITESTS_TRUE@am_osiUnitTest_OBJECTS = \ @COIN_HAS_OSITESTS_TRUE@ osiUnitTest.$(OBJEXT) \ @COIN_HAS_OSITESTS_TRUE@ OsiClpSolverInterfaceTest.$(OBJEXT) osiUnitTest_OBJECTS = $(am_osiUnitTest_OBJECTS) am__DEPENDENCIES_1 = DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src -I$(top_builddir)/src 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 $@ SOURCES = $(osiUnitTest_SOURCES) DIST_SOURCES = $(am__osiUnitTest_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ABSBUILDDIR = @ABSBUILDDIR@ ACLOCAL = @ACLOCAL@ ADD_CFLAGS = @ADD_CFLAGS@ ADD_CXXFLAGS = @ADD_CXXFLAGS@ ADD_FFLAGS = @ADD_FFLAGS@ ALWAYS_FALSE_FALSE = @ALWAYS_FALSE_FALSE@ ALWAYS_FALSE_TRUE = @ALWAYS_FALSE_TRUE@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMDINCDIR = @AMDINCDIR@ AMDLIB = @AMDLIB@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUX_DIR = @AUX_DIR@ AWK = @AWK@ BLAS_CFLAGS = @BLAS_CFLAGS@ BLAS_CFLAGS_INSTALLED = @BLAS_CFLAGS_INSTALLED@ BLAS_DATA = @BLAS_DATA@ BLAS_DATA_INSTALLED = @BLAS_DATA_INSTALLED@ BLAS_DEPENDENCIES = @BLAS_DEPENDENCIES@ BLAS_LIBS = @BLAS_LIBS@ BLAS_LIBS_INSTALLED = @BLAS_LIBS_INSTALLED@ BUILDTOOLSDIR = @BUILDTOOLSDIR@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CDEFS = @CDEFS@ CFLAGS = @CFLAGS@ CHOLMODINCDIR = @CHOLMODINCDIR@ CHOLMODLIB = @CHOLMODLIB@ CLPLIB_CFLAGS = @CLPLIB_CFLAGS@ CLPLIB_CFLAGS_INSTALLED = @CLPLIB_CFLAGS_INSTALLED@ CLPLIB_DEPENDENCIES = @CLPLIB_DEPENDENCIES@ CLPLIB_LIBS = @CLPLIB_LIBS@ CLPLIB_LIBS_INSTALLED = @CLPLIB_LIBS_INSTALLED@ CLPLIB_PCLIBS = @CLPLIB_PCLIBS@ CLPLIB_PCREQUIRES = @CLPLIB_PCREQUIRES@ CLP_SVN_REV = @CLP_SVN_REV@ COINUTILS_CFLAGS = @COINUTILS_CFLAGS@ COINUTILS_CFLAGS_INSTALLED = @COINUTILS_CFLAGS_INSTALLED@ COINUTILS_DATA = @COINUTILS_DATA@ COINUTILS_DATA_INSTALLED = @COINUTILS_DATA_INSTALLED@ COINUTILS_DEPENDENCIES = @COINUTILS_DEPENDENCIES@ COINUTILS_LIBS = @COINUTILS_LIBS@ COINUTILS_LIBS_INSTALLED = @COINUTILS_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_ABC_FALSE = @COIN_HAS_ABC_FALSE@ COIN_HAS_ABC_TRUE = @COIN_HAS_ABC_TRUE@ COIN_HAS_AMD_FALSE = @COIN_HAS_AMD_FALSE@ COIN_HAS_AMD_TRUE = @COIN_HAS_AMD_TRUE@ COIN_HAS_BLAS_FALSE = @COIN_HAS_BLAS_FALSE@ COIN_HAS_BLAS_TRUE = @COIN_HAS_BLAS_TRUE@ COIN_HAS_CHOLMOD_FALSE = @COIN_HAS_CHOLMOD_FALSE@ COIN_HAS_CHOLMOD_TRUE = @COIN_HAS_CHOLMOD_TRUE@ COIN_HAS_COINUTILS_FALSE = @COIN_HAS_COINUTILS_FALSE@ COIN_HAS_COINUTILS_TRUE = @COIN_HAS_COINUTILS_TRUE@ COIN_HAS_GLPK_FALSE = @COIN_HAS_GLPK_FALSE@ COIN_HAS_GLPK_TRUE = @COIN_HAS_GLPK_TRUE@ COIN_HAS_MUMPS_FALSE = @COIN_HAS_MUMPS_FALSE@ COIN_HAS_MUMPS_TRUE = @COIN_HAS_MUMPS_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_OSI_FALSE = @COIN_HAS_OSI_FALSE@ COIN_HAS_OSI_TRUE = @COIN_HAS_OSI_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_WSMP_FALSE = @COIN_HAS_WSMP_FALSE@ COIN_HAS_WSMP_TRUE = @COIN_HAS_WSMP_TRUE@ COIN_PKG_CONFIG_PATH = @COIN_PKG_CONFIG_PATH@ COIN_PKG_CONFIG_PATH_UNINSTALLED = @COIN_PKG_CONFIG_PATH_UNINSTALLED@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEFS = @CXXDEFS@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBG_CFLAGS = @DBG_CFLAGS@ DBG_CXXFLAGS = @DBG_CXXFLAGS@ DBG_FFLAGS = @DBG_FFLAGS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DEPENDENCY_LINKING_FALSE = @DEPENDENCY_LINKING_FALSE@ DEPENDENCY_LINKING_TRUE = @DEPENDENCY_LINKING_TRUE@ ECHO = @ECHO@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ F77 = @F77@ FFLAGS = @FFLAGS@ FLIBS = @FLIBS@ 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@ 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@ MPICC = @MPICC@ MPICXX = @MPICXX@ MPIF77 = @MPIF77@ MUMPS_CFLAGS = @MUMPS_CFLAGS@ MUMPS_CFLAGS_INSTALLED = @MUMPS_CFLAGS_INSTALLED@ MUMPS_DATA = @MUMPS_DATA@ MUMPS_DATA_INSTALLED = @MUMPS_DATA_INSTALLED@ MUMPS_DEPENDENCIES = @MUMPS_DEPENDENCIES@ MUMPS_LIBS = @MUMPS_LIBS@ MUMPS_LIBS_INSTALLED = @MUMPS_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@ OPT_FFLAGS = @OPT_FFLAGS@ OSICLPLIB_CFLAGS = @OSICLPLIB_CFLAGS@ OSICLPLIB_CFLAGS_INSTALLED = @OSICLPLIB_CFLAGS_INSTALLED@ OSICLPLIB_DEPENDENCIES = @OSICLPLIB_DEPENDENCIES@ OSICLPLIB_LIBS = @OSICLPLIB_LIBS@ OSICLPLIB_LIBS_INSTALLED = @OSICLPLIB_LIBS_INSTALLED@ OSICLPLIB_PCLIBS = @OSICLPLIB_PCLIBS@ OSICLPLIB_PCREQUIRES = @OSICLPLIB_PCREQUIRES@ 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@ OSI_CFLAGS = @OSI_CFLAGS@ OSI_CFLAGS_INSTALLED = @OSI_CFLAGS_INSTALLED@ OSI_DATA = @OSI_DATA@ OSI_DATA_INSTALLED = @OSI_DATA_INSTALLED@ OSI_DEPENDENCIES = @OSI_DEPENDENCIES@ OSI_LIBS = @OSI_LIBS@ OSI_LIBS_INSTALLED = @OSI_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@ STRIP = @STRIP@ VERSION = @VERSION@ VPATH_DISTCLEANFILES = @VPATH_DISTCLEANFILES@ 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 @COIN_HAS_OSITESTS_TRUE@osiUnitTest_SOURCES = osiUnitTest.cpp OsiClpSolverInterfaceTest.cpp @COIN_HAS_OSITESTS_TRUE@osiUnitTest_LDADD = ../src/libClp.la ../src/OsiClp/libOsiClp.la \ @COIN_HAS_OSITESTS_TRUE@ $(CLPLIB_LIBS) $(OSICLP_LIBS) $(OSITESTS_LIBS) @COIN_HAS_OSITESTS_TRUE@osiUnitTest_DEPENDENCIES = ../src/libClp.la ../src/OsiClp/libOsiClp.la \ @COIN_HAS_OSITESTS_TRUE@ $(CLPLIB_DEPENDENCIES) $(OSICLP_DEPENDENCIES) $(OSITESTS_DEPENDENCIES) @COIN_HAS_OSITESTS_TRUE@AM_CPPFLAGS = \ @COIN_HAS_OSITESTS_TRUE@ -I`$(CYGPATH_W) $(srcdir)/../src` \ @COIN_HAS_OSITESTS_TRUE@ -I`$(CYGPATH_W) $(srcdir)/../src/OsiClp` \ @COIN_HAS_OSITESTS_TRUE@ $(COINUTILS_CFLAGS) $(OSI_CFLAGS) $(OSITESTS_CFLAGS) @COIN_HAS_OSITESTS_TRUE@testdepend = osiUnitTest$(EXEEXT) ######################################################################## # unitTest for Clp # ######################################################################## unittestflags = $(am__append_1) -unitTest $(am__append_3) osiunittestflags = $(am__append_2) $(am__append_4) ######################################################################## # 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 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 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 clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done 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)/OsiClpSolverInterfaceTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osiUnitTest.Po@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: 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: 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-generic clean-libtool clean-noinstPROGRAMS \ 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-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-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstPROGRAMS 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-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-info-am # We are using the CLP solver executable to do the unit test test: ../src/clp$(EXEEXT) $(testdepend) ../src/clp$(EXEEXT) $(unittestflags) || exit 1 if test -e osiUnitTest$(EXEEXT) ; then \ ./osiUnitTest$(EXEEXT) $(osiunittestflags) || exit 1 ; \ fi .PHONY: test # 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: Clp-1.15.10/test/OsiClpSolverInterfaceTest.cpp0000644000076600007660000017103111722233153017605 0ustar coincoin// $Id$ // 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 "CoinPragma.hpp" //#include //#include //#include //#include #include "OsiClpSolverInterface.hpp" #include "OsiUnitTests.hpp" #include "OsiCuts.hpp" #include "OsiRowCut.hpp" #include "OsiColCut.hpp" #include "CoinMessage.hpp" #include "ClpMessage.hpp" #include "ClpFactorization.hpp" #include "CoinModel.hpp" #include "CoinIndexedVector.hpp" #include "ClpPlusMinusOneMatrix.hpp" //############################################################################# class OsiClpMessageTest : public CoinMessageHandler { public: virtual int print() ; OsiClpMessageTest(); }; OsiClpMessageTest::OsiClpMessageTest() : CoinMessageHandler() { } int OsiClpMessageTest::print() { if (currentMessage().externalNumber()==0&¤tSource()=="Clp") std::cout<<"This is not actually an advertisement by Dash Associates - just my feeble attempt to test message handling and language - JJHF"<clone(); OsiClpSolverInterface * clpClone = dynamic_cast(siClone); OSIUNITTEST_ASSERT_ERROR(clpClone != NULL, {}, "clp", "clone"); OSIUNITTEST_ASSERT_ERROR(clpClone->getModelPtr() != clpSi.getModelPtr(), {}, "clp", "clone"); OSIUNITTEST_ASSERT_ERROR(clpClone->getNumRows() == clpSi.getNumRows(), {}, "clp", "clone"); OSIUNITTEST_ASSERT_ERROR(clpClone->getNumCols() == m.getNumCols(), {}, "clp", "clone"); delete siClone; } // Test infinity { OsiClpSolverInterface si; OSIUNITTEST_ASSERT_ERROR(si.getInfinity() == OsiClpInfinity, {}, "clp", "infinity"); } // Test some catches if (!OsiClpHasNDEBUG()) { OsiClpSolverInterface solver; try { solver.setObjCoeff(0,0.0); OSIUNITTEST_ADD_OUTCOME("clp", "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, "clp", "getMatrixByRow: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "clp", "getMatrixByRow: num elements"); CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[0], 3.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[1], 1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[2], -2.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[3], -1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[4], -1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[5], 2.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[6], 1.1), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[7], 1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[8], 1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[9], 2.8), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], -1.2), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "clp", "getMatrixByRow: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "getMatrixByRow: elements"); const int * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "clp", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "clp", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "clp", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "clp", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "getMatrixByRow: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "getMatrixByRow: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "getMatrixByRow: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "getMatrixByRow: indices"); } // Test adding several cuts { OsiClpSolverInterface 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;cnumberRows(); int * rowStatus = new int[numberRows]; int numberColumns = fim.getModelPtr()->numberColumns(); int * columnStatus = new int[numberColumns]; fim.getBasisStatus(columnStatus,rowStatus); for (int i=0; igetMajorDim() == 8, return, "clp", "getMatrixByCol: major dim"); OSIUNITTEST_ASSERT_ERROR(smP->getMinorDim() == 5, return, "clp", "getMatrixByCol: minor dim"); OSIUNITTEST_ASSERT_ERROR(smP->getNumElements() == 14, return, "clp", "getMatrixByCol: number of elements"); OSIUNITTEST_ASSERT_ERROR(smP->getSizeVectorStarts() == 9, return, "clp", "getMatrixByCol: vector starts size"); CoinRelFltEq eq; const double * ev = smP->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 5.6), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2], 1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3], 2.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4], 1.1), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6],-2.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 2.8), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8],-1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10], 1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11],-1.2), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12],-1.0), {}, "clp", "getMatrixByCol: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "getMatrixByCol: elements"); const CoinBigIndex * mi = smP->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 2, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 4, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 6, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 8, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 10, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[6] == 11, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[7] == 12, {}, "clp", "getMatrixByCol: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[8] == 14, {}, "clp", "getMatrixByCol: vector starts"); const int * ei = smP->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 4, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 0, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 1, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 1, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 2, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 0, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 3, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 0, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 4, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 2, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 3, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 0, {}, "clp", "getMatrixByCol: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 4, {}, "clp", "getMatrixByCol: indices"); } //-------------- // Test rowsense, rhs, rowrange, matrixByRow { OsiClpSolverInterface lhs; { OsiClpSolverInterface siC1(m); OSIUNITTEST_ASSERT_WARNING(siC1.rowrange_ == NULL, {}, "clp", "row range"); OSIUNITTEST_ASSERT_WARNING(siC1.rowsense_ == NULL, {}, "clp", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1.rhs_ == NULL, {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1.matrixByRow_ == NULL, {}, "clp", "matrix by row"); const char * siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "clp", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "clp", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "clp", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "clp", "row sense"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "clp", "row sense"); const double * siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "clp", "right hand side"); const double * siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "clp", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "clp", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "clp", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "clp", "row range"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "clp", "row range"); const CoinPackedMatrix * siC1mbr = siC1.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(siC1mbr != NULL, {}, "clp", "matrix by row"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getMajorDim() == 5, return, "clp", "matrix by row: major dim"); OSIUNITTEST_ASSERT_ERROR(siC1mbr->getNumElements() == 14, return, "clp", "matrix by row: num elements"); const double * ev = siC1mbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "clp", "matrix by row: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "matrix by row: elements"); const CoinBigIndex * mi = siC1mbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "clp", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "clp", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "clp", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "clp", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "matrix by row: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "matrix by row: vector starts"); const int * ei = siC1mbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "matrix by row: indices"); OSIUNITTEST_ASSERT_WARNING(siC1rs == siC1.getRowSense(), {}, "clp", "row sense"); OSIUNITTEST_ASSERT_WARNING(siC1rhs == siC1.getRightHandSide(), {}, "clp", "right hand side"); OSIUNITTEST_ASSERT_WARNING(siC1rr == siC1.getRowRange(), {}, "clp", "row range"); // Change CLP 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); // Since model was changed, test that cached data is now freed. OSIUNITTEST_ASSERT_ERROR(siC1.rowrange_ == NULL, {}, "clp", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rowsense_ == NULL, {}, "clp", "free cached data after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1.rhs_ == NULL, {}, "clp", "free cached data after adding row"); // siC1.matrixByRow_ is updated, so it does not have to be NULL siC1rs = siC1.getRowSense(); OSIUNITTEST_ASSERT_ERROR(siC1rs[0] == 'G', {}, "clp", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[1] == 'L', {}, "clp", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[2] == 'E', {}, "clp", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[3] == 'R', {}, "clp", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[4] == 'R', {}, "clp", "row sense after adding row"); OSIUNITTEST_ASSERT_ERROR(siC1rs[5] == 'N', {}, "clp", "row sense after adding row"); siC1rhs = siC1.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[0],2.5), {}, "clp", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[1],2.1), {}, "clp", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[2],4.0), {}, "clp", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[3],5.0), {}, "clp", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[4],15.), {}, "clp", "right hand side after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rhs[5],0.0), {}, "clp", "right hand side after adding row"); siC1rr = siC1.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[0],0.0), {}, "clp", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[1],0.0), {}, "clp", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[2],0.0), {}, "clp", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[3],5.0-1.8), {}, "clp", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[4],15.0-3.0), {}, "clp", "row range after adding row"); OSIUNITTEST_ASSERT_ERROR(eq(siC1rr[5],0.0), {}, "clp", "row range after adding row"); lhs = siC1; } // Test that lhs has correct values even though siC1 has gone out of scope OSIUNITTEST_ASSERT_ERROR(lhs.rowrange_ == NULL, {}, "clp", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rowsense_ == NULL, {}, "clp", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.rhs_ == NULL, {}, "clp", "freed origin after assignment"); OSIUNITTEST_ASSERT_ERROR(lhs.matrixByRow_ == NULL, {}, "clp", "freed origin after assignment"); const char * lhsrs = lhs.getRowSense(); OSIUNITTEST_ASSERT_ERROR(lhsrs[0] == 'G', {}, "clp", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[1] == 'L', {}, "clp", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[2] == 'E', {}, "clp", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[3] == 'R', {}, "clp", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[4] == 'R', {}, "clp", "row sense after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsrs[5] == 'N', {}, "clp", "row sense after assignment"); const double * lhsrhs = lhs.getRightHandSide(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[0],2.5), {}, "clp", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[1],2.1), {}, "clp", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[2],4.0), {}, "clp", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[3],5.0), {}, "clp", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[4],15.), {}, "clp", "right hand side after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrhs[5],0.0), {}, "clp", "right hand side after assignment"); const double *lhsrr = lhs.getRowRange(); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[0],0.0), {}, "clp", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[1],0.0), {}, "clp", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[2],0.0), {}, "clp", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[3],5.0-1.8), {}, "clp", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[4],15.0-3.0), {}, "clp", "row range after assignment"); OSIUNITTEST_ASSERT_ERROR(eq(lhsrr[5],0.0), {}, "clp", "row range after assignment"); const CoinPackedMatrix * lhsmbr = lhs.getMatrixByRow(); OSIUNITTEST_ASSERT_ERROR(lhsmbr != NULL, {}, "clp", "matrix by row after assignment"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getMajorDim() == 6, return, "clp", "matrix by row after assignment: major dim"); OSIUNITTEST_ASSERT_ERROR(lhsmbr->getNumElements() == 14, return, "clp", "matrix by row after assignment: num elements"); const double * ev = lhsmbr->getElements(); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 0], 3.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 1], 1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 2],-2.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 3],-1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 4],-1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 5], 2.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 6], 1.1), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 7], 1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 8], 1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[ 9], 2.8), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[10],-1.2), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[11], 5.6), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[12], 1.0), {}, "clp", "matrix by row after assignment: elements"); OSIUNITTEST_ASSERT_ERROR(eq(ev[13], 1.9), {}, "clp", "matrix by row after assignment: elements"); const CoinBigIndex * mi = lhsmbr->getVectorStarts(); OSIUNITTEST_ASSERT_ERROR(mi[0] == 0, {}, "clp", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[1] == 5, {}, "clp", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[2] == 7, {}, "clp", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[3] == 9, {}, "clp", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[4] == 11, {}, "clp", "matrix by row after assignment: vector starts"); OSIUNITTEST_ASSERT_ERROR(mi[5] == 14, {}, "clp", "matrix by row after assignment: vector starts"); const int * ei = lhsmbr->getIndices(); OSIUNITTEST_ASSERT_ERROR(ei[ 0] == 0, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 1] == 1, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 2] == 3, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 3] == 4, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 4] == 7, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 5] == 1, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 6] == 2, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 7] == 2, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 8] == 5, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[ 9] == 3, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[10] == 6, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[11] == 0, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[12] == 4, {}, "clp", "matrix by row after assignment: indices"); OSIUNITTEST_ASSERT_ERROR(ei[13] == 7, {}, "clp", "matrix by row after assignment: indices"); } } // Test ClpPlusMinusOneMatrix by way of loadProblem(ClpMatrixBase, ... ) { int pos_start[4] = {0,5,9,12}; int neg_start[4] = {3,7,11,12}; int col[12] = {0,1,2,3,4,5,6,7,0,1,2,3}; double rhs[3] = {0.0,0.0,0.0}; double cost[8]; double var_lb[8]; double var_ub[8]; for (int i = 0 ; i < 8 ; i++) { cost[i] = 1.0; var_lb[i] = 0.0; var_ub[i] = 1.0; } ClpPlusMinusOneMatrix pmone_matrix(3,8,false,col,pos_start,neg_start); OsiClpSolverInterface clpSi; OSIUNITTEST_CATCH_ERROR( {clpSi.loadProblem(pmone_matrix,var_lb,var_ub,cost,rhs,rhs); clpSi.initialSolve();}, {},"clp","loadProblem(ClpMatrixBase, ...)") } // Test add/delete columns { OsiClpSolverInterface 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), {}, "clp", "objvalue after adding col"); // Try deleting first column int * d = new int[1]; d[0]=0; m.deleteCols(1,d); delete [] d; 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 int iCol = m.getNumCols()-1; m.deleteCols(1,&iCol); m.resolve(); objValue = m.getObjValue(); OSIUNITTEST_ASSERT_ERROR(eq(objValue,2520.57), {}, "clp", "objvalue after deleting added col"); } // Test branch and bound { OsiClpSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); // reduce printout m.setHintParam(OsiDoReducePrint,true,OsiHintTry); // test maximization int n = m.getNumCols(); int i; double * obj2 = new double[n]; const double * obj = m.getObjCoefficients(); for (i=0;i= 2 ) for ( i=0;i1.0e-7) printf("%d has value %g\n",i,cs[i]); } } // Test infeasible bounds { OsiClpSolverInterface solver; std::string fn = mpsDir+"exmip1"; solver.readMps(fn.c_str(),"mps"); int index[]={0}; double value[]={1.0,0.0}; solver.setColSetBounds(index,index+1,value); solver.setHintParam(OsiDoPresolveInInitial, false, OsiHintDo); solver.initialSolve(); OSIUNITTEST_ASSERT_ERROR(!solver.isProvenOptimal(), {}, "clp", "infeasible bounds"); } // Build a model { OsiClpSolverInterface 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= 1) for (iColumn=0;iColumn=0) { int iColumn = triple.column(); if (iColumn*2messageHandler()->setLogLevel(4); m.initialSolve(); m.getModelPtr()->factorization()->maximumPivots(5); m.setObjSense(1.0); // clone to test pivot as well as primalPivot OsiSolverInterface * mm =m.clone(); // enable special mode m.enableSimplexInterface(true); // need to do after clone mm->enableSimplexInterface(true); // we happen to know that variables are 0-1 and rows are L int numberIterations=0; int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); double * fakeCost = new double[numberColumns]; double * duals = new double [numberRows]; double * djs = new double [numberColumns]; const double * solution = m.getColSolution(); memcpy(fakeCost,m.getObjCoefficients(),numberColumns*sizeof(double)); while (1) { const double * dj; const double * dual; if ((numberIterations&1)==0) { // use given ones dj = m.getReducedCost(); dual = m.getRowPrice(); } else { // create dj = djs; dual = duals; m.getReducedGradient(djs,duals,fakeCost); } int i; int colIn=9999; int direction=1; double best=1.0e-6; // find most negative reduced cost // Should check basic - but should be okay on this problem for (i=0;ibest) { direction=-1; best=value; colIn=-i-1; } } for (i=0;ibest&&solution[i]>1.0-1.0e-6) { direction=-1; best=value; colIn=i; } } if (colIn==9999) break; // should be optimal int colOut; int outStatus; double theta; OSIUNITTEST_ASSERT_ERROR(m.primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL) == 0, {}, "clp", "solve model by hand"); if (OsiUnitTest::verbosity >= 1) printf("out %d, direction %d theta %g\n", colOut,outStatus,theta); if (colIn!=colOut) { OSIUNITTEST_ASSERT_ERROR(mm->pivot(colIn,colOut,outStatus) >= 0, {}, "clp", "solve model by hand"); } else { // bound flip (so pivot does not make sense) OSIUNITTEST_ASSERT_ERROR(mm->primalPivotResult(colIn,direction,colOut,outStatus,theta,NULL) == 0, {}, "clp", "solve model by hand"); } numberIterations++; } delete mm; delete [] fakeCost; delete [] duals; delete [] djs; // exit special mode m.disableSimplexInterface(); m.getModelPtr()->messageHandler()->setLogLevel(4); m.messageHandler()->setLogLevel(0); m.resolve(); OSIUNITTEST_ASSERT_ERROR(m.getIterationCount() == 0, {}, "clp", "resolve after solving model by hand"); m.setObjSense(-1.0); m.initialSolve(); } # if 0 /* This section stops working without setObjectiveAndRefresh. Assertion failure down in the guts of clp, likely due to reduced costs not properly updated. Leave the code in for a bit so it's easily recoverable if anyone actually yells about the loss. There was no response to a public announcement of intent to delete, but sometimes it takes a whack on the head to get peoples' attention. At some point, it'd be good to come back through and make this work again. -- lh, 100828 -- */ // Do parametrics on the objective by hand { std::cout << " Beginning Osi Simplex mode 2 ... " << std::endl ; OsiClpSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); ClpSimplex * simplex = m.getModelPtr(); simplex->messageHandler()->setLogLevel(4); m.initialSolve(); simplex->factorization()->maximumPivots(5); simplex->messageHandler()->setLogLevel(63); m.setObjSense(1.0); // enable special mode m.enableSimplexInterface(true); int numberIterations=0; int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); double * changeCost = new double[numberColumns]; double * duals = new double [numberRows]; double * djs = new double [numberColumns]; // As getReducedGradient mucks about with innards of Clp get arrays to save double * dualsNow = new double [numberRows]; double * djsNow = new double [numberColumns]; const double * solution = m.getColSolution(); int i; // Set up change cost for (i=0;igetRowStatus(i)==ClpSimplex::basic) { assert (fabs(dualsNow[i])<1.0e-4&&fabs(duals[i])<1.0e-4); } else { assert (dualsNow[i]<1.0e-4); if (duals[i]>1.0e-8) { if (dualsNow[i]+best*duals[i]>0.0) { best = CoinMax(-dualsNow[i]/duals[i],0.0); direction=-1; colIn=-i-1; } } } } for (i=0;igetColumnStatus(i)==ClpSimplex::basic) { assert (fabs(djsNow[i])<1.0e-4&&fabs(djs[i])<1.0e-4); } else { if (solution[i]<1.0e-6) { assert (djsNow[i]>-1.0e-4); if (djs[i]<-1.0e-8) { if (djsNow[i]+best*djs[i]<0.0) { best = CoinMax(-djsNow[i]/djs[i],0.0); direction=1; colIn=i; } } } else if (solution[i]>1.0-1.0e-6) { assert (djsNow[i]<1.0e-4); if (djs[i]>1.0e-8) { if (djsNow[i]+best*djs[i]>0.0) { best = CoinMax(-djsNow[i]/djs[i],0.0); direction=-1; colIn=i; } } } } } if (colIn==9999) break; // should be optimal // update objective - djs is spare array const double * obj = m.getObjCoefficients(); for (i=0;imessageHandler()->setLogLevel(4); m.resolve(); assert (!m.getIterationCount()); } # endif // Solve an lp when interface is on { OsiClpSolverInterface m; std::string fn = mpsDir+"p0033"; m.readMps(fn.c_str(),"mps"); // enable special mode m.setHintParam(OsiDoScale,false,OsiHintDo); m.setHintParam(OsiDoPresolveInInitial,false,OsiHintDo); m.setHintParam(OsiDoDualInInitial,false,OsiHintDo); m.setHintParam(OsiDoPresolveInResolve,false,OsiHintDo); m.setHintParam(OsiDoDualInResolve,false,OsiHintDo); m.enableSimplexInterface(true); m.initialSolve(); } // Check tableau stuff when simplex interface is on { OsiClpSolverInterface m; /* Wolsey : Page 130 max 4x1 - x2 7x1 - 2x2 <= 14 x2 <= 3 2x1 - 2x2 <= 3 x1 in Z+, x2 >= 0 */ double inf_ = m.getInfinity(); int n_cols = 2; int n_rows = 3; double obj[2] = {-4.0, 1.0}; double collb[2] = {0.0, 0.0}; double colub[2] = {inf_, inf_}; double rowlb[3] = {-inf_, -inf_, -inf_}; double rowub[3] = {14.0, 3.0, 3.0}; int rowIndices[5] = {0, 2, 0, 1, 2}; int colIndices[5] = {0, 0, 1, 1, 1}; double elements[5] = {7.0, 2.0, -2.0, 1.0, -2.0}; CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5); m.loadProblem(M, collb, colub, obj, rowlb, rowub); m.enableSimplexInterface(true); m.initialSolve(); //check that the tableau matches wolsey (B-1 A) // slacks in second part of binvA double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double)); if (OsiUnitTest::verbosity >= 2) printf("B-1 A"); int i; for( i = 0; i < n_rows; i++){ m.getBInvARow(i, binvA,binvA+n_cols); if (OsiUnitTest::verbosity >= 2) { printf("\nrow: %d -> ",i); for(int j=0; j < n_cols+n_rows; j++) printf("%g, ", binvA[j]); } } if (OsiUnitTest::verbosity >= 2) { printf("\n"); printf("And by column"); } for( i = 0; i < n_cols+n_rows; i++){ m.getBInvACol(i, binvA); if (OsiUnitTest::verbosity >= 2) { printf("\ncolumn: %d -> ",i); for(int j=0; j < n_rows; j++) printf("%g, ", binvA[j]); } } if (OsiUnitTest::verbosity >= 2) printf("\n"); // and when doing as expert m.setSpecialOptions(m.specialOptions()|512); ClpSimplex * clp = m.getModelPtr(); /* Do twice - first time with enableSimplexInterface still set then without and with scaling */ for (int iPass=0;iPass<2;iPass++) { const double * rowScale = clp->rowScale(); const double * columnScale = clp->columnScale(); # if 0 if (!iPass) assert (!rowScale); else assert (rowScale); // only true for this example # endif /* has to be exactly correct as in OsiClpsolverInterface.cpp (also redo each pass as may change */ CoinIndexedVector * rowArray = clp->rowArray(1); CoinIndexedVector * columnArray = clp->columnArray(0); int n; int * which; double * array; if (OsiUnitTest::verbosity >= 2) printf("B-1 A"); for( i = 0; i < n_rows; i++){ m.getBInvARow(i, binvA,binvA+n_cols); if (OsiUnitTest::verbosity >= 2) printf("\nrow: %d -> ",i); int j; // First columns n = columnArray->getNumElements(); which = columnArray->getIndices(); array = columnArray->denseVector(); for(j=0; j < n; j++){ int k=which[j]; if (OsiUnitTest::verbosity >= 2) { if (!columnScale) { printf("(%d %g), ", k, array[k]); } else { printf("(%d %g), ", k, array[k]/columnScale[k]); } } // zero out array[k]=0.0; } // say empty columnArray->setNumElements(0); // and check (would not be in any production code) columnArray->checkClear(); // now rows n = rowArray->getNumElements(); which = rowArray->getIndices(); array = rowArray->denseVector(); for(j=0; j < n; j++){ int k=which[j]; if (OsiUnitTest::verbosity >= 2) { if (!rowScale) { printf("(%d %g), ", k+n_cols, array[k]); } else { printf("(%d %g), ", k+n_cols, array[k]*rowScale[k]); } } // zero out array[k]=0.0; } // say empty rowArray->setNumElements(0); // and check (would not be in any production code) rowArray->checkClear(); } if (OsiUnitTest::verbosity >= 2) { printf("\n"); printf("And by column (trickier)"); } const int * pivotVariable = clp->pivotVariable(); for( i = 0; i < n_cols+n_rows; i++){ m.getBInvACol(i, binvA); if (OsiUnitTest::verbosity >= 2) printf("\ncolumn: %d -> ",i); n = rowArray->getNumElements(); which = rowArray->getIndices(); array = rowArray->denseVector(); for(int j=0; j < n; j++){ int k=which[j]; // need to know pivot variable for +1/-1 (slack) and row/column scaling int pivot = pivotVariable[k]; if (OsiUnitTest::verbosity >= 2) { if (pivotsetNumElements(0); // and check (would not be in any production code) rowArray->checkClear(); } if (OsiUnitTest::verbosity >= 2) printf("\n"); // now deal with next pass if (!iPass) { m.disableSimplexInterface(); // see if we can get scaling for testing clp->scaling(1); m.enableFactorization(); } else { // may not be needed - but cleaner m.disableFactorization(); } } m.setSpecialOptions(m.specialOptions()&~512); free(binvA); // Do using newer interface m.enableFactorization(); { CoinIndexedVector * rowArray = new CoinIndexedVector(n_rows); CoinIndexedVector * columnArray = new CoinIndexedVector(n_cols); int n; int * which; double * array; if (OsiUnitTest::verbosity >= 2) printf("B-1 A"); for( i = 0; i < n_rows; i++){ m.getBInvARow(i, columnArray,rowArray); if (OsiUnitTest::verbosity >= 2) printf("\nrow: %d -> ",i); int j; // First columns n = columnArray->getNumElements(); which = columnArray->getIndices(); array = columnArray->denseVector(); for(j=0; j < n; j++){ int k=which[j]; if (OsiUnitTest::verbosity >= 2) printf("(%d %g), ", k, array[k]); // zero out array[k]=0.0; } // say empty (if I had not zeroed array[k] I would use ->clear()) columnArray->setNumElements(0); // and check (would not be in any production code) columnArray->checkClear(); // now rows n = rowArray->getNumElements(); which = rowArray->getIndices(); array = rowArray->denseVector(); for(j=0; j < n; j++){ int k=which[j]; if (OsiUnitTest::verbosity >= 2) printf("(%d %g), ", k+n_cols, array[k]); // zero out array[k]=0.0; } // say empty rowArray->setNumElements(0); // and check (would not be in any production code) rowArray->checkClear(); } if (OsiUnitTest::verbosity >= 2) { printf("\n"); printf("And by column"); } for( i = 0; i < n_cols+n_rows; i++){ m.getBInvACol(i, rowArray); if (OsiUnitTest::verbosity >= 2) printf("\ncolumn: %d -> ",i); n = rowArray->getNumElements(); which = rowArray->getIndices(); array = rowArray->denseVector(); for(int j=0; j < n; j++){ int k=which[j]; if (OsiUnitTest::verbosity >= 2) printf("(%d %g), ", k, array[k]); // zero out array[k]=0.0; } // say empty rowArray->setNumElements(0); // and check (would not be in any production code) rowArray->checkClear(); } if (OsiUnitTest::verbosity >= 2) printf("\n"); delete rowArray; delete columnArray; } // may not be needed - but cleaner m.disableFactorization(); } // Check tableau stuff when simplex interface is off { OsiClpSolverInterface m; /* Wolsey : Page 130 max 4x1 - x2 7x1 - 2x2 <= 14 x2 <= 3 2x1 - 2x2 <= 3 x1 in Z+, x2 >= 0 */ double inf_ = m.getInfinity(); int n_cols = 2; int n_rows = 3; double obj[2] = {-4.0, 1.0}; double collb[2] = {0.0, 0.0}; double colub[2] = {inf_, inf_}; double rowlb[3] = {-inf_, -inf_, -inf_}; double rowub[3] = {14.0, 3.0, 3.0}; int rowIndices[5] = {0, 2, 0, 1, 2}; int colIndices[5] = {0, 0, 1, 1, 1}; double elements[5] = {7.0, 2.0, -2.0, 1.0, -2.0}; CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5); m.loadProblem(M, collb, colub, obj, rowlb, rowub); // Test with scaling m.setHintParam(OsiDoScale,true); // Tell code to keep factorization m.setupForRepeatedUse(3,0); m.initialSolve(); // Repeated stuff only in resolve // m.resolve(); (now in both (just for (3,0)) //check that the tableau matches wolsey (B-1 A) // slacks in second part of binvA double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double)); // and getBasics int * pivots = new int[n_rows]; m.getBasics(pivots); if (OsiUnitTest::verbosity >= 2) printf("B-1 A"); int i; for( i = 0; i < n_rows; i++){ m.getBInvARow(i, binvA,binvA+n_cols); if (OsiUnitTest::verbosity >= 2) { printf("\nrow: %d (pivot %d) -> ",i,pivots[i]); for(int j=0; j < n_cols+n_rows; j++) printf("%g, ", binvA[j]); } } if (OsiUnitTest::verbosity >= 2) { printf("\n"); printf("And by column"); } for( i = 0; i < n_cols+n_rows; i++){ m.getBInvACol(i, binvA); if (OsiUnitTest::verbosity >= 2) { printf("\ncolumn: %d -> ",i); for(int j=0; j < n_rows; j++) printf("%g, ", binvA[j]); } } if (OsiUnitTest::verbosity >= 2) printf("\n"); free(binvA); delete [] pivots; } // Do common solverInterface testing { OsiClpSolverInterface m; OsiSolverInterfaceCommonUnitTest(&m, mpsDir, netlibDir); } } Clp-1.15.10/configure0000755000076600007660000412167112377500504013001 0ustar coincoin#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for Clp 1.15.10. # # 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='Clp' PACKAGE_TARNAME='clp' PACKAGE_VERSION='1.15.10' PACKAGE_STRING='Clp 1.15.10' PACKAGE_BUGREPORT='clp@list.coin-or.org' ac_unique_file="src/ClpSimplex.cpp" 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 CLP_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 COINUTILS_LIBS COINUTILS_CFLAGS COINUTILS_DATA COINUTILS_DEPENDENCIES COINUTILS_LIBS_INSTALLED COINUTILS_CFLAGS_INSTALLED COINUTILS_DATA_INSTALLED CLPLIB_CFLAGS CLPLIB_LIBS CLPLIB_PCLIBS CLPLIB_PCREQUIRES CLPLIB_DEPENDENCIES CLPLIB_CFLAGS_INSTALLED CLPLIB_LIBS_INSTALLED COIN_HAS_COINUTILS_TRUE COIN_HAS_COINUTILS_FALSE OSI_LIBS OSI_CFLAGS OSI_DATA OSI_DEPENDENCIES OSI_LIBS_INSTALLED OSI_CFLAGS_INSTALLED OSI_DATA_INSTALLED OSICLPLIB_CFLAGS OSICLPLIB_LIBS OSICLPLIB_PCLIBS OSICLPLIB_PCREQUIRES OSICLPLIB_DEPENDENCIES OSICLPLIB_CFLAGS_INSTALLED OSICLPLIB_LIBS_INSTALLED COIN_HAS_OSI_TRUE COIN_HAS_OSI_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 COIN_HAS_ABC_TRUE COIN_HAS_ABC_FALSE AMDINCDIR AMDLIB COIN_HAS_AMD_TRUE COIN_HAS_AMD_FALSE CHOLMODINCDIR CHOLMODLIB COIN_HAS_CHOLMOD_TRUE COIN_HAS_CHOLMOD_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 MUMPS_LIBS MUMPS_CFLAGS MUMPS_DATA MUMPS_DEPENDENCIES MUMPS_LIBS_INSTALLED MUMPS_CFLAGS_INSTALLED MUMPS_DATA_INSTALLED COIN_HAS_MUMPS_TRUE COIN_HAS_MUMPS_FALSE ADD_FFLAGS DBG_FFLAGS OPT_FFLAGS MPIF77 FLIBS BLAS_LIBS BLAS_CFLAGS BLAS_DATA BLAS_DEPENDENCIES BLAS_LIBS_INSTALLED BLAS_CFLAGS_INSTALLED BLAS_DATA_INSTALLED COIN_HAS_BLAS_TRUE COIN_HAS_BLAS_FALSE COIN_HAS_WSMP_TRUE COIN_HAS_WSMP_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 ac_env_ADD_FFLAGS_set=${ADD_FFLAGS+set} ac_env_ADD_FFLAGS_value=$ADD_FFLAGS ac_cv_env_ADD_FFLAGS_set=${ADD_FFLAGS+set} ac_cv_env_ADD_FFLAGS_value=$ADD_FFLAGS ac_env_DBG_FFLAGS_set=${DBG_FFLAGS+set} ac_env_DBG_FFLAGS_value=$DBG_FFLAGS ac_cv_env_DBG_FFLAGS_set=${DBG_FFLAGS+set} ac_cv_env_DBG_FFLAGS_value=$DBG_FFLAGS ac_env_OPT_FFLAGS_set=${OPT_FFLAGS+set} ac_env_OPT_FFLAGS_value=$OPT_FFLAGS ac_cv_env_OPT_FFLAGS_set=${OPT_FFLAGS+set} ac_cv_env_OPT_FFLAGS_value=$OPT_FFLAGS ac_env_MPIF77_set=${MPIF77+set} ac_env_MPIF77_value=$MPIF77 ac_cv_env_MPIF77_set=${MPIF77+set} ac_cv_env_MPIF77_value=$MPIF77 # # 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 Clp 1.15.10 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 Clp 1.15.10:";; 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-clp compile project Clp 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-aboca enables build of Aboca solver (set to 1,2,3,4) --disable-amd-libcheck skip the link check at configuration time --disable-cholmod-libcheck skip the link check at configuration time --enable-gnu-packages compile with GNU packages (disabled by default) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-clp-verbosity specify the debug verbosity level for project Clp --with-clp-checklevel specify the sanity check level for project Clp --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-coinutils-lib linker flags for using package CoinUtils --with-coinutils-incdir directory with header files for using package CoinUtils --with-coinutils-datadir directory with data files for using package CoinUtils --with-osi-lib linker flags for using package Osi --with-osi-incdir directory with header files for using package Osi --with-osi-datadir directory with data files for using package Osi --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-amd-incdir specify the header file directory for library AMD --with-amd-lib specify the flags used to link with the library AMD --with-cholmod-incdir specify the header file directory for library CHOLMOD --with-cholmod-lib specify the flags used to link with the library CHOLMOD --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-mumps-lib linker flags for using package Mumps --with-mumps-incdir directory with header files for using package Mumps --with-mumps-datadir directory with data files for using package Mumps --with-wsmp specify WSMP library --with-blas specify BLAS library (or BUILD to enforce use of ThirdParty/Blas) --with-blas-lib linker flags for using package Blas --with-blas-incdir directory with header files for using package Blas --with-blas-datadir directory with data files for using package Blas --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 ADD_FFLAGS Additional Fortran compiler options DBG_FFLAGS Debug Fortran compiler options OPT_FFLAGS Optimize Fortran compiler options MPIF77 Fortran MPI Compiler 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 Clp configure 1.15.10 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 Clp $as_me 1.15.10, 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 CLP_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 CLP_VERSION_MAJOR $coin_majorver _ACEOF cat >>confdefs.h <<_ACEOF #define CLP_VERSION_MINOR $coin_minorver _ACEOF cat >>confdefs.h <<_ACEOF #define CLP_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=CLP # 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 CLP_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 CLP_SVN_REV $CLP_SVN_REV _ACEOF fi fi # Capture libtool library version, if given. coin_libversion=13:10:12 # 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-clp or --disable-debug-clp was given. if test "${enable_debug_clp+set}" = set; then enableval="$enable_debug_clp" case "${enableval}" in yes) coin_debug_compile=true ;; no) coin_debug_compile=false ;; *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-debug-clp" >&5 echo "$as_me: error: bad value ${enableval} for --enable-debug-clp" >&2;} { (exit 1); exit 1; }; } ;; esac else : fi; # m4_ifvaln([Clp], 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-clp-verbosity or --without-clp-verbosity was given. if test "${with_clp_verbosity+set}" = set; then withval="$with_clp_verbosity" if test "$withval" = yes; then withval=1 fi coin_clp_verbosity=$withval else coin_clp_verbosity=0 fi; cat >>confdefs.h <<_ACEOF #define COIN_CLP_VERBOSITY $coin_clp_verbosity _ACEOF # Check whether --with-clp-checklevel or --without-clp-checklevel was given. if test "${with_clp_checklevel+set}" = set; then withval="$with_clp_checklevel" if test "$withval" = yes; then withval=1 fi coin_clp_checklevel=$withval else coin_clp_checklevel=0 fi; cat >>confdefs.h <<_ACEOF #define COIN_CLP_CHECKLEVEL $coin_clp_checklevel _ACEOF # m4_ifvaln([Clp], # 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='clp' VERSION='1.15.10' 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 5870 "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 clp@list.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:7004:" \ "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:8071: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8075: \$? = $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:8339: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:8343: \$? = $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:8443: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:8447: \$? = $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:13232: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:13236: \$? = $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:13336: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:13340: \$? = $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:14906: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:14910: \$? = $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:15010: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:15014: \$? = $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:17217: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17221: \$? = $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:17485: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:17489: \$? = $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:17589: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:17593: \$? = $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 CoinUtils" >&5 echo $ECHO_N "checking for COIN-OR package CoinUtils... $ECHO_C" >&6 coin_has_coinutils=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 = "CoinUtils"; then coin_has_coinutils=skipping fi done fi if test "$coin_has_coinutils" != skipping; then # Check whether --with-m4_tolower(CoinUtils) or --without-m4_tolower(CoinUtils) was given. if test "${with_coinutils+set}" = set; then withval="$with_coinutils" if test "$withval" = no ; then coin_has_coinutils=skipping fi fi; fi COINUTILS_LIBS= COINUTILS_CFLAGS= COINUTILS_DATA= COINUTILS_DEPENDENCIES= COINUTILS_PCLIBS= COINUTILS_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_coinutils != skipping; then # Check whether --with-m4_tolower(CoinUtils)-lib or --without-m4_tolower(CoinUtils)-lib was given. if test "${with_coinutils_lib+set}" = set; then withval="$with_coinutils_lib" if test "$withval" = no ; then coin_has_coinutils=skipping else coin_has_coinutils=yes COINUTILS_LIBS="$withval" COINUTILS_PCLIBS="$withval" CLPLIB_PCLIBS="$withval $CLPLIB_PCLIBS" CLPLIB_LIBS="$withval $CLPLIB_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 COINUTILS_LIBS_INSTALLED="$withval" CLPLIB_LIBS_INSTALLED="$withval $CLPLIB_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_coinutils != skipping; then # Check whether --with-m4_tolower(CoinUtils)-incdir or --without-m4_tolower(CoinUtils)-incdir was given. if test "${with_coinutils_incdir+set}" = set; then withval="$with_coinutils_incdir" if test "$withval" = no ; then coin_has_coinutils=skipping else coin_has_coinutils=yes COINUTILS_CFLAGS="-I`${CYGPATH_W} $withval`" CLPLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CLPLIB_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 COINUTILS_CFLAGS_INSTALLED="$COINUTILS_CFLAGS" CLPLIB_CFLAGS_INSTALLED="$COINUTILS_CFLAGS $CLPLIB_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_coinutils != skipping; then # Check whether --with-m4_tolower(CoinUtils)-datadir or --without-m4_tolower(CoinUtils)-datadir was given. if test "${with_coinutils_datadir+set}" = set; then withval="$with_coinutils_datadir" if test "$withval" = no ; then coin_has_coinutils=skipping else coin_has_coinutils=yes COINUTILS_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 COINUTILS_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_coinutils = 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 "coinutils"; then COINUTILS_VERSIONS=`$PKG_CONFIG --modversion "coinutils" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "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 COINUTILS_CFLAGS="$cflags" COINUTILS_LIBS=`$PKG_CONFIG --libs "coinutils" 2>/dev/null` COINUTILS_DATA=`$PKG_CONFIG --variable=datadir "coinutils" 2>/dev/null` coin_has_coinutils=yes echo "$as_me:$LINENO: result: yes: $COINUTILS_VERSIONS" >&5 echo "${ECHO_T}yes: $COINUTILS_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 COINUTILS_LIBS=`echo " $COINUTILS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi COINUTILS_PCREQUIRES="coinutils" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in ClpLib CLPLIB_PCREQUIRES="coinutils $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$COINUTILS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$COINUTILS_LIBS $CLPLIB_LIBS" else COINUTILS_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coinutils"` coin_has_coinutils=notGiven echo "$as_me:$LINENO: result: not given: $COINUTILS_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $COINUTILS_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module CoinUtils without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module CoinUtils 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 CoinUtils (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package CoinUtils (fallback)... $ECHO_C" >&6 coin_has_coinutils=notGiven COINUTILS_LIBS= COINUTILS_LIBS_INSTALLED= COINUTILS_CFLAGS= COINUTILS_CFLAGS_INSTALLED= COINUTILS_DATA= COINUTILS_DATA_INSTALLED= COINUTILS_PCLIBS= COINUTILS_PCREQUIRES= # initial list of dependencies is "coinutils", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="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$COINUTILS_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` COINUTILS_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$COINUTILS_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 COINUTILS_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 COINUTILS_CFLAGS="$projcflags $COINUTILS_CFLAGS" # set LIBS variable COINUTILS_LIBS="$projlibs $COINUTILS_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 COINUTILS_CFLAGS_INSTALLED="$projcflags $COINUTILS_CFLAGS_INSTALLED" # set LIBS variable COINUTILS_LIBS_INSTALLED="$projlibs $COINUTILS_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_coinutils=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_COINUTILS 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 COINUTILS_LIBS=`echo " $COINUTILS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` COINUTILS_LIBS_INSTALLED=`echo " $COINUTILS_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 COINUTILS_PCREQUIRES="coinutils" CLPLIB_PCREQUIRES="coinutils $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$COINUTILS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$COINUTILS_LIBS $CLPLIB_LIBS" CLPLIB_CFLAGS_INSTALLED="$COINUTILS_CFLAGS_INSTALLED $CLPLIB_CFLAGS_INSTALLED" CLPLIB_LIBS_INSTALLED="$COINUTILS_LIBS_INSTALLED $CLPLIB_LIBS_INSTALLED" fi if test $coin_has_coinutils != notGiven && test $coin_has_coinutils != skipping; then COIN_HAS_COINUTILS_TRUE= COIN_HAS_COINUTILS_FALSE='#' else COIN_HAS_COINUTILS_TRUE='#' COIN_HAS_COINUTILS_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_coinutils" >&5 echo "${ECHO_T}$coin_has_coinutils" >&6 fi if test $coin_has_coinutils != skipping && test $coin_has_coinutils != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_COINUTILS 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) COINUTILS_DEPENDENCIES=`echo " $COINUTILS_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CLPLIB_DEPENDENCIES=`echo " $CLPLIB_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 "$COINUTILS_CFLAGS" ; then { echo "$as_me:$LINENO: CoinUtils CFLAGS are $COINUTILS_CFLAGS" >&5 echo "$as_me: CoinUtils CFLAGS are $COINUTILS_CFLAGS" >&6;} fi if test -n "$COINUTILS_LIBS" ; then { echo "$as_me:$LINENO: CoinUtils LIBS are $COINUTILS_LIBS" >&5 echo "$as_me: CoinUtils LIBS are $COINUTILS_LIBS" >&6;} fi if test -n "$COINUTILS_DEPENDENCIES" ; then { echo "$as_me:$LINENO: CoinUtils DEPENDENCIES are $COINUTILS_DEPENDENCIES" >&5 echo "$as_me: CoinUtils DEPENDENCIES are $COINUTILS_DEPENDENCIES" >&6;} fi if test -n "$COINUTILS_DATA" ; then { echo "$as_me:$LINENO: CoinUtils DATA is $COINUTILS_DATA" >&5 echo "$as_me: CoinUtils DATA is $COINUTILS_DATA" >&6;} fi if test -n "$COINUTILS_PCLIBS" ; then { echo "$as_me:$LINENO: CoinUtils PCLIBS are $COINUTILS_PCLIBS" >&5 echo "$as_me: CoinUtils PCLIBS are $COINUTILS_PCLIBS" >&6;} fi if test -n "$COINUTILS_PCREQUIRES" ; then { echo "$as_me:$LINENO: CoinUtils PCREQUIRES are $COINUTILS_PCREQUIRES" >&5 echo "$as_me: CoinUtils PCREQUIRES are $COINUTILS_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&5 echo "$as_me: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: ClpLib LIBS are $CLPLIB_LIBS" >&5 echo "$as_me: ClpLib LIBS are $CLPLIB_LIBS" >&6;} { echo "$as_me:$LINENO: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&5 echo "$as_me: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_coinutils != notGiven && test $coin_has_coinutils != skipping; then COIN_HAS_COINUTILS_TRUE= COIN_HAS_COINUTILS_FALSE='#' else COIN_HAS_COINUTILS_TRUE='#' COIN_HAS_COINUTILS_FALSE= fi if test $coin_has_coinutils != yes ; then { { echo "$as_me:$LINENO: error: Required package CoinUtils not available." >&5 echo "$as_me: error: Required package CoinUtils not available." >&2;} { (exit 1); exit 1; }; } fi echo "$as_me:$LINENO: checking for COIN-OR package Osi" >&5 echo $ECHO_N "checking for COIN-OR package Osi... $ECHO_C" >&6 coin_has_osi=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 = "Osi"; then coin_has_osi=skipping fi done fi if test "$coin_has_osi" != skipping; then # Check whether --with-m4_tolower(Osi) or --without-m4_tolower(Osi) was given. if test "${with_osi+set}" = set; then withval="$with_osi" if test "$withval" = no ; then coin_has_osi=skipping fi fi; fi OSI_LIBS= OSI_CFLAGS= OSI_DATA= OSI_DEPENDENCIES= OSI_PCLIBS= OSI_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_osi != skipping; then # Check whether --with-m4_tolower(Osi)-lib or --without-m4_tolower(Osi)-lib was given. if test "${with_osi_lib+set}" = set; then withval="$with_osi_lib" if test "$withval" = no ; then coin_has_osi=skipping else coin_has_osi=yes OSI_LIBS="$withval" OSI_PCLIBS="$withval" OSICLPLIB_PCLIBS="$withval $OSICLPLIB_PCLIBS" OSICLPLIB_LIBS="$withval $OSICLPLIB_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 OSI_LIBS_INSTALLED="$withval" OSICLPLIB_LIBS_INSTALLED="$withval $OSICLPLIB_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_osi != skipping; then # Check whether --with-m4_tolower(Osi)-incdir or --without-m4_tolower(Osi)-incdir was given. if test "${with_osi_incdir+set}" = set; then withval="$with_osi_incdir" if test "$withval" = no ; then coin_has_osi=skipping else coin_has_osi=yes OSI_CFLAGS="-I`${CYGPATH_W} $withval`" OSICLPLIB_CFLAGS="-I`${CYGPATH_W} $withval` $OSICLPLIB_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 OSI_CFLAGS_INSTALLED="$OSI_CFLAGS" OSICLPLIB_CFLAGS_INSTALLED="$OSI_CFLAGS $OSICLPLIB_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_osi != skipping; then # Check whether --with-m4_tolower(Osi)-datadir or --without-m4_tolower(Osi)-datadir was given. if test "${with_osi_datadir+set}" = set; then withval="$with_osi_datadir" if test "$withval" = no ; then coin_has_osi=skipping else coin_has_osi=yes OSI_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 OSI_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_osi = 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"; then OSI_VERSIONS=`$PKG_CONFIG --modversion "osi" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "osi" 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 OSI_CFLAGS="$cflags" OSI_LIBS=`$PKG_CONFIG --libs "osi" 2>/dev/null` OSI_DATA=`$PKG_CONFIG --variable=datadir "osi" 2>/dev/null` coin_has_osi=yes echo "$as_me:$LINENO: result: yes: $OSI_VERSIONS" >&5 echo "${ECHO_T}yes: $OSI_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 OSI_LIBS=`echo " $OSI_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi OSI_PCREQUIRES="osi" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in OsiClpLib OSICLPLIB_PCREQUIRES="osi $OSICLPLIB_PCREQUIRES" OSICLPLIB_CFLAGS="$OSI_CFLAGS $OSICLPLIB_CFLAGS" OSICLPLIB_LIBS="$OSI_LIBS $OSICLPLIB_LIBS" else OSI_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "osi"` coin_has_osi=notGiven echo "$as_me:$LINENO: result: not given: $OSI_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $OSI_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Osi without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Osi 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 Osi (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Osi (fallback)... $ECHO_C" >&6 coin_has_osi=notGiven OSI_LIBS= OSI_LIBS_INSTALLED= OSI_CFLAGS= OSI_CFLAGS_INSTALLED= OSI_DATA= OSI_DATA_INSTALLED= OSI_PCLIBS= OSI_PCREQUIRES= # initial list of dependencies is "osi", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="osi" # 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$OSI_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` OSI_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$OSI_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 OSI_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 OSI_CFLAGS="$projcflags $OSI_CFLAGS" # set LIBS variable OSI_LIBS="$projlibs $OSI_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 OSI_CFLAGS_INSTALLED="$projcflags $OSI_CFLAGS_INSTALLED" # set LIBS variable OSI_LIBS_INSTALLED="$projlibs $OSI_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_osi=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_OSI 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 OSI_LIBS=`echo " $OSI_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` OSI_LIBS_INSTALLED=`echo " $OSI_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 OSI_PCREQUIRES="osi" OSICLPLIB_PCREQUIRES="osi $OSICLPLIB_PCREQUIRES" OSICLPLIB_CFLAGS="$OSI_CFLAGS $OSICLPLIB_CFLAGS" OSICLPLIB_LIBS="$OSI_LIBS $OSICLPLIB_LIBS" OSICLPLIB_CFLAGS_INSTALLED="$OSI_CFLAGS_INSTALLED $OSICLPLIB_CFLAGS_INSTALLED" OSICLPLIB_LIBS_INSTALLED="$OSI_LIBS_INSTALLED $OSICLPLIB_LIBS_INSTALLED" fi if test $coin_has_osi != notGiven && test $coin_has_osi != skipping; then COIN_HAS_OSI_TRUE= COIN_HAS_OSI_FALSE='#' else COIN_HAS_OSI_TRUE='#' COIN_HAS_OSI_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_osi" >&5 echo "${ECHO_T}$coin_has_osi" >&6 fi if test $coin_has_osi != skipping && test $coin_has_osi != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_OSI 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) OSI_DEPENDENCIES=`echo " $OSI_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` OSICLPLIB_DEPENDENCIES=`echo " $OSICLPLIB_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 "$OSI_CFLAGS" ; then { echo "$as_me:$LINENO: Osi CFLAGS are $OSI_CFLAGS" >&5 echo "$as_me: Osi CFLAGS are $OSI_CFLAGS" >&6;} fi if test -n "$OSI_LIBS" ; then { echo "$as_me:$LINENO: Osi LIBS are $OSI_LIBS" >&5 echo "$as_me: Osi LIBS are $OSI_LIBS" >&6;} fi if test -n "$OSI_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Osi DEPENDENCIES are $OSI_DEPENDENCIES" >&5 echo "$as_me: Osi DEPENDENCIES are $OSI_DEPENDENCIES" >&6;} fi if test -n "$OSI_DATA" ; then { echo "$as_me:$LINENO: Osi DATA is $OSI_DATA" >&5 echo "$as_me: Osi DATA is $OSI_DATA" >&6;} fi if test -n "$OSI_PCLIBS" ; then { echo "$as_me:$LINENO: Osi PCLIBS are $OSI_PCLIBS" >&5 echo "$as_me: Osi PCLIBS are $OSI_PCLIBS" >&6;} fi if test -n "$OSI_PCREQUIRES" ; then { echo "$as_me:$LINENO: Osi PCREQUIRES are $OSI_PCREQUIRES" >&5 echo "$as_me: Osi PCREQUIRES are $OSI_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: OsiClpLib CFLAGS are $OSICLPLIB_CFLAGS" >&5 echo "$as_me: OsiClpLib CFLAGS are $OSICLPLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: OsiClpLib LIBS are $OSICLPLIB_LIBS" >&5 echo "$as_me: OsiClpLib LIBS are $OSICLPLIB_LIBS" >&6;} { echo "$as_me:$LINENO: OsiClpLib DEPENDENCIES are $OSICLPLIB_DEPENDENCIES" >&5 echo "$as_me: OsiClpLib DEPENDENCIES are $OSICLPLIB_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_osi != notGiven && test $coin_has_osi != skipping; then COIN_HAS_OSI_TRUE= COIN_HAS_OSI_FALSE='#' else COIN_HAS_OSI_TRUE='#' COIN_HAS_OSI_FALSE= fi 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 ############################################################################# # Aboca # ############################################################################# # 1 - build Abc serial but no inherit code # 2 - build Abc serial and inherit code # 3 - build Abc cilk parallel but no inherit code # 4 - build Abc cilk parallel and inherit code # Check whether --enable-aboca or --disable-aboca was given. if test "${enable_aboca+set}" = set; then enableval="$enable_aboca" use_aboca=$enableval else use_aboca=no fi; if test "$use_aboca" = yes ; then use_aboca=1 fi case "$use_aboca" in 1 | 2 | 3 | 4) cat >>confdefs.h <<_ACEOF #define CLP_HAS_ABC $use_aboca _ACEOF ;; no) ;; *) { { echo "$as_me:$LINENO: error: invalid argument for --enable-aboca: $use_aboca" >&5 echo "$as_me: error: invalid argument for --enable-aboca: $use_aboca" >&2;} { (exit 1); exit 1; }; } ;; esac if test ! "$use_aboca" = no; then COIN_HAS_ABC_TRUE= COIN_HAS_ABC_FALSE='#' else COIN_HAS_ABC_TRUE='#' COIN_HAS_ABC_FALSE= fi ############################################################################# # Third party linear solvers # ############################################################################# # AMD from UFL echo "$as_me:$LINENO: checking if user provides library for AMD" >&5 echo $ECHO_N "checking if user provides library for AMD... $ECHO_C" >&6 # Check for header file directory # Check whether --with-amd-incdir or --without-amd-incdir was given. if test "${with_amd_incdir+set}" = set; then withval="$with_amd_incdir" AMDINCDIR=`cd $withval; pwd` fi; # Check for library directory # Check whether --with-amd-lib or --without-amd-lib was given. if test "${with_amd_lib+set}" = set; then withval="$with_amd_lib" AMDLIB=$withval fi; # Switch to disable library check if requested # Check whether --enable-amd-libcheck or --disable-amd-libcheck was given. if test "${enable_amd_libcheck+set}" = set; then enableval="$enable_amd_libcheck" amd_libcheck=$enableval else amd_libcheck=yes fi; # At this point, if we're going to use the library, both LBRYINCDIR and # LBRYLIB must be defined and not empty. if test x"$AMDINCDIR" != x || test x"$AMDLIB" != x; then if test x"$AMDINCDIR" = x || test x"$AMDLIB" = x; then { { echo "$as_me:$LINENO: error: You need to specify both an include directory and link flags to use library AMD. Use --with-amd-incdir of environment variable $AMDINCDIR to specify the include directory. Use --with-amd-lib or environment variable $AMDLIB to specify link flags." >&5 echo "$as_me: error: You need to specify both an include directory and link flags to use library AMD. Use --with-amd-incdir of environment variable $AMDINCDIR to specify the include directory. Use --with-amd-lib or environment variable $AMDLIB to specify link flags." >&2;} { (exit 1); exit 1; }; } fi coin_has_amd=true echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else coin_has_amd=false echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # If we have instructions for use, consider header and link checks. if test $coin_has_amd = true; then # If argument 3 (file) is given, check for the file. Typically this will be a # header file, but that's not assumed. if test -r $AMDINCDIR/amd.h; then : else { { echo "$as_me:$LINENO: error: Cannot find file amd.h in $AMDINCDIR" >&5 echo "$as_me: error: Cannot find file amd.h in $AMDINCDIR" >&2;} { (exit 1); exit 1; }; } : fi # Now see if we can link the function. There are arguments for and against # assuming argument 3 is a header file declaring the function. A correct # function declaration is the main argument in favour. Having to cope with # possible dependencies or other oddities are the main arguments against. # Force the use of C as the best single choice amongst C++, C, and Fortran. # Obviously, this has limits. if test x"$amd_libcheck" != xno; then coin_save_LIBS="$LIBS" LIBS="$AMDLIB " coin_AMD_link=no 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 fnm in amd_defaults ; do echo "$as_me:$LINENO: checking whether symbol $fnm is available with AMD" >&5 echo $ECHO_N "checking whether symbol $fnm is available with AMD... $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 () { $fnm() ; 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 echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 coin_AMD_link=yes break 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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done 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 LIBS="$coin_save_LIBS" if test x"$coin_AMD_link" != xyes ; then { { echo "$as_me:$LINENO: error: Cannot find symbol(s) amd_defaults with AMD" >&5 echo "$as_me: error: Cannot find symbol(s) amd_defaults with AMD" >&2;} { (exit 1); exit 1; }; } fi fi # If we make it this far, we've verified the file and linked the function. Add # the necessary link flags to ClpLib_{PC}LIBS and define the preprocessor symbol # COIN_HAS_LBRY. CLPLIB_LIBS="$AMDLIB $CLPLIB_LIBS" CLPLIB_PCLIBS="$AMDLIB $CLPLIB_PCLIBS" CLPLIB_LIBS_INSTALLED="$AMDLIB $CLPLIB_LIBS_INSTALLED" cat >>confdefs.h <<\_ACEOF #define COIN_HAS_AMD 1 _ACEOF fi # Arrange for configure to substitute LBRYINCDIR and LBRYLIB and create the # automake conditional. These actions must occur unconditionally. if test $coin_has_amd = true; then COIN_HAS_AMD_TRUE= COIN_HAS_AMD_FALSE='#' else COIN_HAS_AMD_TRUE='#' COIN_HAS_AMD_FALSE= fi # CHOLMOD from UFL # CHOLMOD requires AMD, which can be given by AMD_LIBS # CHOLMOD requires Blas and Lapack? coin_save_LIBS="$LIBS" LIBS="$LIBS $AMD_LIBS" echo "$as_me:$LINENO: checking if user provides library for CHOLMOD" >&5 echo $ECHO_N "checking if user provides library for CHOLMOD... $ECHO_C" >&6 # Check for header file directory # Check whether --with-cholmod-incdir or --without-cholmod-incdir was given. if test "${with_cholmod_incdir+set}" = set; then withval="$with_cholmod_incdir" CHOLMODINCDIR=`cd $withval; pwd` fi; # Check for library directory # Check whether --with-cholmod-lib or --without-cholmod-lib was given. if test "${with_cholmod_lib+set}" = set; then withval="$with_cholmod_lib" CHOLMODLIB=$withval fi; # Switch to disable library check if requested # Check whether --enable-cholmod-libcheck or --disable-cholmod-libcheck was given. if test "${enable_cholmod_libcheck+set}" = set; then enableval="$enable_cholmod_libcheck" cholmod_libcheck=$enableval else cholmod_libcheck=yes fi; # At this point, if we're going to use the library, both LBRYINCDIR and # LBRYLIB must be defined and not empty. if test x"$CHOLMODINCDIR" != x || test x"$CHOLMODLIB" != x; then if test x"$CHOLMODINCDIR" = x || test x"$CHOLMODLIB" = x; then { { echo "$as_me:$LINENO: error: You need to specify both an include directory and link flags to use library CHOLMOD. Use --with-cholmod-incdir of environment variable $CHOLMODINCDIR to specify the include directory. Use --with-cholmod-lib or environment variable $CHOLMODLIB to specify link flags." >&5 echo "$as_me: error: You need to specify both an include directory and link flags to use library CHOLMOD. Use --with-cholmod-incdir of environment variable $CHOLMODINCDIR to specify the include directory. Use --with-cholmod-lib or environment variable $CHOLMODLIB to specify link flags." >&2;} { (exit 1); exit 1; }; } fi coin_has_cholmod=true echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 else coin_has_cholmod=false echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi # If we have instructions for use, consider header and link checks. if test $coin_has_cholmod = true; then # If argument 3 (file) is given, check for the file. Typically this will be a # header file, but that's not assumed. if test -r $CHOLMODINCDIR/cholmod.h; then : else { { echo "$as_me:$LINENO: error: Cannot find file cholmod.h in $CHOLMODINCDIR" >&5 echo "$as_me: error: Cannot find file cholmod.h in $CHOLMODINCDIR" >&2;} { (exit 1); exit 1; }; } : fi # Now see if we can link the function. There are arguments for and against # assuming argument 3 is a header file declaring the function. A correct # function declaration is the main argument in favour. Having to cope with # possible dependencies or other oddities are the main arguments against. # Force the use of C as the best single choice amongst C++, C, and Fortran. # Obviously, this has limits. if test x"$cholmod_libcheck" != xno; then coin_save_LIBS="$LIBS" LIBS="$CHOLMODLIB " coin_CHOLMOD_link=no 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 fnm in cholmod_start ; do echo "$as_me:$LINENO: checking whether symbol $fnm is available with CHOLMOD" >&5 echo $ECHO_N "checking whether symbol $fnm is available with CHOLMOD... $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 () { $fnm() ; 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 echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 coin_CHOLMOD_link=yes break 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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done 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 LIBS="$coin_save_LIBS" if test x"$coin_CHOLMOD_link" != xyes ; then { { echo "$as_me:$LINENO: error: Cannot find symbol(s) cholmod_start with CHOLMOD" >&5 echo "$as_me: error: Cannot find symbol(s) cholmod_start with CHOLMOD" >&2;} { (exit 1); exit 1; }; } fi fi # If we make it this far, we've verified the file and linked the function. Add # the necessary link flags to ClpLib_{PC}LIBS and define the preprocessor symbol # COIN_HAS_LBRY. CLPLIB_LIBS="$CHOLMODLIB $CLPLIB_LIBS" CLPLIB_PCLIBS="$CHOLMODLIB $CLPLIB_PCLIBS" CLPLIB_LIBS_INSTALLED="$CHOLMODLIB $CLPLIB_LIBS_INSTALLED" cat >>confdefs.h <<\_ACEOF #define COIN_HAS_CHOLMOD 1 _ACEOF fi # Arrange for configure to substitute LBRYINCDIR and LBRYLIB and create the # automake conditional. These actions must occur unconditionally. if test $coin_has_cholmod = true; then COIN_HAS_CHOLMOD_TRUE= COIN_HAS_CHOLMOD_FALSE='#' else COIN_HAS_CHOLMOD_TRUE='#' COIN_HAS_CHOLMOD_FALSE= fi LIBS="$coin_save_LIBS" # Glpk also brings AMD if test $coin_has_cholmod = false -a $coin_has_amd = false ; then 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" CLPLIB_PCLIBS="$withval $CLPLIB_PCLIBS" CLPLIB_LIBS="$withval $CLPLIB_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" CLPLIB_LIBS_INSTALLED="$withval $CLPLIB_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`" CLPLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CLPLIB_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" CLPLIB_CFLAGS_INSTALLED="$GLPK_CFLAGS $CLPLIB_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 "coinglpk"; then GLPK_VERSIONS=`$PKG_CONFIG --modversion "coinglpk" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coinglpk" 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 "coinglpk" 2>/dev/null` GLPK_DATA=`$PKG_CONFIG --variable=datadir "coinglpk" 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="coinglpk" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in ClpLib CLPLIB_PCREQUIRES="coinglpk $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$GLPK_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$GLPK_LIBS $CLPLIB_LIBS" else GLPK_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coinglpk"` 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 "coinglpk", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coinglpk" # 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="coinglpk" CLPLIB_PCREQUIRES="coinglpk $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$GLPK_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$GLPK_LIBS $CLPLIB_LIBS" CLPLIB_CFLAGS_INSTALLED="$GLPK_CFLAGS_INSTALLED $CLPLIB_CFLAGS_INSTALLED" CLPLIB_LIBS_INSTALLED="$GLPK_LIBS_INSTALLED $CLPLIB_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'` CLPLIB_DEPENDENCIES=`echo " $CLPLIB_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: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&5 echo "$as_me: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: ClpLib LIBS are $CLPLIB_LIBS" >&5 echo "$as_me: ClpLib LIBS are $CLPLIB_LIBS" >&6;} { echo "$as_me:$LINENO: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&5 echo "$as_me: ClpLib DEPENDENCIES are $CLPLIB_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 if test $coin_has_glpk = yes ; then { echo "$as_me:$LINENO: using AMD from GLPK package" >&5 echo "$as_me: using AMD from GLPK package" >&6;} cat >>confdefs.h <<\_ACEOF #define COIN_HAS_AMD 1 _ACEOF fi else # for configure if test 0 = 1; then COIN_HAS_GLPK_TRUE= COIN_HAS_GLPK_FALSE='#' else COIN_HAS_GLPK_TRUE='#' COIN_HAS_GLPK_FALSE= fi fi # MUMPS echo "$as_me:$LINENO: checking for COIN-OR package Mumps" >&5 echo $ECHO_N "checking for COIN-OR package Mumps... $ECHO_C" >&6 coin_has_mumps=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 = "Mumps"; then coin_has_mumps=skipping fi done fi if test "$coin_has_mumps" != skipping; then # Check whether --with-m4_tolower(Mumps) or --without-m4_tolower(Mumps) was given. if test "${with_mumps+set}" = set; then withval="$with_mumps" if test "$withval" = no ; then coin_has_mumps=skipping fi fi; fi MUMPS_LIBS= MUMPS_CFLAGS= MUMPS_DATA= MUMPS_DEPENDENCIES= MUMPS_PCLIBS= MUMPS_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_mumps != skipping; then # Check whether --with-m4_tolower(Mumps)-lib or --without-m4_tolower(Mumps)-lib was given. if test "${with_mumps_lib+set}" = set; then withval="$with_mumps_lib" if test "$withval" = no ; then coin_has_mumps=skipping else coin_has_mumps=yes MUMPS_LIBS="$withval" MUMPS_PCLIBS="$withval" CLPLIB_PCLIBS="$withval $CLPLIB_PCLIBS" CLPLIB_LIBS="$withval $CLPLIB_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 MUMPS_LIBS_INSTALLED="$withval" CLPLIB_LIBS_INSTALLED="$withval $CLPLIB_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_mumps != skipping; then # Check whether --with-m4_tolower(Mumps)-incdir or --without-m4_tolower(Mumps)-incdir was given. if test "${with_mumps_incdir+set}" = set; then withval="$with_mumps_incdir" if test "$withval" = no ; then coin_has_mumps=skipping else coin_has_mumps=yes MUMPS_CFLAGS="-I`${CYGPATH_W} $withval`" CLPLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CLPLIB_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 MUMPS_CFLAGS_INSTALLED="$MUMPS_CFLAGS" CLPLIB_CFLAGS_INSTALLED="$MUMPS_CFLAGS $CLPLIB_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_mumps != skipping; then # Check whether --with-m4_tolower(Mumps)-datadir or --without-m4_tolower(Mumps)-datadir was given. if test "${with_mumps_datadir+set}" = set; then withval="$with_mumps_datadir" if test "$withval" = no ; then coin_has_mumps=skipping else coin_has_mumps=yes MUMPS_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 MUMPS_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_mumps = 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 "coinmumps"; then MUMPS_VERSIONS=`$PKG_CONFIG --modversion "coinmumps" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coinmumps" 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 MUMPS_CFLAGS="$cflags" MUMPS_LIBS=`$PKG_CONFIG --libs "coinmumps" 2>/dev/null` MUMPS_DATA=`$PKG_CONFIG --variable=datadir "coinmumps" 2>/dev/null` coin_has_mumps=yes echo "$as_me:$LINENO: result: yes: $MUMPS_VERSIONS" >&5 echo "${ECHO_T}yes: $MUMPS_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 MUMPS_LIBS=`echo " $MUMPS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi MUMPS_PCREQUIRES="coinmumps" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in ClpLib CLPLIB_PCREQUIRES="coinmumps $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$MUMPS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$MUMPS_LIBS $CLPLIB_LIBS" else MUMPS_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coinmumps"` coin_has_mumps=notGiven echo "$as_me:$LINENO: result: not given: $MUMPS_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $MUMPS_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Mumps without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Mumps 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 Mumps (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Mumps (fallback)... $ECHO_C" >&6 coin_has_mumps=notGiven MUMPS_LIBS= MUMPS_LIBS_INSTALLED= MUMPS_CFLAGS= MUMPS_CFLAGS_INSTALLED= MUMPS_DATA= MUMPS_DATA_INSTALLED= MUMPS_PCLIBS= MUMPS_PCREQUIRES= # initial list of dependencies is "coinmumps", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coinmumps" # 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$MUMPS_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` MUMPS_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$MUMPS_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 MUMPS_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 MUMPS_CFLAGS="$projcflags $MUMPS_CFLAGS" # set LIBS variable MUMPS_LIBS="$projlibs $MUMPS_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 MUMPS_CFLAGS_INSTALLED="$projcflags $MUMPS_CFLAGS_INSTALLED" # set LIBS variable MUMPS_LIBS_INSTALLED="$projlibs $MUMPS_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_mumps=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MUMPS 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 MUMPS_LIBS=`echo " $MUMPS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` MUMPS_LIBS_INSTALLED=`echo " $MUMPS_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 MUMPS_PCREQUIRES="coinmumps" CLPLIB_PCREQUIRES="coinmumps $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$MUMPS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$MUMPS_LIBS $CLPLIB_LIBS" CLPLIB_CFLAGS_INSTALLED="$MUMPS_CFLAGS_INSTALLED $CLPLIB_CFLAGS_INSTALLED" CLPLIB_LIBS_INSTALLED="$MUMPS_LIBS_INSTALLED $CLPLIB_LIBS_INSTALLED" fi if test $coin_has_mumps != notGiven && test $coin_has_mumps != skipping; then COIN_HAS_MUMPS_TRUE= COIN_HAS_MUMPS_FALSE='#' else COIN_HAS_MUMPS_TRUE='#' COIN_HAS_MUMPS_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_mumps" >&5 echo "${ECHO_T}$coin_has_mumps" >&6 fi if test $coin_has_mumps != skipping && test $coin_has_mumps != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_MUMPS 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) MUMPS_DEPENDENCIES=`echo " $MUMPS_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CLPLIB_DEPENDENCIES=`echo " $CLPLIB_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 "$MUMPS_CFLAGS" ; then { echo "$as_me:$LINENO: Mumps CFLAGS are $MUMPS_CFLAGS" >&5 echo "$as_me: Mumps CFLAGS are $MUMPS_CFLAGS" >&6;} fi if test -n "$MUMPS_LIBS" ; then { echo "$as_me:$LINENO: Mumps LIBS are $MUMPS_LIBS" >&5 echo "$as_me: Mumps LIBS are $MUMPS_LIBS" >&6;} fi if test -n "$MUMPS_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Mumps DEPENDENCIES are $MUMPS_DEPENDENCIES" >&5 echo "$as_me: Mumps DEPENDENCIES are $MUMPS_DEPENDENCIES" >&6;} fi if test -n "$MUMPS_DATA" ; then { echo "$as_me:$LINENO: Mumps DATA is $MUMPS_DATA" >&5 echo "$as_me: Mumps DATA is $MUMPS_DATA" >&6;} fi if test -n "$MUMPS_PCLIBS" ; then { echo "$as_me:$LINENO: Mumps PCLIBS are $MUMPS_PCLIBS" >&5 echo "$as_me: Mumps PCLIBS are $MUMPS_PCLIBS" >&6;} fi if test -n "$MUMPS_PCREQUIRES" ; then { echo "$as_me:$LINENO: Mumps PCREQUIRES are $MUMPS_PCREQUIRES" >&5 echo "$as_me: Mumps PCREQUIRES are $MUMPS_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&5 echo "$as_me: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: ClpLib LIBS are $CLPLIB_LIBS" >&5 echo "$as_me: ClpLib LIBS are $CLPLIB_LIBS" >&6;} { echo "$as_me:$LINENO: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&5 echo "$as_me: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_mumps != notGiven && test $coin_has_mumps != skipping; then COIN_HAS_MUMPS_TRUE= COIN_HAS_MUMPS_FALSE='#' else COIN_HAS_MUMPS_TRUE='#' COIN_HAS_MUMPS_FALSE= fi # WSMP # Check whether --with-wsmp or --without-wsmp was given. if test "${with_wsmp+set}" = set; then withval="$with_wsmp" use_wsmp=$withval else use_wsmp=no fi; if test "$use_wsmp" != "no"; then # Check how to link against Fortran libraries from C case $build in *-cygwin* | *-mingw*) if test "$enable_msvc" = yes ; then coin_f77_comps="ifort fl32 compile_f2c gfortran g95 g77" else coin_f77_comps="gfortran ifort g95 g77 fl32 compile_f2c" fi ;; *-*-solaris*) coin_f77_comps="f95 f90 g95 f77 xlf_r fort77 gfortran g77 pgf90 pgf77 ifort ifc frt af77" ;; *-linux-gnu*) coin_f77_comps="gfortran ifort g95 fort77 f77 g77 pgf90 pgf77 ifc frt af77 xlf_r" ;; *) coin_f77_comps="xlf_r fort77 gfortran ifort g95 f77 g77 pgf90 pgf77 ifc frt af77" ;; esac 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 coin_has_f77=yes save_fflags="$FFLAGS" # We delete the cached value, since the test might not have been # performed with our choice of compilers earlier $as_unset ac_cv_prog_F77 || test "${ac_cv_prog_F77+set}" != set || { ac_cv_prog_F77=; export ac_cv_prog_F77; } # This is a real belt-and-suspenders approach. AC_COIN_FIND_F77 will use # coin_f77_comps to see if there's a program that matches one of the names. # If there's no such program, F77 = unavailable. If we match the name, # feed AC_PROG_F77 the same search list, just to be sure it's a functioning # compiler. # AC_MSG_NOTICE([Fortran compiler candidates: $coin_f77_comps]) { echo "$as_me:$LINENO: Trying to determine Fortran compiler name" >&5 echo "$as_me: Trying to determine Fortran compiler name" >&6;} if test -n "$ac_tool_prefix"; then for ac_prog in $coin_f77_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_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 $coin_f77_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_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 test -n "$ac_ct_F77" || ac_ct_F77="unavailable" F77=$ac_ct_F77 fi if test "$F77" != "unavailable" ; 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 if test -n "$ac_tool_prefix"; then for ac_prog in $coin_f77_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_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 $coin_f77_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_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:24903:" \ "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=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 else { echo "$as_me:$LINENO: WARNING: Failed to find a Fortran compiler!" >&5 echo "$as_me: WARNING: Failed to find a Fortran compiler!" >&2;} fi FFLAGS="$save_fflags" # Check if a project specific FFLAGS variable has been set if test x$COIN_PRJCT != x; then eval coin_tmp=\${${COIN_PRJCT}_FFLAGS+set} if test x$coin_tmp = xset; then eval FFLAGS=\${${COIN_PRJCT}_FFLAGS} fi fi if test "$F77" != "unavailable" && test x"$FFLAGS" = x ; then coin_add_fflags= coin_opt_fflags= coin_dbg_fflags= coin_warn_fflags= if test "$G77" = "yes"; then coin_opt_fflags="-O3" coin_add_fflags="-pipe" coin_dbg_fflags="-g -O0" else case $build in *-cygwin* | *-mingw*) case $F77 in ifort* | */ifort* | IFORT* | */IFORT* ) if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_fflags='-MD -O3' coin_dbg_fflags='-MDd -debug' else coin_opt_fflags='-MT -O3' coin_dbg_fflags='-MTd -debug' fi coin_add_fflags='-fpp -nologo' ;; compile_f2c*) if test "$coin_disable_shared" = yes || test "$enable_shared" = yes ; then coin_opt_fflags='-MD -O2' coin_dbg_fflags='-MDd' else coin_opt_fflags='-MT -O2' coin_dbg_fflags='-MTd' fi coin_add_fflags='-nologo -wd4996' ;; esac ;; *-linux-*) case $F77 in ifc* | */ifc* | ifort* | */ifort*) coin_opt_fflags="-O3 -ip" coin_add_fflags="-cm -w90 -w95" coin_dbg_fflags="-g -CA -CB -CS" # Check if -i_dynamic is necessary (for new glibc library) FFLAGS= cat >conftest.$ac_ext <<_ACEOF program main write(*,*) 'Hello world' 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 : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 coin_add_fflags="-i_dynamic $coin_add_fflags" fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; pgf77* | */pgf77* | pgf90* | */pgf90*) coin_opt_fflags="-fast" coin_add_fflags="-Kieee -pc 64" coin_dbg_fflags="-g" ;; esac ;; *-ibm-*) case "$F77" in xlf* | */xlf* | mpxlf* | */mpxlf* ) coin_opt_fflags="-O -qarch=auto -qcache=auto -qtune=auto -qmaxmem=-1" coin_add_fflags="-bmaxdata:0x80000000 -qsuppress=1500-036 -qsuppress=1500-029" coin_dbg_fflags="-g -C" ;; esac ;; *-hp-*) coin_opt_fflags="+O3" coin_add_fflags="+U77" coin_dbg_fflags="-C -g" ;; *-*-solaris*) coin_opt_fflags="-O4" coin_dbg_fflags="-g" ;; *-sgi-*) coin_opt_fflags="-O5 -OPT:Olimit=0" coin_dbg_fflags="-g" ;; esac fi if test "$ac_cv_prog_f77_g" = yes && test -z "$coin_dbg_fflags" ; then coin_dbg_fflags="-g" fi if test -z "$coin_opt_fflags"; then # Try if -O option works if nothing else is set FFLAGS=-O cat >conftest.$ac_ext <<_ACEOF program main integer i 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 coin_opt_fflags="-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_fflags" = xyes; then coin_warn_fflags= fi if test x${DBG_FFLAGS+set} != xset; then DBG_FFLAGS="$coin_dbg_fflags $coin_add_fflags $coin_warn_fflags" fi if test x${OPT_FFLAGS+set} != xset; then OPT_FFLAGS="$coin_opt_fflags $coin_add_fflags $coin_warn_fflags" fi DBG_FFLAGS="$DBG_FFLAGS $ADD_FFLAGS" OPT_FFLAGS="$OPT_FFLAGS $ADD_FFLAGS" if test "$coin_debug_compile" = "true"; then FFLAGS="$DBG_FFLAGS" else FFLAGS="$OPT_FFLAGS" fi else FFLAGS="$FFLAGS $ADD_FFLAGS" if test x${DBG_FFLAGS+set} != xset; then DBG_FFLAGS="$FFLAGS" fi if test x${OPT_FFLAGS+set} != xset; then OPT_FFLAGS="$FFLAGS" fi fi # Try if FFLAGS works if test "$F77" != "unavailable" ; then cat >conftest.$ac_ext <<_ACEOF program main integer i 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 : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 FFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$FFLAGS"; then { echo "$as_me:$LINENO: WARNING: The flags FFLAGS=\"$FFLAGS\" do not work. I will now just try '-O', but you might want to set FFLAGS manually." >&5 echo "$as_me: WARNING: The flags FFLAGS=\"$FFLAGS\" do not work. I will now just try '-O', but you might want to set FFLAGS manually." >&2;} FFLAGS='-O' cat >conftest.$ac_ext <<_ACEOF program main integer i 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 : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 FFLAGS= fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$FFLAGS"; then { echo "$as_me:$LINENO: WARNING: This value for FFLAGS does not work. I will continue with empty FFLAGS, but you might want to set FFLAGS manually." >&5 echo "$as_me: WARNING: This value for FFLAGS does not work. I will continue with empty FFLAGS, but you might want to set FFLAGS manually." >&2;} fi fi fi { echo "$as_me:$LINENO: Fortran compiler options are: $FFLAGS" >&5 echo "$as_me: Fortran compiler options are: $FFLAGS" >&6;} if test x"$MPIF77" = x; then :; else { echo "$as_me:$LINENO: Will use MPI Fortran compiler $MPIF77" >&5 echo "$as_me: Will use MPI Fortran compiler $MPIF77" >&6;} F77="$MPIF77" fi # correct the LD variable if we use the intel fortran compiler in windows case "$F77" in ifort* | */ifort* | IFORT* | */IFORT*) 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 # get FLIBS 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 echo "$as_me:$LINENO: checking how to get verbose linking output from $F77" >&5 echo $ECHO_N "checking how to get verbose linking output from $F77... $ECHO_C" >&6 if test "${ac_cv_prog_f77_v+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else 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_v= # Try some options frequently used verbose output for ac_verb in -v -verbose --verbose -V -\#\#\#; do cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF # Compile and link our simple test program by passing a flag (argument # 1 to this macro) to the Fortran compiler in order to get # "verbose" output that we can then parse for the Fortran linker # flags. ac_save_FFLAGS=$FFLAGS FFLAGS="$FFLAGS $ac_verb" (eval echo $as_me:25411: \"$ac_link\") >&5 ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'` echo "$ac_f77_v_output" >&5 FFLAGS=$ac_save_FFLAGS rm -f conftest* # On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where # /foo, /bar, and /baz are search directories for the Fortran linker. # Here, we change these into -L/foo -L/bar -L/baz (and put it first): ac_f77_v_output="`echo $ac_f77_v_output | grep 'LPATH is:' | sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output" case $ac_f77_v_output in # If we are using xlf then replace all the commas with spaces. *xlfentry*) ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;; # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted # $LIBS confuse us, and the libraries appear later in the output anyway). *mGLOB_options_string*) ac_f77_v_output=`echo $ac_f77_v_output | sed 's/\"-mGLOB[^\"]*\"/ /g'` ;; # If we are using Cray Fortran then delete quotes. # Use "\"" instead of '"' for font-lock-mode. # FIXME: a more general fix for quoted arguments with spaces? *cft90*) ac_f77_v_output=`echo $ac_f77_v_output | sed "s/\"//g"` ;; esac # look for -l* and *.a constructs in the output for ac_arg in $ac_f77_v_output; do case $ac_arg in [\\/]*.a | ?:[\\/]*.a | -[lLRu]*) ac_cv_prog_f77_v=$ac_verb break 2 ;; esac done done if test -z "$ac_cv_prog_f77_v"; then { echo "$as_me:$LINENO: WARNING: cannot determine how to obtain linking information from $F77" >&5 echo "$as_me: WARNING: cannot determine how to obtain linking information from $F77" >&2;} fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: WARNING: compilation failed" >&5 echo "$as_me: WARNING: compilation failed" >&2;} fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_f77_v" >&5 echo "${ECHO_T}$ac_cv_prog_f77_v" >&6 echo "$as_me:$LINENO: checking for Fortran libraries of $F77" >&5 echo $ECHO_N "checking for Fortran libraries of $F77... $ECHO_C" >&6 if test "${ac_cv_f77_libs+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "x$FLIBS" != "x"; then ac_cv_f77_libs="$FLIBS" # Let the user override the test. else cat >conftest.$ac_ext <<_ACEOF program main end _ACEOF # Compile and link our simple test program by passing a flag (argument # 1 to this macro) to the Fortran compiler in order to get # "verbose" output that we can then parse for the Fortran linker # flags. ac_save_FFLAGS=$FFLAGS FFLAGS="$FFLAGS $ac_cv_prog_f77_v" (eval echo $as_me:25489: \"$ac_link\") >&5 ac_f77_v_output=`eval $ac_link 5>&1 2>&1 | grep -v 'Driving:'` echo "$ac_f77_v_output" >&5 FFLAGS=$ac_save_FFLAGS rm -f conftest* # On HP/UX there is a line like: "LPATH is: /foo:/bar:/baz" where # /foo, /bar, and /baz are search directories for the Fortran linker. # Here, we change these into -L/foo -L/bar -L/baz (and put it first): ac_f77_v_output="`echo $ac_f77_v_output | grep 'LPATH is:' | sed 's,.*LPATH is\(: *[^ ]*\).*,\1,;s,: */, -L/,g'` $ac_f77_v_output" case $ac_f77_v_output in # If we are using xlf then replace all the commas with spaces. *xlfentry*) ac_f77_v_output=`echo $ac_f77_v_output | sed 's/,/ /g'` ;; # With Intel ifc, ignore the quoted -mGLOB_options_string stuff (quoted # $LIBS confuse us, and the libraries appear later in the output anyway). *mGLOB_options_string*) ac_f77_v_output=`echo $ac_f77_v_output | sed 's/\"-mGLOB[^\"]*\"/ /g'` ;; # If we are using Cray Fortran then delete quotes. # Use "\"" instead of '"' for font-lock-mode. # FIXME: a more general fix for quoted arguments with spaces? *cft90*) ac_f77_v_output=`echo $ac_f77_v_output | sed "s/\"//g"` ;; esac ac_cv_f77_libs= # Save positional arguments (if any) ac_save_positional="$@" set X $ac_f77_v_output while test $# != 1; do shift ac_arg=$1 case $ac_arg in [\\/]*.a | ?:[\\/]*.a) ac_exists=false for ac_i in $ac_cv_f77_libs; do if test x"$ac_arg" = x"$ac_i"; then ac_exists=true break fi done if test x"$ac_exists" = xtrue; then : else ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg" fi ;; -bI:*) ac_exists=false for ac_i in $ac_cv_f77_libs; do if test x"$ac_arg" = x"$ac_i"; then ac_exists=true break fi done if test x"$ac_exists" = xtrue; then : else if test "$ac_compiler_gnu" = yes; then for ac_link_opt in $ac_arg; do ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt" done else ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg" fi fi ;; # Ignore these flags. -lang* | -lcrt[01].o | -lcrtbegin.o | -lc | -lgcc | -libmil | -LANG:=*) ;; -lkernel32) test x"$CYGWIN" != xyes && ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg" ;; -[LRuY]) # These flags, when seen by themselves, take an argument. # We remove the space between option and argument and re-iterate # unless we find an empty arg or a new option (starting with -) case $2 in "" | -*);; *) ac_arg="$ac_arg$2" shift; shift set X $ac_arg "$@" ;; esac ;; -YP,*) for ac_j in `echo $ac_arg | sed -e 's/-YP,/-L/;s/:/ -L/g'`; do ac_exists=false for ac_i in $ac_cv_f77_libs; do if test x"$ac_j" = x"$ac_i"; then ac_exists=true break fi done if test x"$ac_exists" = xtrue; then : else ac_arg="$ac_arg $ac_j" ac_cv_f77_libs="$ac_cv_f77_libs $ac_j" fi done ;; -[lLR]*) ac_exists=false for ac_i in $ac_cv_f77_libs; do if test x"$ac_arg" = x"$ac_i"; then ac_exists=true break fi done if test x"$ac_exists" = xtrue; then : else ac_cv_f77_libs="$ac_cv_f77_libs $ac_arg" fi ;; # Ignore everything else. esac done # restore positional arguments set X $ac_save_positional; shift # We only consider "LD_RUN_PATH" on Solaris systems. If this is seen, # then we insist that the "run path" must be an absolute path (i.e. it # must begin with a "/"). case `(uname -sr) 2>/dev/null` in "SunOS 5"*) ac_ld_run_path=`echo $ac_f77_v_output | sed -n 's,^.*LD_RUN_PATH *= *\(/[^ ]*\).*$,-R\1,p'` test "x$ac_ld_run_path" != x && if test "$ac_compiler_gnu" = yes; then for ac_link_opt in $ac_ld_run_path; do ac_cv_f77_libs="$ac_cv_f77_libs -Xlinker $ac_link_opt" done else ac_cv_f77_libs="$ac_cv_f77_libs $ac_ld_run_path" fi ;; esac fi # test "x$[]_AC_LANG_PREFIX[]LIBS" = "x" fi echo "$as_me:$LINENO: result: $ac_cv_f77_libs" >&5 echo "${ECHO_T}$ac_cv_f77_libs" >&6 FLIBS="$ac_cv_f77_libs" 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 orig_FLIBS="$FLIBS" # If FLIBS has been set by the user, we just restore its value here if test x"$save_FLIBS" != x; then FLIBS="$save_FLIBS" else # This is to correct a missing exclusion in autoconf 2.59 if test x"$FLIBS" != x; then my_flibs= for flag in $FLIBS; do case $flag in -lcrt*.o) ;; -lcygwin) ;; -lgcc*) ;; *) my_flibs="$my_flibs $flag" ;; esac done FLIBS="$my_flibs" fi case $build in # The following is a fix to define FLIBS for ifort on Windows # In its original version, it linked in libifcorert.lib or libifcorertd.lib on Windows/ifort explicitly. # However, this seem to create a dependency on libifcorert.dll (or libifcorertd.dll) in the executables. # This is seem to be unnecessary, libifcorert(d).lib has been removed from the link line. # Further, excluding libc.lib from the default libs seemed to be necessary only for VS < 8. # Since the corresponding flag seems to make more trouble than it avoids, it has been removed now. *-cygwin* | *-mingw*) case "$F77" in # ifort* | */ifort* | IFORT* | */IFORT*) # FLIBS="-link $LIBS /NODEFAULTLIB:libc.lib" # if "$coin_debug_compile" = true ; then # FLIBS="-link $LIBS /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmt.lib" # else # FLIBS="-link $LIBS /NODEFAULTLIB:libc.lib /NODEFAULTLIB:libcmtd.lib" # fi # ;; compile_f2c*) FLIBS=`$F77 -FLIBS` ;; esac;; *-hp-*) FLIBS="$FLIBS -lm";; *-ibm-*) FLIBS=`echo $FLIBS | sed 's/-lc)/-lc/g'` ;; *-linux-*) case "$F77" in pgf77* | */pgf77* | pgf90* | */pgf90*) # ask linker to go through the archives multiple times # (the Fortran compiler seems to do that automatically...) FLIBS="-Wl,--start-group $FLIBS -Wl,--end-group" ;; esac esac ac_cv_f77_libs="$FLIBS" fi if test "x$orig_FLIBS" != "x$FLIBS" ; then { echo "$as_me:$LINENO: Corrected Fortran libraries: $FLIBS" >&5 echo "$as_me: Corrected Fortran libraries: $FLIBS" >&6;} 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 echo "$as_me:$LINENO: checking for dummy main to link with Fortran libraries" >&5 echo $ECHO_N "checking for dummy main to link with Fortran libraries... $ECHO_C" >&6 if test "${ac_cv_f77_dummy_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_f77_dm_save_LIBS=$LIBS LIBS="$LIBS $FLIBS" ac_fortran_dm_var=F77_DUMMY_MAIN 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 # First, try linking without a dummy main: cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif 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 ac_cv_fortran_dummy_main=none else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_fortran_dummy_main=unknown fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test $ac_cv_fortran_dummy_main = unknown; then for ac_func in MAIN__ MAIN_ __main MAIN _MAIN __MAIN main_ main__ _main; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define $ac_fortran_dm_var $ac_func #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif 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 ac_cv_fortran_dummy_main=$ac_func; 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 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 ac_cv_f77_dummy_main=$ac_cv_fortran_dummy_main rm -f conftest* LIBS=$ac_f77_dm_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_f77_dummy_main" >&5 echo "${ECHO_T}$ac_cv_f77_dummy_main" >&6 F77_DUMMY_MAIN=$ac_cv_f77_dummy_main if test "$F77_DUMMY_MAIN" != unknown; then if test $F77_DUMMY_MAIN != none; then cat >>confdefs.h <<_ACEOF #define F77_DUMMY_MAIN $F77_DUMMY_MAIN _ACEOF if test "x$ac_cv_fc_dummy_main" = "x$ac_cv_f77_dummy_main"; then cat >>confdefs.h <<\_ACEOF #define FC_DUMMY_MAIN_EQ_F77 1 _ACEOF fi fi else { { echo "$as_me:$LINENO: error: linking to Fortran libraries from C fails See \`config.log' for more details." >&5 echo "$as_me: error: linking to Fortran libraries from C fails See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } 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 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 echo "$as_me:$LINENO: checking for Fortran name-mangling scheme" >&5 echo $ECHO_N "checking for Fortran name-mangling scheme... $ECHO_C" >&6 if test "${ac_cv_f77_mangling+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF subroutine foobar() return end subroutine foo_bar() return 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 mv conftest.$ac_objext cfortran_test.$ac_objext ac_save_LIBS=$LIBS LIBS="cfortran_test.$ac_objext $LIBS $FLIBS" 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_success=no for ac_foobar in foobar FOOBAR; do for ac_underscore in "" "_"; do ac_func="$ac_foobar$ac_underscore" 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 $ac_func (); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $ac_func (); ; 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_success=yes; break 2 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 done 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 "$ac_success" = "yes"; then case $ac_foobar in foobar) ac_case=lower ac_foo_bar=foo_bar ;; FOOBAR) ac_case=upper ac_foo_bar=FOO_BAR ;; 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 ac_success_extra=no for ac_extra in "" "_"; do ac_func="$ac_foo_bar$ac_underscore$ac_extra" 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 $ac_func (); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $ac_func (); ; 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_success_extra=yes; 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 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 "$ac_success_extra" = "yes"; then ac_cv_f77_mangling="$ac_case case" if test -z "$ac_underscore"; then ac_cv_f77_mangling="$ac_cv_f77_mangling, no underscore" else ac_cv_f77_mangling="$ac_cv_f77_mangling, underscore" fi if test -z "$ac_extra"; then ac_cv_f77_mangling="$ac_cv_f77_mangling, no extra underscore" else ac_cv_f77_mangling="$ac_cv_f77_mangling, extra underscore" fi else ac_cv_f77_mangling="unknown" fi else ac_cv_f77_mangling="unknown" fi LIBS=$ac_save_LIBS rm -f cfortran_test* conftest* else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compile a simple Fortran program See \`config.log' for more details." >&5 echo "$as_me: error: cannot compile a simple Fortran program See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_f77_mangling" >&5 echo "${ECHO_T}$ac_cv_f77_mangling" >&6 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 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 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 case $ac_cv_f77_mangling in "lower case, no underscore, no extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) name _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) name _ACEOF ;; "lower case, no underscore, extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) name _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) name ## _ _ACEOF ;; "lower case, underscore, no extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) name ## _ _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) name ## _ _ACEOF ;; "lower case, underscore, extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) name ## _ _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) name ## __ _ACEOF ;; "upper case, no underscore, no extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) NAME _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) NAME _ACEOF ;; "upper case, no underscore, extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) NAME _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) NAME ## _ _ACEOF ;; "upper case, underscore, no extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) NAME ## _ _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) NAME ## _ _ACEOF ;; "upper case, underscore, extra underscore") cat >>confdefs.h <<\_ACEOF #define F77_FUNC(name,NAME) NAME ## _ _ACEOF cat >>confdefs.h <<\_ACEOF #define F77_FUNC_(name,NAME) NAME ## __ _ACEOF ;; *) { echo "$as_me:$LINENO: WARNING: unknown Fortran name-mangling scheme" >&5 echo "$as_me: WARNING: unknown Fortran name-mangling scheme" >&2;} ;; esac 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 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 # WSMP requires Blas # Check whether --with-blas or --without-blas was given. if test "${with_blas+set}" = set; then withval="$with_blas" use_blas="$withval" else use_blas= fi; # if user specified --with-blas-lib, then we should give COIN_CHECK_PACKAGE # preference # Check whether --with-blas-lib or --without-blas-lib was given. if test "${with_blas_lib+set}" = set; then withval="$with_blas_lib" use_blas=BUILD fi; # Check if user supplied option makes sense if test x"$use_blas" != x; then if test "$use_blas" = "BUILD"; then # we come to this later : elif test "$use_blas" != "no"; then echo "$as_me:$LINENO: checking whether user supplied BLASLIB=\"$use_blas\" works" >&5 echo $ECHO_N "checking whether user supplied BLASLIB=\"$use_blas\" works... $ECHO_C" >&6 coin_need_flibs=no coin_save_LIBS="$LIBS" LIBS="$use_blas $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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: user supplied BLAS library \"$use_blas\" does not work" >&5 echo "$as_me: error: user supplied BLAS library \"$use_blas\" does not work" >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: user supplied BLAS library \"$use_blas\" does not work" >&5 echo "$as_me: error: user supplied BLAS library \"$use_blas\" does not work" >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: user supplied BLAS library \"$use_blas\" does not work" >&5 echo "$as_me: error: user supplied BLAS library \"$use_blas\" does not work" >&2;} { (exit 1); exit 1; }; } fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: user supplied BLAS library \"$use_blas\" does not work" >&5 echo "$as_me: error: user supplied BLAS library \"$use_blas\" does not work" >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 { { echo "$as_me:$LINENO: error: user supplied BLAS library \"$use_blas\" does not work" >&5 echo "$as_me: error: user supplied BLAS library \"$use_blas\" does not work" >&2;} { (exit 1); exit 1; }; } fi fi ;; esac LIBS="$coin_save_LIBS" fi else # Try to autodetect the library for blas based on build system #AC_MSG_CHECKING([default locations for BLAS]) case $build in *-sgi-*) echo "$as_me:$LINENO: checking whether -lcomplib.sgimath has BLAS" >&5 echo $ECHO_N "checking whether -lcomplib.sgimath has BLAS... $ECHO_C" >&6 coin_need_flibs=no coin_save_LIBS="$LIBS" LIBS="-lcomplib.sgimath $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas="-lcomplib.sgimath" if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas="-lcomplib.sgimath" if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas="-lcomplib.sgimath" if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas="-lcomplib.sgimath" if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas="-lcomplib.sgimath" if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" ;; # Ideally, we'd use -library=sunperf, but it's an imperfect world. Studio # cc doesn't recognise -library, it wants -xlic_lib. Studio 12 CC doesn't # recognise -xlic_lib. Libtool doesn't like -xlic_lib anyway. Sun claims # that CC and cc will understand -library in Studio 13. The main extra # function of -xlic_lib and -library is to arrange for the Fortran run-time # libraries to be linked for C++ and C. We can arrange that explicitly. *-*-solaris*) echo "$as_me:$LINENO: checking for BLAS in libsunperf" >&5 echo $ECHO_N "checking for BLAS in libsunperf... $ECHO_C" >&6 coin_need_flibs=no coin_save_LIBS="$LIBS" LIBS="-lsunperf $FLIBS $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas='-lsunperf' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-lsunperf' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-lsunperf' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-lsunperf' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-lsunperf' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" ;; *-cygwin* | *-mingw*) case "$CC" in clang* ) ;; cl* | */cl* | CL* | */CL* | icl* | */icl* | ICL* | */ICL*) coin_save_LIBS="$LIBS" echo "$as_me:$LINENO: checking for BLAS in MKL (32bit)" >&5 echo $ECHO_N "checking for BLAS in MKL (32bit)... $ECHO_C" >&6 LIBS="mkl_intel_c.lib mkl_sequential.lib mkl_core.lib $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas='mkl_intel_c.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='mkl_intel_c.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='mkl_intel_c.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='mkl_intel_c.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='mkl_intel_c.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" if test "x$use_blas" = x ; then echo "$as_me:$LINENO: checking for BLAS in MKL (64bit)" >&5 echo $ECHO_N "checking for BLAS in MKL (64bit)... $ECHO_C" >&6 LIBS="mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas='mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='mkl_intel_lp64.lib mkl_sequential.lib mkl_core.lib' echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" fi ;; esac ;; *-darwin*) echo "$as_me:$LINENO: checking for BLAS in Veclib" >&5 echo $ECHO_N "checking for BLAS in Veclib... $ECHO_C" >&6 coin_need_flibs=no coin_save_LIBS="$LIBS" LIBS="-framework vecLib $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas='-framework vecLib' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-framework vecLib' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-framework vecLib' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-framework vecLib' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-framework vecLib' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" ;; esac if test -z "$use_blas" ; then echo "$as_me:$LINENO: checking whether -lblas has BLAS" >&5 echo $ECHO_N "checking whether -lblas has BLAS... $ECHO_C" >&6 coin_need_flibs=no coin_save_LIBS="$LIBS" LIBS="-lblas $LIBS" case $ac_ext in f) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { call daxpy ; 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 use_blas='-lblas' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&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 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; c) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-lblas' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ void $cfuncdaxpy(); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-lblas' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; cc|cpp) 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 case $ac_cv_f77_mangling in upper*) ac_val="DAXPY" ;; lower*) ac_val="daxpy" ;; *) ac_val="unknown" ;; esac case $ac_cv_f77_mangling in *," underscore"*) ac_val="$ac_val"_ ;; esac cfuncdaxpy="$ac_val" 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 x"$coin_need_flibs" = xyes; then flink_try=no; else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 flink_try=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 flink_try=no fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test $flink_try = yes; then use_blas='-lblas' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else if test x"$FLIBS" != x; then flink_save_libs="$LIBS" LIBS="$LIBS $FLIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ extern "C" {void $cfuncdaxpy();} #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif int main () { $cfuncdaxpy() ; 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 LIBS="$flink_save_libs" coin_need_flibs=yes use_blas='-lblas' if test $coin_need_flibs = yes ; then use_blas="$use_blas $FLIBS" fi echo "$as_me:$LINENO: result: yes: $use_blas" >&5 echo "${ECHO_T}yes: $use_blas" >&6 else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$flink_save_libs" echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi fi ;; esac LIBS="$coin_save_LIBS" fi # If we have no other ideas, consider building BLAS. if test -z "$use_blas" ; then use_blas=BUILD fi fi if test "x$use_blas" = xBUILD ; then echo "$as_me:$LINENO: checking for COIN-OR package Blas" >&5 echo $ECHO_N "checking for COIN-OR package Blas... $ECHO_C" >&6 coin_has_blas=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 = "Blas"; then coin_has_blas=skipping fi done fi if test "$coin_has_blas" != skipping; then # Check whether --with-m4_tolower(Blas) or --without-m4_tolower(Blas) was given. if test "${with_blas+set}" = set; then withval="$with_blas" if test "$withval" = no ; then coin_has_blas=skipping fi fi; fi BLAS_LIBS= BLAS_CFLAGS= BLAS_DATA= BLAS_DEPENDENCIES= BLAS_PCLIBS= BLAS_PCREQUIRES= #check if user provided LIBS, CFLAGS, or DATA for package or disables use of package if test $coin_has_blas != skipping; then # Check whether --with-m4_tolower(Blas)-lib or --without-m4_tolower(Blas)-lib was given. if test "${with_blas_lib+set}" = set; then withval="$with_blas_lib" if test "$withval" = no ; then coin_has_blas=skipping else coin_has_blas=yes BLAS_LIBS="$withval" BLAS_PCLIBS="$withval" CLPLIB_PCLIBS="$withval $CLPLIB_PCLIBS" CLPLIB_LIBS="$withval $CLPLIB_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 BLAS_LIBS_INSTALLED="$withval" CLPLIB_LIBS_INSTALLED="$withval $CLPLIB_LIBS_INSTALLED" fi fi fi; fi if test $coin_has_blas != skipping; then # Check whether --with-m4_tolower(Blas)-incdir or --without-m4_tolower(Blas)-incdir was given. if test "${with_blas_incdir+set}" = set; then withval="$with_blas_incdir" if test "$withval" = no ; then coin_has_blas=skipping else coin_has_blas=yes BLAS_CFLAGS="-I`${CYGPATH_W} $withval`" CLPLIB_CFLAGS="-I`${CYGPATH_W} $withval` $CLPLIB_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 BLAS_CFLAGS_INSTALLED="$BLAS_CFLAGS" CLPLIB_CFLAGS_INSTALLED="$BLAS_CFLAGS $CLPLIB_CFLAGS_INSTALLED" fi fi fi; fi if test $coin_has_blas != skipping; then # Check whether --with-m4_tolower(Blas)-datadir or --without-m4_tolower(Blas)-datadir was given. if test "${with_blas_datadir+set}" = set; then withval="$with_blas_datadir" if test "$withval" = no ; then coin_has_blas=skipping else coin_has_blas=yes BLAS_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 BLAS_DATA_INSTALLED="$withval" fi fi fi; fi if test $coin_has_blas = 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 "coinblas"; then BLAS_VERSIONS=`$PKG_CONFIG --modversion "coinblas" 2>/dev/null | tr '\n' ' '` cflags=`$PKG_CONFIG --cflags "coinblas" 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 BLAS_CFLAGS="$cflags" BLAS_LIBS=`$PKG_CONFIG --libs "coinblas" 2>/dev/null` BLAS_DATA=`$PKG_CONFIG --variable=datadir "coinblas" 2>/dev/null` coin_has_blas=yes echo "$as_me:$LINENO: result: yes: $BLAS_VERSIONS" >&5 echo "${ECHO_T}yes: $BLAS_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 BLAS_LIBS=`echo " $BLAS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` fi BLAS_PCREQUIRES="coinblas" # augment X_PCREQUIRES, X_CFLAGS, and X_LIBS for each build target X in ClpLib CLPLIB_PCREQUIRES="coinblas $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$BLAS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$BLAS_LIBS $CLPLIB_LIBS" else BLAS_PKG_ERRORS=`$PKG_CONFIG $pkg_short_errors --errors-to-stdout --print-errors "coinblas"` coin_has_blas=notGiven echo "$as_me:$LINENO: result: not given: $BLAS_PKG_ERRORS" >&5 echo "${ECHO_T}not given: $BLAS_PKG_ERRORS" >&6 fi else { { echo "$as_me:$LINENO: error: \"Cannot check for existance of module Blas without pkg-config\"" >&5 echo "$as_me: error: \"Cannot check for existance of module Blas 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 Blas (fallback)" >&5 echo $ECHO_N "checking for COIN-OR package Blas (fallback)... $ECHO_C" >&6 coin_has_blas=notGiven BLAS_LIBS= BLAS_LIBS_INSTALLED= BLAS_CFLAGS= BLAS_CFLAGS_INSTALLED= BLAS_DATA= BLAS_DATA_INSTALLED= BLAS_PCLIBS= BLAS_PCREQUIRES= # initial list of dependencies is "coinblas", but we need to filter out version number specifications (= x, <= x, >= x, != x) projtoprocess="coinblas" # 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$BLAS_DATA" = x ; then projdatadir= pcfilemod=`sed -e '/[a-zA-Z]:/d' -e 's/datadir=\(.*\)/echo projdatadir=\\\\"\1\\\\"/g' $pcfile` eval `sh -c "$pcfilemod"` BLAS_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$BLAS_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 BLAS_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 BLAS_CFLAGS="$projcflags $BLAS_CFLAGS" # set LIBS variable BLAS_LIBS="$projlibs $BLAS_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 BLAS_CFLAGS_INSTALLED="$projcflags $BLAS_CFLAGS_INSTALLED" # set LIBS variable BLAS_LIBS_INSTALLED="$projlibs $BLAS_LIBS_INSTALLED" # remember that we have processed $pcfile pcfilesprocessed="$pcfilesprocessed:$pcfile" done IFS="$save_IFS" # finish up coin_has_blas=yes echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define COIN_HAS_BLAS 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 BLAS_LIBS=`echo " $BLAS_LIBS " | sed -e 's/ \(\/[^ ]*\/\)\([^ ]*\)\.lib / \`$(CYGPATH_W) \1 | sed -e "s|\\\\\\\\\\\\\\\\\\\\|\/|g"\`\2.lib /g'` BLAS_LIBS_INSTALLED=`echo " $BLAS_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 BLAS_PCREQUIRES="coinblas" CLPLIB_PCREQUIRES="coinblas $CLPLIB_PCREQUIRES" CLPLIB_CFLAGS="$BLAS_CFLAGS $CLPLIB_CFLAGS" CLPLIB_LIBS="$BLAS_LIBS $CLPLIB_LIBS" CLPLIB_CFLAGS_INSTALLED="$BLAS_CFLAGS_INSTALLED $CLPLIB_CFLAGS_INSTALLED" CLPLIB_LIBS_INSTALLED="$BLAS_LIBS_INSTALLED $CLPLIB_LIBS_INSTALLED" fi if test $coin_has_blas != notGiven && test $coin_has_blas != skipping; then COIN_HAS_BLAS_TRUE= COIN_HAS_BLAS_FALSE='#' else COIN_HAS_BLAS_TRUE='#' COIN_HAS_BLAS_FALSE= fi fi else echo "$as_me:$LINENO: result: $coin_has_blas" >&5 echo "${ECHO_T}$coin_has_blas" >&6 fi if test $coin_has_blas != skipping && test $coin_has_blas != notGiven ; then cat >>confdefs.h <<\_ACEOF #define COIN_HAS_BLAS 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) BLAS_DEPENDENCIES=`echo " $BLAS_LIBS" | sed -e 's/ mkl[^ ]*//g' -e 's/ libiomp5[^ ]*//g' -e 's/ wsock32[^ ]*//g' -e 's/ -framework *[^ ]*//g' -e 's/ -[^ ]*//g' -e 's/\`[^\`]*\`[^ ]* //g'` CLPLIB_DEPENDENCIES=`echo " $CLPLIB_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 "$BLAS_CFLAGS" ; then { echo "$as_me:$LINENO: Blas CFLAGS are $BLAS_CFLAGS" >&5 echo "$as_me: Blas CFLAGS are $BLAS_CFLAGS" >&6;} fi if test -n "$BLAS_LIBS" ; then { echo "$as_me:$LINENO: Blas LIBS are $BLAS_LIBS" >&5 echo "$as_me: Blas LIBS are $BLAS_LIBS" >&6;} fi if test -n "$BLAS_DEPENDENCIES" ; then { echo "$as_me:$LINENO: Blas DEPENDENCIES are $BLAS_DEPENDENCIES" >&5 echo "$as_me: Blas DEPENDENCIES are $BLAS_DEPENDENCIES" >&6;} fi if test -n "$BLAS_DATA" ; then { echo "$as_me:$LINENO: Blas DATA is $BLAS_DATA" >&5 echo "$as_me: Blas DATA is $BLAS_DATA" >&6;} fi if test -n "$BLAS_PCLIBS" ; then { echo "$as_me:$LINENO: Blas PCLIBS are $BLAS_PCLIBS" >&5 echo "$as_me: Blas PCLIBS are $BLAS_PCLIBS" >&6;} fi if test -n "$BLAS_PCREQUIRES" ; then { echo "$as_me:$LINENO: Blas PCREQUIRES are $BLAS_PCREQUIRES" >&5 echo "$as_me: Blas PCREQUIRES are $BLAS_PCREQUIRES" >&6;} fi { echo "$as_me:$LINENO: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&5 echo "$as_me: ClpLib CFLAGS are $CLPLIB_CFLAGS" >&6;} { echo "$as_me:$LINENO: ClpLib LIBS are $CLPLIB_LIBS" >&5 echo "$as_me: ClpLib LIBS are $CLPLIB_LIBS" >&6;} { echo "$as_me:$LINENO: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&5 echo "$as_me: ClpLib DEPENDENCIES are $CLPLIB_DEPENDENCIES" >&6;} fi fi # Define the Makefile conditional if test $coin_has_blas != notGiven && test $coin_has_blas != skipping; then COIN_HAS_BLAS_TRUE= COIN_HAS_BLAS_FALSE='#' else COIN_HAS_BLAS_TRUE='#' COIN_HAS_BLAS_FALSE= fi elif test "x$use_blas" != x && test "$use_blas" != no; then coin_has_blas=yes if test 0 = 0; then COIN_HAS_BLAS_TRUE= COIN_HAS_BLAS_FALSE='#' else COIN_HAS_BLAS_TRUE='#' COIN_HAS_BLAS_FALSE= fi cat >>confdefs.h <<\_ACEOF #define COIN_HAS_BLAS 1 _ACEOF BLAS_LIBS="$use_blas" BLAS_CFLAGS= BLAS_DATA= CLPLIB_PCLIBS="$BLAS_LIBS $CLPLIB_PCLIBS" CLPLIB_LIBS="$BLAS_LIBS $CLPLIB_LIBS" CLPLIB_LIBS_INSTALLED="$BLAS_LIBS $CLPLIB_LIBS_INSTALLED" else coin_has_blas=no if test 0 = 1; then COIN_HAS_BLAS_TRUE= COIN_HAS_BLAS_FALSE='#' else COIN_HAS_BLAS_TRUE='#' COIN_HAS_BLAS_FALSE= fi fi coin_save_LIBS="$LIBS" LIBS="$LIBS $use_wsmp $BLAS_LIBS" 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 echo "$as_me:$LINENO: checking whether user-supplied WSMP library \"$use_wsmp\" works" >&5 echo $ECHO_N "checking whether user-supplied WSMP library \"$use_wsmp\" works... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF program main call WSSMP() 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 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: WSMP library $use_wsmp does not seem to work" >&5 echo "$as_me: error: WSMP library $use_wsmp does not seem to work" >&2;} { (exit 1); exit 1; }; } 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 LIBS="$coin_save_LIBS" cat >>confdefs.h <<_ACEOF #define COIN_HAS_WSMP 1 _ACEOF CLPLIB_LIBS="$use_wsmp $CLPLIB_LIBS" CLPLIB_LIBS_INSTALLED="$use_wsmp $CLPLIB_LIBS_INSTALLED" CLPLIB_PCLIBS="$use_wsmp $CLPLIB_PCLIBS" else # to please configure if test 0 = 1; then COIN_HAS_BLAS_TRUE= COIN_HAS_BLAS_FALSE='#' else COIN_HAS_BLAS_TRUE='#' COIN_HAS_BLAS_FALSE= fi fi if test "$use_wsmp" != no; then COIN_HAS_WSMP_TRUE= COIN_HAS_WSMP_FALSE='#' else COIN_HAS_WSMP_TRUE='#' COIN_HAS_WSMP_FALSE= fi ############################################################################# # Other dependencies # ############################################################################# # 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 (); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif 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 (); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif 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 (); #ifdef F77_DUMMY_MAIN # ifdef __cplusplus extern "C" # endif int F77_DUMMY_MAIN() { return 1; } #endif 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 CLPLIB_LIBS="-lreadline $LIBS $CLPLIB_LIBS" CLPLIB_PCLIBS="-lreadline $LIBS $CLPLIB_PCLIBS" CLPLIB_LIBS_INSTALLED="-lreadline $LIBS $CLPLIB_LIBS_INSTALLED" cat >>confdefs.h <<\_ACEOF #define COIN_HAS_READLINE 1 _ACEOF fi LIBS="$coin_save_LIBS" 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 #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 clp@list.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 clp@list.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 clp@list.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 clp@list.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 clp@list.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 clp@list.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 ############################################################################## # 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/hello.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/input.130" 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/g.tiny" 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/gparm.tiny" 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" 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/OsiClp/Makefile test/Makefile clp.pc clp-uninstalled.pc" if test $coin_has_osi = yes ; then ac_config_files="$ac_config_files osi-clp.pc:src/OsiClp/osi-clp.pc.in osi-clp-uninstalled.pc:src/OsiClp/osi-clp-uninstalled.pc.in" fi 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_clp.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_COINUTILS_TRUE}" && test -z "${COIN_HAS_COINUTILS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_COINUTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_COINUTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_COINUTILS_TRUE}" && test -z "${COIN_HAS_COINUTILS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_COINUTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_COINUTILS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_OSI_TRUE}" && test -z "${COIN_HAS_OSI_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_OSI\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_OSI\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_OSI_TRUE}" && test -z "${COIN_HAS_OSI_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_OSI\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_OSI\" 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_ABC_TRUE}" && test -z "${COIN_HAS_ABC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_ABC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_ABC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_AMD_TRUE}" && test -z "${COIN_HAS_AMD_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_AMD\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_AMD\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_CHOLMOD_TRUE}" && test -z "${COIN_HAS_CHOLMOD_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_CHOLMOD\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_CHOLMOD\" 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_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_MUMPS_TRUE}" && test -z "${COIN_HAS_MUMPS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MUMPS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MUMPS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_MUMPS_TRUE}" && test -z "${COIN_HAS_MUMPS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_MUMPS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_MUMPS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_BLAS_TRUE}" && test -z "${COIN_HAS_BLAS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_BLAS_TRUE}" && test -z "${COIN_HAS_BLAS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_BLAS_TRUE}" && test -z "${COIN_HAS_BLAS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_BLAS_TRUE}" && test -z "${COIN_HAS_BLAS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_BLAS_TRUE}" && test -z "${COIN_HAS_BLAS_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_BLAS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${COIN_HAS_WSMP_TRUE}" && test -z "${COIN_HAS_WSMP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"COIN_HAS_WSMP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"COIN_HAS_WSMP\" 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 Clp $as_me 1.15.10, 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="\\ Clp config.status 1.15.10 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/OsiClp/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/OsiClp/Makefile" ;; "test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "clp.pc" ) CONFIG_FILES="$CONFIG_FILES clp.pc" ;; "clp-uninstalled.pc" ) CONFIG_FILES="$CONFIG_FILES clp-uninstalled.pc" ;; "osi-clp.pc" ) CONFIG_FILES="$CONFIG_FILES osi-clp.pc:src/OsiClp/osi-clp.pc.in" ;; "osi-clp-uninstalled.pc" ) CONFIG_FILES="$CONFIG_FILES osi-clp-uninstalled.pc:src/OsiClp/osi-clp-uninstalled.pc.in" ;; "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_clp.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/config_clp.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,@CLP_SVN_REV@,$CLP_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,@COINUTILS_LIBS@,$COINUTILS_LIBS,;t t s,@COINUTILS_CFLAGS@,$COINUTILS_CFLAGS,;t t s,@COINUTILS_DATA@,$COINUTILS_DATA,;t t s,@COINUTILS_DEPENDENCIES@,$COINUTILS_DEPENDENCIES,;t t s,@COINUTILS_LIBS_INSTALLED@,$COINUTILS_LIBS_INSTALLED,;t t s,@COINUTILS_CFLAGS_INSTALLED@,$COINUTILS_CFLAGS_INSTALLED,;t t s,@COINUTILS_DATA_INSTALLED@,$COINUTILS_DATA_INSTALLED,;t t s,@CLPLIB_CFLAGS@,$CLPLIB_CFLAGS,;t t s,@CLPLIB_LIBS@,$CLPLIB_LIBS,;t t s,@CLPLIB_PCLIBS@,$CLPLIB_PCLIBS,;t t s,@CLPLIB_PCREQUIRES@,$CLPLIB_PCREQUIRES,;t t s,@CLPLIB_DEPENDENCIES@,$CLPLIB_DEPENDENCIES,;t t s,@CLPLIB_CFLAGS_INSTALLED@,$CLPLIB_CFLAGS_INSTALLED,;t t s,@CLPLIB_LIBS_INSTALLED@,$CLPLIB_LIBS_INSTALLED,;t t s,@COIN_HAS_COINUTILS_TRUE@,$COIN_HAS_COINUTILS_TRUE,;t t s,@COIN_HAS_COINUTILS_FALSE@,$COIN_HAS_COINUTILS_FALSE,;t t s,@OSI_LIBS@,$OSI_LIBS,;t t s,@OSI_CFLAGS@,$OSI_CFLAGS,;t t s,@OSI_DATA@,$OSI_DATA,;t t s,@OSI_DEPENDENCIES@,$OSI_DEPENDENCIES,;t t s,@OSI_LIBS_INSTALLED@,$OSI_LIBS_INSTALLED,;t t s,@OSI_CFLAGS_INSTALLED@,$OSI_CFLAGS_INSTALLED,;t t s,@OSI_DATA_INSTALLED@,$OSI_DATA_INSTALLED,;t t s,@OSICLPLIB_CFLAGS@,$OSICLPLIB_CFLAGS,;t t s,@OSICLPLIB_LIBS@,$OSICLPLIB_LIBS,;t t s,@OSICLPLIB_PCLIBS@,$OSICLPLIB_PCLIBS,;t t s,@OSICLPLIB_PCREQUIRES@,$OSICLPLIB_PCREQUIRES,;t t s,@OSICLPLIB_DEPENDENCIES@,$OSICLPLIB_DEPENDENCIES,;t t s,@OSICLPLIB_CFLAGS_INSTALLED@,$OSICLPLIB_CFLAGS_INSTALLED,;t t s,@OSICLPLIB_LIBS_INSTALLED@,$OSICLPLIB_LIBS_INSTALLED,;t t s,@COIN_HAS_OSI_TRUE@,$COIN_HAS_OSI_TRUE,;t t s,@COIN_HAS_OSI_FALSE@,$COIN_HAS_OSI_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,@COIN_HAS_ABC_TRUE@,$COIN_HAS_ABC_TRUE,;t t s,@COIN_HAS_ABC_FALSE@,$COIN_HAS_ABC_FALSE,;t t s,@AMDINCDIR@,$AMDINCDIR,;t t s,@AMDLIB@,$AMDLIB,;t t s,@COIN_HAS_AMD_TRUE@,$COIN_HAS_AMD_TRUE,;t t s,@COIN_HAS_AMD_FALSE@,$COIN_HAS_AMD_FALSE,;t t s,@CHOLMODINCDIR@,$CHOLMODINCDIR,;t t s,@CHOLMODLIB@,$CHOLMODLIB,;t t s,@COIN_HAS_CHOLMOD_TRUE@,$COIN_HAS_CHOLMOD_TRUE,;t t s,@COIN_HAS_CHOLMOD_FALSE@,$COIN_HAS_CHOLMOD_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,@MUMPS_LIBS@,$MUMPS_LIBS,;t t s,@MUMPS_CFLAGS@,$MUMPS_CFLAGS,;t t s,@MUMPS_DATA@,$MUMPS_DATA,;t t s,@MUMPS_DEPENDENCIES@,$MUMPS_DEPENDENCIES,;t t s,@MUMPS_LIBS_INSTALLED@,$MUMPS_LIBS_INSTALLED,;t t s,@MUMPS_CFLAGS_INSTALLED@,$MUMPS_CFLAGS_INSTALLED,;t t s,@MUMPS_DATA_INSTALLED@,$MUMPS_DATA_INSTALLED,;t t s,@COIN_HAS_MUMPS_TRUE@,$COIN_HAS_MUMPS_TRUE,;t t s,@COIN_HAS_MUMPS_FALSE@,$COIN_HAS_MUMPS_FALSE,;t t s,@ADD_FFLAGS@,$ADD_FFLAGS,;t t s,@DBG_FFLAGS@,$DBG_FFLAGS,;t t s,@OPT_FFLAGS@,$OPT_FFLAGS,;t t s,@MPIF77@,$MPIF77,;t t s,@FLIBS@,$FLIBS,;t t s,@BLAS_LIBS@,$BLAS_LIBS,;t t s,@BLAS_CFLAGS@,$BLAS_CFLAGS,;t t s,@BLAS_DATA@,$BLAS_DATA,;t t s,@BLAS_DEPENDENCIES@,$BLAS_DEPENDENCIES,;t t s,@BLAS_LIBS_INSTALLED@,$BLAS_LIBS_INSTALLED,;t t s,@BLAS_CFLAGS_INSTALLED@,$BLAS_CFLAGS_INSTALLED,;t t s,@BLAS_DATA_INSTALLED@,$BLAS_DATA_INSTALLED,;t t s,@COIN_HAS_BLAS_TRUE@,$COIN_HAS_BLAS_TRUE,;t t s,@COIN_HAS_BLAS_FALSE@,$COIN_HAS_BLAS_FALSE,;t t s,@COIN_HAS_WSMP_TRUE@,$COIN_HAS_WSMP_TRUE,;t t s,@COIN_HAS_WSMP_FALSE@,$COIN_HAS_WSMP_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 Clp-1.15.10/clp-uninstalled.pc.in0000644000076600007660000000043711573730475015122 0ustar coincoinprefix=@prefix@ libdir=@ABSBUILDDIR@/src Name: CLP Description: COIN-OR Linear Programming Solver URL: https://projects.coin-or.org/Clp Version: @PACKAGE_VERSION@ Libs: ${libdir}/libClp.la @CLPLIB_PCLIBS@ Cflags: -I@abs_source_dir@/src -I@ABSBUILDDIR@/src Requires: @CLPLIB_PCREQUIRES@ Clp-1.15.10/config.guess0000755000076600007660000012706311405215425013403 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: